diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 0fe754bb071ea3..25cc726504b376 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -1,14 +1,14 @@ variables: coverage: false -trigger: ['master', '3.9', '3.8', '3.7'] +trigger: ['main', '3.10', '3.9', '3.8', '3.7'] jobs: - job: Prebuild displayName: Pre-build checks pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 steps: - template: ./prebuild-checks.yml @@ -20,7 +20,7 @@ jobs: condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true')) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 steps: - template: ./docs-steps.yml @@ -40,7 +40,7 @@ jobs: testRunPlatform: macos pool: - vmImage: macos-10.14 + vmImage: macos-10.15 steps: - template: ./macos-steps.yml @@ -52,12 +52,12 @@ jobs: condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.1k + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -78,12 +78,12 @@ jobs: ) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1k + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 2d32e6d49bcc0e..e2aae324f211be 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -1,14 +1,14 @@ variables: coverage: false -pr: ['master', '3.9', '3.8', '3.7'] +pr: ['main', '3.10', '3.9', '3.8', '3.7'] jobs: - job: Prebuild displayName: Pre-build checks pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 steps: - template: ./prebuild-checks.yml @@ -20,7 +20,7 @@ jobs: condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true')) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 steps: - template: ./docs-steps.yml @@ -38,7 +38,7 @@ jobs: testRunPlatform: macos pool: - vmImage: macos-10.14 + vmImage: macos-10.15 steps: - template: ./macos-steps.yml @@ -52,12 +52,12 @@ jobs: condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.1k + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml @@ -78,12 +78,12 @@ jobs: ) pool: - vmImage: ubuntu-18.04 + vmImage: ubuntu-20.04 variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1k + openssl_version: 1.1.1m steps: - template: ./posix-steps.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000000..81445d2d79c739 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*.{py,c,cpp,h,rst,md,yml}] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space + +[*.{py,c,cpp,h}] +indent_size = 4 + +[*.yml] +indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5b86d39dc9c259..8412314680df69 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -128,7 +128,7 @@ Lib/ast.py @isidentical **/*idlelib* @terryjreedy -**/*typing* @gvanrossum @ilevkivskyi +**/*typing* @gvanrossum @Fidget-Spinner **/*asyncore @giampaolo **/*asynchat @giampaolo diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 28aea946623cc5..82ae4ca8c30977 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -10,9 +10,8 @@ https://devguide.python.org/#status-of-python-branches ## Reporting a Vulnerability Please read the guidelines on reporting security issues [on the -official website]( -https://www.python.org/news/security/#reporting-security-issues-in-python -) for instructions on how to report a security-related problem to +official website](https://www.python.org/dev/security/) for +instructions on how to report a security-related problem to the Python team responsibly. To reach the response team, email `security at python dot org`. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 41200bb957e47c..1102449a1af068 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,12 +7,14 @@ on: push: branches: - master + - 3.10 - 3.9 - 3.8 - 3.7 pull_request: branches: - master + - 3.10 - 3.9 - 3.8 - 3.7 @@ -51,6 +53,28 @@ jobs: git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE '(ssl|hashlib|hmac|^.github)' && echo '::set-output name=run_ssl_tests::true' || true fi + check_abi: + name: 'Check if the ABI has changed' + runs-on: ubuntu-20.04 + needs: check_source + if: needs.check_source.outputs.run_tests == 'true' + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - name: Install Dependencies + run: | + sudo ./.github/workflows/posix-deps-apt.sh + sudo apt-get install -yq abigail-tools + - name: Build CPython + env: + CFLAGS: -g3 -O0 + run: | + # Build Python with the libpython dynamic library + ./configure --enable-shared + make -j4 + - name: Check for changes in the ABI + run: make check-abidump + check_generated_files: name: 'Check if generated files are up to date' runs-on: ubuntu-latest @@ -61,6 +85,18 @@ jobs: - uses: actions/setup-python@v2 - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh + - name: Add ccache to PATH + run: echo "PATH=/usr/lib/ccache:$PATH" >> $GITHUB_ENV + - name: Configure ccache action + uses: hendrikmuhs/ccache-action@v1 + - name: Check Autoconf version 2.69 and aclocal 1.16.3 + run: | + grep "Generated by GNU Autoconf 2.69" configure + grep "aclocal 1.16.3" aclocal.m4 + grep -q "runstatedir" configure + grep -q "PKG_PROG_PKG_CONFIG" aclocal.m4 + - name: Regenerate autoconf files + run: docker run --rm -v $(pwd):/src quay.io/tiran/cpython_autoconf:269 - name: Build CPython run: | # Build Python with the libpython dynamic library @@ -71,9 +107,10 @@ jobs: run: | changes=$(git status --porcelain) # Check for changes in regenerated files - if ! test -z "$changes" - then - echo "Generated files not up to date. Perhaps you forgot to run make regen-all ;)" + if test -n "$changes"; then + echo "Generated files not up to date." + echo "Perhaps you forgot to run make regen-all or build.bat --regen. ;)" + echo "configure files must be regenerated with a specific, unpatched version of autoconf." echo "$changes" exit 1 fi @@ -87,6 +124,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout@v2 - name: Build CPython @@ -101,6 +140,8 @@ jobs: runs-on: windows-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + IncludeUwp: 'true' steps: - uses: actions/checkout@v2 - name: Register MSVC problem matcher @@ -117,10 +158,16 @@ jobs: runs-on: macos-latest needs: check_source if: needs.check_source.outputs.run_tests == 'true' + env: + PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout@v2 + - name: Prepare homebrew environment variables + run: | + echo "LDFLAGS=-L$(brew --prefix tcl-tk)/lib" >> $GITHUB_ENV + echo "PKG_CONFIG_PATH=$(brew --prefix openssl@1.1)/lib/pkgconfig:$(brew --prefix tcl-tk)/lib/pkgconfig" >> $GITHUB_ENV - name: Configure CPython - run: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl --prefix=/opt/python-dev + run: ./configure --with-pydebug --prefix=/opt/python-dev - name: Build CPython run: make -j4 - name: Display build info @@ -134,7 +181,8 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1k + OPENSSL_VER: 1.1.1m + PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout@v2 - name: Register gcc problem matcher @@ -177,7 +225,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1k, 3.0.0-alpha15] + openssl_ver: [1.1.1m, 3.0.1] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl diff --git a/.github/workflows/build_msi.yml b/.github/workflows/build_msi.yml index 182eb7ce571671..28ce06f3cf4e08 100644 --- a/.github/workflows/build_msi.yml +++ b/.github/workflows/build_msi.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - 3.10 - 3.9 - 3.8 - 3.7 @@ -12,6 +13,7 @@ on: pull_request: branches: - master + - 3.10 - 3.9 - 3.8 - 3.7 diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 8924fc992e25e6..4426238b9d9fa0 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -12,6 +12,7 @@ on: pull_request: branches: - master + - 3.10 - 3.9 - 3.8 - 3.7 diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh index 56cc70edf60001..0119843e47eeb1 100755 --- a/.github/workflows/posix-deps-apt.sh +++ b/.github/workflows/posix-deps-apt.sh @@ -9,6 +9,7 @@ apt-get -yq install \ libbz2-dev \ libffi-dev \ libgdbm-dev \ + libgdbm-compat-dev \ liblzma-dev \ libncurses5-dev \ libreadline6-dev \ diff --git a/.gitignore b/.gitignore index 80dcf34bf47a6f..09d08c8050cb2f 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ gmon.out .coverage .mypy_cache/ .pytest_cache/ +.DS_Store *.exe !Lib/distutils/command/*.exe @@ -60,6 +61,15 @@ Lib/test/data/* !Lib/test/data/README /Makefile /Makefile.pre +Mac/Makefile +Mac/PythonLauncher/Info.plist +Mac/PythonLauncher/Makefile +Mac/PythonLauncher/Python Launcher +Mac/PythonLauncher/Python Launcher.app/* +Mac/Resources/app/Info.plist +Mac/Resources/framework/Info.plist +Mac/pythonw +/*.framework/ Misc/python.pc Misc/python-embed.pc Misc/python-config.sh @@ -102,6 +112,8 @@ Tools/unicode/data/ /config.log /config.status /config.status.lineno +# hendrikmuhs/ccache-action@v1 +/.ccache /platform /profile-clean-stamp /profile-run-stamp @@ -124,3 +136,9 @@ Tools/ssl/win32 # Ignore ./python binary on Unix but still look into ./Python/ directory. /python !/Python/ + +# Artifacts generated by 3.11 lying around when switching branches: +/_bootstrap_python +/Programs/_freeze_module +/Python/deepfreeze/ +/Python/frozen_modules/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 1112a0b266227b..ee6cabe5ae0da3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ env: # Set rpath with env var instead of -Wl,-rpath linker flag # OpenSSL ignores LDFLAGS when linking bin/openssl - LD_RUN_PATH="${OPENSSL_DIR}/lib" + - PYTHONSTRICTEXTENSIONBUILD=1 branches: only: diff --git a/Doc/Makefile b/Doc/Makefile index f113dd06539869..24528a1c4f3269 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -137,14 +137,22 @@ pydoc-topics: build htmlview: html $(PYTHON) -c "import webbrowser; webbrowser.open('build/html/index.html')" -clean: - -rm -rf build/* $(VENVDIR)/* +clean: clean-venv + -rm -rf build/* + +clean-venv: + rm -rf $(VENVDIR) venv: - $(PYTHON) -m venv $(VENVDIR) - $(VENVDIR)/bin/python3 -m pip install -U pip setuptools - $(VENVDIR)/bin/python3 -m pip install -r requirements.txt - @echo "The venv has been created in the $(VENVDIR) directory" + @if [ -d $(VENVDIR) ] ; then \ + echo "venv already exists."; \ + echo "To recreate it, remove it first with \`make clean-venv'."; \ + else \ + $(PYTHON) -m venv $(VENVDIR); \ + $(VENVDIR)/bin/python3 -m pip install -U pip setuptools; \ + $(VENVDIR)/bin/python3 -m pip install -r requirements.txt; \ + echo "The venv has been created in the $(VENVDIR) directory"; \ + fi dist: rm -rf dist diff --git a/Doc/README.rst b/Doc/README.rst index 380ea4fa9b26ad..7e8a27b4066d87 100644 --- a/Doc/README.rst +++ b/Doc/README.rst @@ -28,28 +28,31 @@ install the tools into there. Using make ---------- -To get started on UNIX, you can create a virtual environment with the command :: +To get started on UNIX, you can create a virtual environment and build +documentation with the commands:: make venv - -That will install all the tools necessary to build the documentation. Assuming -the virtual environment was created in the ``venv`` directory (the default; -configurable with the VENVDIR variable), you can run the following command to -build the HTML output files:: - make html -By default, if the virtual environment is not created, the Makefile will -look for instances of sphinxbuild and blurb installed on your process PATH -(configurable with the SPHINXBUILD and BLURB variables). +The virtual environment in the ``venv`` directory will contain all the tools +necessary to build the documentation downloaded and installed from PyPI. +If you'd like to create the virtual environment in a different location, +you can specify it using the ``VENVDIR`` variable. + +You can also skip creating the virtual environment altogether, in which case +the Makefile will look for instances of ``sphinxbuild`` and ``blurb`` +installed on your process ``PATH`` (configurable with the ``SPHINXBUILD`` and +``BLURB`` variables). On Windows, we try to emulate the Makefile as closely as possible with a ``make.bat`` file. If you need to specify the Python interpreter to use, -set the PYTHON environment variable instead. +set the PYTHON environment variable. Available make targets are: -* "clean", which removes all build files. +* "clean", which removes all build files and the virtual environment. + +* "clean-venv", which removes the virtual environment directory. * "venv", which creates a virtual environment with all necessary tools installed. diff --git a/Doc/bugs.rst b/Doc/bugs.rst index a17f04d26fa40b..b3d057797c2561 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -41,7 +41,7 @@ Using the Python issue tracker ============================== Bug reports for Python itself should be submitted via the Python Bug Tracker -(https://bugs.python.org/). The bug tracker offers a Web form which allows +(https://bugs.python.org/). The bug tracker offers a web form which allows pertinent information to be entered and submitted to the developers. The first step in filing a report is to determine whether the problem has @@ -80,7 +80,7 @@ taken on the bug. Article which goes into some detail about how to create a useful bug report. This describes what kind of information is useful and why it is useful. - `Bug Report Writing Guidelines `_ + `Bug Writing Guidelines `_ Information about writing a good bug report. Some of this is specific to the Mozilla project, but describes general good practices. diff --git a/Doc/c-api/abstract.rst b/Doc/c-api/abstract.rst index f5df09fa7fd786..1823f9d70c79f3 100644 --- a/Doc/c-api/abstract.rst +++ b/Doc/c-api/abstract.rst @@ -24,3 +24,4 @@ but whose items have not been set to some non-\ ``NULL`` value yet. mapping.rst iter.rst buffer.rst + objbuffer.rst diff --git a/Doc/c-api/apiabiversion.rst b/Doc/c-api/apiabiversion.rst index b8a8f2ff886219..04050f7dabe172 100644 --- a/Doc/c-api/apiabiversion.rst +++ b/Doc/c-api/apiabiversion.rst @@ -6,34 +6,57 @@ API and ABI Versioning *********************** -``PY_VERSION_HEX`` is the Python version number encoded in a single integer. - -For example if the ``PY_VERSION_HEX`` is set to ``0x030401a2``, the underlying -version information can be found by treating it as a 32 bit number in -the following manner: - - +-------+-------------------------+------------------------------------------------+ - | Bytes | Bits (big endian order) | Meaning | - +=======+=========================+================================================+ - | ``1`` | ``1-8`` | ``PY_MAJOR_VERSION`` (the ``3`` in | - | | | ``3.4.1a2``) | - +-------+-------------------------+------------------------------------------------+ - | ``2`` | ``9-16`` | ``PY_MINOR_VERSION`` (the ``4`` in | - | | | ``3.4.1a2``) | - +-------+-------------------------+------------------------------------------------+ - | ``3`` | ``17-24`` | ``PY_MICRO_VERSION`` (the ``1`` in | - | | | ``3.4.1a2``) | - +-------+-------------------------+------------------------------------------------+ - | ``4`` | ``25-28`` | ``PY_RELEASE_LEVEL`` (``0xA`` for alpha, | - | | | ``0xB`` for beta, ``0xC`` for release | - | | | candidate and ``0xF`` for final), in this | - | | | case it is alpha. | - +-------+-------------------------+------------------------------------------------+ - | | ``29-32`` | ``PY_RELEASE_SERIAL`` (the ``2`` in | - | | | ``3.4.1a2``, zero for final releases) | - +-------+-------------------------+------------------------------------------------+ - -Thus ``3.4.1a2`` is hexversion ``0x030401a2``. +CPython exposes its version number in the following macros. +Note that these correspond to the version code is **built** with, +not necessarily the version used at **run time**. -All the given macros are defined in :source:`Include/patchlevel.h`. +See :ref:`stable` for a discussion of API and ABI stability across versions. + +.. c:macro:: PY_MAJOR_VERSION + + The ``3`` in ``3.4.1a2``. + +.. c:macro:: PY_MINOR_VERSION + + The ``4`` in ``3.4.1a2``. + +.. c:macro:: PY_MICRO_VERSION + + The ``1`` in ``3.4.1a2``. + +.. c:macro:: PY_RELEASE_LEVEL + + The ``a`` in ``3.4.1a2``. + This can be ``0xA`` for alpha, ``0xB`` for beta, ``0xC`` for release + candidate or ``0xF`` for final. +.. c:macro:: PY_RELEASE_SERIAL + + The ``2`` in ``3.4.1a2``. Zero for final releases. + +.. c:macro:: PY_VERSION_HEX + + The Python version number encoded in a single integer. + + The underlying version information can be found by treating it as a 32 bit + number in the following manner: + + +-------+-------------------------+-------------------------+--------------------------+ + | Bytes | Bits (big endian order) | Meaning | Value for ``3.4.1a2`` | + +=======+=========================+=========================+==========================+ + | 1 | 1-8 | ``PY_MAJOR_VERSION`` | ``0x03`` | + +-------+-------------------------+-------------------------+--------------------------+ + | 2 | 9-16 | ``PY_MINOR_VERSION`` | ``0x04`` | + +-------+-------------------------+-------------------------+--------------------------+ + | 3 | 17-24 | ``PY_MICRO_VERSION`` | ``0x01`` | + +-------+-------------------------+-------------------------+--------------------------+ + | 4 | 25-28 | ``PY_RELEASE_LEVEL`` | ``0xA`` | + + +-------------------------+-------------------------+--------------------------+ + | | 29-32 | ``PY_RELEASE_SERIAL`` | ``0x2`` | + +-------+-------------------------+-------------------------+--------------------------+ + + Thus ``3.4.1a2`` is hexversion ``0x030401a2`` and ``3.10.0`` is + hexversion ``0x030a00f0``. + + +All the given macros are defined in :source:`Include/patchlevel.h`. diff --git a/Doc/c-api/call.rst b/Doc/c-api/call.rst index 31dc9c8031fdb6..739b5e97d15150 100644 --- a/Doc/c-api/call.rst +++ b/Doc/c-api/call.rst @@ -185,7 +185,7 @@ Object Calling API Various functions are available for calling a Python object. Each converts its arguments to a convention supported by the called object – either *tp_call* or vectorcall. -In order to do as litle conversion as possible, pick one that best fits +In order to do as little conversion as possible, pick one that best fits the format of data you have available. The following table summarizes the available functions; diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst index e2ea766b3a32a7..c25894681bca35 100644 --- a/Doc/c-api/complex.rst +++ b/Doc/c-api/complex.rst @@ -46,9 +46,9 @@ pointers. This is consistent throughout the API. :c:type:`Py_complex` representation. -.. c:function:: Py_complex _Py_c_neg(Py_complex complex) +.. c:function:: Py_complex _Py_c_neg(Py_complex num) - Return the negation of the complex number *complex*, using the C + Return the negation of the complex number *num*, using the C :c:type:`Py_complex` representation. diff --git a/Doc/c-api/concrete.rst b/Doc/c-api/concrete.rst index c1d9fa1b41a3fe..84224dcca523b9 100644 --- a/Doc/c-api/concrete.rst +++ b/Doc/c-api/concrete.rst @@ -115,3 +115,4 @@ Other Objects coro.rst contextvars.rst datetime.rst + typehints.rst diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 21c508dc30ae22..dc056590074707 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -100,7 +100,7 @@ For convenience, some of these functions will always return a This is the most common way to set the error indicator. The first argument specifies the exception type; it is normally one of the standard exceptions, e.g. :c:data:`PyExc_RuntimeError`. You need not increment its reference count. - The second argument is an error message; it is decoded from ``'utf-8``'. + The second argument is an error message; it is decoded from ``'utf-8'``. .. c:function:: void PyErr_SetObject(PyObject *type, PyObject *value) diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 55ed9d4f7fad48..8c90d1e8991c10 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -33,6 +33,26 @@ Constructors for container types must conform to two rules: #. Once all the fields which may contain references to other containers are initialized, it must call :c:func:`PyObject_GC_Track`. +Similarly, the deallocator for the object must conform to a similar pair of +rules: + +#. Before fields which refer to other containers are invalidated, + :c:func:`PyObject_GC_UnTrack` must be called. + +#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`. + + .. warning:: + If a type adds the Py_TPFLAGS_HAVE_GC, then it *must* implement at least + a :c:member:`~PyTypeObject.tp_traverse` handler or explicitly use one + from its subclass or subclasses. + + When calling :c:func:`PyType_Ready` or some of the APIs that indirectly + call it like :c:func:`PyType_FromSpecWithBases` or + :c:func:`PyType_FromSpec` the interpreter will automatically populate the + :c:member:`~PyTypeObject.tp_flags`, :c:member:`~PyTypeObject.tp_traverse` + and :c:member:`~PyTypeObject.tp_clear` fields if the type inherits from a + class that implements the garbage collector protocol and the child class + does *not* include the :const:`Py_TPFLAGS_HAVE_GC` flag. .. c:function:: TYPE* PyObject_GC_New(TYPE, PyTypeObject *type) @@ -88,14 +108,6 @@ Constructors for container types must conform to two rules: .. versionadded:: 3.9 -Similarly, the deallocator for the object must conform to a similar pair of -rules: - -#. Before fields which refer to other containers are invalidated, - :c:func:`PyObject_GC_UnTrack` must be called. - -#. The object's memory must be deallocated using :c:func:`PyObject_GC_Del`. - .. c:function:: void PyObject_GC_Del(void *op) diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index c6fc33076f0f51..d2ae6b6d4e4711 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -299,4 +299,8 @@ Importing Modules field; failure to provide the sentinel value can result in a memory fault. Returns ``0`` on success or ``-1`` if insufficient memory could be allocated to extend the internal table. In the event of failure, no modules are added to the - internal table. This should be called before :c:func:`Py_Initialize`. + internal table. This must be called before :c:func:`Py_Initialize`. + + If Python is initialized multiple times, :c:func:`PyImport_AppendInittab` or + :c:func:`PyImport_ExtendInittab` must be called before each Python + initialization. diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 0f759732b35ea8..9ac3039d02ec38 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -473,7 +473,7 @@ Process-wide parameters (set by :c:func:`Py_SetProgramName` above) and some environment variables. The returned string consists of a series of directory names separated by a platform dependent delimiter character. The delimiter character is ``':'`` - on Unix and Mac OS X, ``';'`` on Windows. The returned string points into + on Unix and macOS, ``';'`` on Windows. The returned string points into static storage; the caller should not modify its value. The list :data:`sys.path` is initialized with this value on interpreter startup; it can be (and usually is) modified later to change the search path for loading @@ -500,7 +500,7 @@ Process-wide parameters default search path but uses the one provided instead. This is useful if Python is embedded by an application that has full knowledge of the location of all modules. The path components should be separated by the platform - dependent delimiter character, which is ``':'`` on Unix and Mac OS X, ``';'`` + dependent delimiter character, which is ``':'`` on Unix and macOS, ``';'`` on Windows. This also causes :data:`sys.executable` to be set to the program @@ -541,7 +541,7 @@ Process-wide parameters Return the platform identifier for the current platform. On Unix, this is formed from the "official" name of the operating system, converted to lower case, followed by the major revision number; e.g., for Solaris 2.x, which is - also known as SunOS 5.x, the value is ``'sunos5'``. On Mac OS X, it is + also known as SunOS 5.x, the value is ``'sunos5'``. On macOS, it is ``'darwin'``. On Windows, it is ``'win'``. The returned string points into static storage; the caller should not modify its value. The value is available to Python code as ``sys.platform``. diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index de85029481185a..c037f19ce64f31 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -22,7 +22,7 @@ There are two kinds of configuration: * The :ref:`Isolated Configuration ` can be used to embed Python into an application. It isolates Python from the system. For example, environments variables are ignored, the LC_CTYPE locale is left unchanged and - no signal handler is registred. + no signal handler is registered. The :c:func:`Py_RunMain` function can be used to write a customized Python program. @@ -696,7 +696,7 @@ PyConfig * Otherwise, use the :term:`locale encoding`: ``nl_langinfo(CODESET)`` result. - At Python statup, the encoding name is normalized to the Python codec + At Python startup, the encoding name is normalized to the Python codec name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``. See also the :c:member:`~PyConfig.filesystem_errors` member. @@ -1193,7 +1193,10 @@ The caller is responsible to handle exceptions (error or exit) using If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or :c:func:`PyImport_ExtendInittab` are used, they must be set or called after -Python preinitialization and before the Python initialization. +Python preinitialization and before the Python initialization. If Python is +initialized multiple times, :c:func:`PyImport_AppendInittab` or +:c:func:`PyImport_ExtendInittab` must be called before each Python +initialization. The current configuration (``PyConfig`` type) is stored in ``PyInterpreterState.config``. diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst index 63290e0a7f0bf7..3e388bb917a029 100644 --- a/Doc/c-api/iter.rst +++ b/Doc/c-api/iter.rst @@ -9,10 +9,10 @@ There are two functions specifically for working with iterators. .. c:function:: int PyIter_Check(PyObject *o) - Return non-zero if the object *o* supports the iterator protocol, and ``0`` - otherwise. This function always succeeds. + Return non-zero if the object *o* can be safely passed to + :c:func:`PyIter_Next`, and ``0`` otherwise. This function always succeeds. -.. c:function:: int PyAiter_Check(PyObject *o) +.. c:function:: int PyAIter_Check(PyObject *o) Returns non-zero if the object 'obj' provides :class:`AsyncIterator` protocols, and ``0`` otherwise. This function always succeeds. @@ -21,10 +21,11 @@ There are two functions specifically for working with iterators. .. c:function:: PyObject* PyIter_Next(PyObject *o) - Return the next value from the iteration *o*. The object must be an iterator - (it is up to the caller to check this). If there are no remaining values, - returns ``NULL`` with no exception set. If an error occurs while retrieving - the item, returns ``NULL`` and passes along the exception. + Return the next value from the iterator *o*. The object must be an iterator + according to :c:func:`PyIter_Check` (it is up to the caller to check this). + If there are no remaining values, returns ``NULL`` with no exception set. + If an error occurs while retrieving the item, returns ``NULL`` and passes + along the exception. To write a loop which iterates over an iterator, the C code should look something like this:: diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index efddc6f7be5e71..0746d9ac52a7bc 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -488,7 +488,7 @@ Customize Memory Allocators Debug hooks on the Python memory allocators =========================================== -When :ref:`Python is built is debug mode `, the +When :ref:`Python is built in debug mode `, the :c:func:`PyMem_SetupDebugHooks` function is called at the :ref:`Python preinitialization ` to setup debug hooks on Python memory allocators to detect memory errors. diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index a2541afb685c30..94c8d9f981713f 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -221,6 +221,12 @@ or request "multi-phase initialization" by returning the definition struct itsel than 0 and the module state (as returned by :c:func:`PyModule_GetState`) is ``NULL``. + Like :c:member:`PyTypeObject.tp_clear`, this function is not *always* + called before a module is deallocated. For example, when reference + counting is enough to determine that an object is no longer used, + the cyclic garbage collector is not involved and + :c:member:`~PyModuleDef.m_free` is called directly. + .. versionchanged:: 3.9 No longer called before the module state is allocated. diff --git a/Doc/c-api/objbuffer.rst b/Doc/c-api/objbuffer.rst new file mode 100644 index 00000000000000..6b82a642d7ee42 --- /dev/null +++ b/Doc/c-api/objbuffer.rst @@ -0,0 +1,55 @@ +.. highlight:: c + +Old Buffer Protocol +------------------- + +.. deprecated:: 3.0 + +These functions were part of the "old buffer protocol" API in Python 2. +In Python 3, this protocol doesn't exist anymore but the functions are still +exposed to ease porting 2.x code. They act as a compatibility wrapper +around the :ref:`new buffer protocol `, but they don't give +you control over the lifetime of the resources acquired when a buffer is +exported. + +Therefore, it is recommended that you call :c:func:`PyObject_GetBuffer` +(or the ``y*`` or ``w*`` :ref:`format codes ` with the +:c:func:`PyArg_ParseTuple` family of functions) to get a buffer view over +an object, and :c:func:`PyBuffer_Release` when the buffer view can be released. + + +.. c:function:: int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len) + + Returns a pointer to a read-only memory location usable as character-based + input. The *obj* argument must support the single-segment character buffer + interface. On success, returns ``0``, sets *buffer* to the memory location + and *buffer_len* to the buffer length. Returns ``-1`` and sets a + :exc:`TypeError` on error. + + +.. c:function:: int PyObject_AsReadBuffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len) + + Returns a pointer to a read-only memory location containing arbitrary data. + The *obj* argument must support the single-segment readable buffer + interface. On success, returns ``0``, sets *buffer* to the memory location + and *buffer_len* to the buffer length. Returns ``-1`` and sets a + :exc:`TypeError` on error. + + +.. c:function:: int PyObject_CheckReadBuffer(PyObject *o) + + Returns ``1`` if *o* supports the single-segment readable buffer interface. + Otherwise returns ``0``. This function always succeeds. + + Note that this function tries to get and release a buffer, and exceptions + which occur while calling corresponding functions will get suppressed. + To get error reporting use :c:func:`PyObject_GetBuffer()` instead. + + +.. c:function:: int PyObject_AsWriteBuffer(PyObject *obj, void **buffer, Py_ssize_t *buffer_len) + + Returns a pointer to a writable memory location. The *obj* argument must + support the single-segment, character buffer interface. On success, + returns ``0``, sets *buffer* to the memory location and *buffer_len* to the + buffer length. Returns ``-1`` and sets a :exc:`TypeError` on error. + diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 42e3340acb79a0..17e37077994968 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -311,12 +311,12 @@ Object Protocol returned. This is the equivalent to the Python expression ``len(o)``. -.. c:function:: Py_ssize_t PyObject_LengthHint(PyObject *o, Py_ssize_t default) +.. c:function:: Py_ssize_t PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue) Return an estimated length for the object *o*. First try to return its actual length, then an estimate using :meth:`~object.__length_hint__`, and finally return the default value. On error return ``-1``. This is the - equivalent to the Python expression ``operator.length_hint(o, default)``. + equivalent to the Python expression ``operator.length_hint(o, defaultvalue)``. .. versionadded:: 3.4 @@ -358,7 +358,7 @@ Object Protocol iterated. -.. c:function:: PyObject* PyObject_GetAiter(PyObject *o) +.. c:function:: PyObject* PyObject_GetAIter(PyObject *o) This is the equivalent to the Python expression ``aiter(o)``. Takes an :class:`AsyncIterable` object and returns an :class:`AsyncIterator` for it. diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst index 9c05cb3c82dfbe..4ae20e93e36785 100644 --- a/Doc/c-api/stable.rst +++ b/Doc/c-api/stable.rst @@ -2,37 +2,157 @@ .. _stable: -*********************************** +*************** +C API Stability +*************** + +Python's C API is covered by the Backwards Compatibility Policy, :pep:`387`. +While the C API will change with every minor release (e.g. from 3.9 to 3.10), +most changes will be source-compatible, typically by only adding new API. +Changing existing API or removing API is only done after a deprecation period +or to fix serious issues. + +CPython's Application Binary Interface (ABI) is forward- and +backwards-compatible across a minor release (if these are compiled the same +way; see :ref:`stable-abi-platform` below). +So, code compiled for Python 3.10.0 will work on 3.10.8 and vice versa, +but will need to be compiled separately for 3.9.x and 3.10.x. + +Names prefixed by an underscore, such as ``_Py_InternalState``, +are private API that can change without notice even in patch releases. + + Stable Application Binary Interface -*********************************** - -Traditionally, the C API of Python will change with every release. Most changes -will be source-compatible, typically by only adding API, rather than changing -existing API or removing API (although some interfaces do get removed after -being deprecated first). - -Unfortunately, the API compatibility does not extend to binary compatibility -(the ABI). The reason is primarily the evolution of struct definitions, where -addition of a new field, or changing the type of a field, might not break the -API, but can break the ABI. As a consequence, extension modules need to be -recompiled for every Python release (although an exception is possible on Unix -when none of the affected interfaces are used). In addition, on Windows, -extension modules link with a specific pythonXY.dll and need to be recompiled to -link with a newer one. - -Since Python 3.2, a subset of the API has been declared to guarantee a stable -ABI. Extension modules wishing to use this API (called "limited API") need to -define ``Py_LIMITED_API``. A number of interpreter details then become hidden -from the extension module; in return, a module is built that works on any 3.x -version (x>=2) without recompilation. - -In some cases, the stable ABI needs to be extended with new functions. -Extension modules wishing to use these new APIs need to set ``Py_LIMITED_API`` -to the ``PY_VERSION_HEX`` value (see :ref:`apiabiversion`) of the minimum Python -version they want to support (e.g. ``0x03030000`` for Python 3.3). Such modules -will work on all subsequent Python releases, but fail to load (because of -missing symbols) on the older releases. - -As of Python 3.2, the set of functions available to the limited API is -documented in :pep:`384`. In the C API documentation, API elements that are not -part of the limited API are marked as "Not part of the limited API." +=================================== + +Python 3.2 introduced the *Limited API*, a subset of Python's C API. +Extensions that only use the Limited API can be +compiled once and work with multiple versions of Python. +Contents of the Limited API are :ref:`listed below `. + +To enable this, Python provides a *Stable ABI*: a set of symbols that will +remain compatible across Python 3.x versions. The Stable ABI contains symbols +exposed in the Limited API, but also other ones – for example, functions +necessary to support older versions of the Limited API. + +(For simplicity, this document talks about *extensions*, but the Limited API +and Stable ABI work the same way for all uses of the API – for example, +embedding Python.) + +.. c:macro:: Py_LIMITED_API + + Define this macro before including ``Python.h`` to opt in to only use + the Limited API, and to select the Limited API version. + + Define ``Py_LIMITED_API`` to the value of :c:data:`PY_VERSION_HEX` + corresponding to the lowest Python version your extension supports. + The extension will work without recompilation with all Python 3 releases + from the specified one onward, and can use Limited API introduced up to that + version. + + Rather than using the ``PY_VERSION_HEX`` macro directly, hardcode a minimum + minor version (e.g. ``0x030A0000`` for Python 3.10) for stability when + compiling with future Python versions. + + You can also define ``Py_LIMITED_API`` to ``3``. This works the same as + ``0x03020000`` (Python 3.2, the version that introduced Limited API). + +On Windows, extensions that use the Stable ABI should be linked against +``python3.dll`` rather than a version-specific library such as +``python39.dll``. + +On some platforms, Python will look for and load shared library files named +with the ``abi3`` tag (e.g. ``mymodule.abi3.so``). +It does not check if such extensions conform to a Stable ABI. +The user (or their packaging tools) need to ensure that, for example, +extensions built with the 3.10+ Limited API are not installed for lower +versions of Python. + +All functions in the Stable ABI are present as functions in Python's shared +library, not solely as macros. This makes them usable from languages that don't +use the C preprocessor. + + +Limited API Scope and Performance +--------------------------------- + +The goal for the Limited API is to allow everything that is possible with the +full C API, but possibly with a performance penalty. + +For example, while :c:func:`PyList_GetItem` is available, its “unsafe” macro +variant :c:func:`PyList_GET_ITEM` is not. +The macro can be faster because it can rely on version-specific implementation +details of the list object. + +Without ``Py_LIMITED_API`` defined, some C API functions are inlined or +replaced by macros. +Defining ``Py_LIMITED_API`` disables this inlining, allowing stability as +Python's data structures are improved, but possibly reducing performance. + +By leaving out the ``Py_LIMITED_API`` definition, it is possible to compile +a Limited API extension with a version-specific ABI. This can improve +performance for that Python version, but will limit compatibility. +Compiling with ``Py_LIMITED_API`` will then yield an extension that can be +distributed where a version-specific one is not available – for example, +for prereleases of an upcoming Python version. + + +Limited API Caveats +------------------- + +Note that compiling with ``Py_LIMITED_API`` is *not* a complete guarantee that +code conforms to the Limited API or the Stable ABI. ``Py_LIMITED_API`` only +covers definitions, but an API also includes other issues, such as expected +semantics. + +One issue that ``Py_LIMITED_API`` does not guard against is calling a function +with arguments that are invalid in a lower Python version. +For example, consider a function that starts accepting ``NULL`` for an +argument. In Python 3.9, ``NULL`` now selects a default behavior, but in +Python 3.8, the argument will be used directly, causing a ``NULL`` dereference +and crash. A similar argument works for fields of structs. + +Another issue is that some struct fields are currently not hidden when +``Py_LIMITED_API`` is defined, even though they're part of the Limited API. + +For these reasons, we recommend testing an extension with *all* minor Python +versions it supports, and preferably to build with the *lowest* such version. + +We also recommend reviewing documentation of all used API to check +if it is explicitly part of the Limited API. Even with ``Py_LIMITED_API`` +defined, a few private declarations are exposed for technical reasons (or +even unintentionally, as bugs). + +Also note that the Limited API is not necessarily stable: compiling with +``Py_LIMITED_API`` with Python 3.8 means that the extension will +run with Python 3.12, but it will not necessarily *compile* with Python 3.12. +In particular, parts of the Limited API may be deprecated and removed, +provided that the Stable ABI stays stable. + + +.. _stable-abi-platform: + +Platform Considerations +======================= + +ABI stability depends not only on Python, but also on the compiler used, +lower-level libraries and compiler options. For the purposes of the Stable ABI, +these details define a “platform”. They usually depend on the OS +type and processor architecture + +It is the responsibility of each particular distributor of Python +to ensure that all Python versions on a particular platform are built +in a way that does not break the Stable ABI. +This is the case with Windows and macOS releases from ``python.org`` and many +third-party distributors. + + +.. _stable-abi-list: + +Contents of Limited API +======================= + + +Currently, the Limited API includes the following items: + +.. limited-api-list:: diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 20d5485d5544c2..05c54ccc8dab59 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -469,6 +469,21 @@ Accessing attributes of extension types {NULL} /* Sentinel */ }; + +.. c:function:: PyObject* PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m) + + Get an attribute belonging to the object at address *obj_addr*. The + attribute is described by ``PyMemberDef`` *m*. Returns ``NULL`` + on error. + + +.. c:function:: int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o) + + Set an attribute belonging to the object at address *obj_addr* to object *o*. + The attribute to set is described by ``PyMemberDef`` *m*. Returns ``0`` + if successful and a negative value on failure. + + .. c:type:: PyGetSetDef Structure to define property-like access for a type. See also description of diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index bdb636dff326f2..c472e8df9cf431 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -13,7 +13,7 @@ Type Objects The C structure of the objects used to describe built-in types. -.. c:var:: PyObject* PyType_Type +.. c:var:: PyTypeObject PyType_Type This is the type object for type objects; it is the same object as :class:`type` in the Python layer. @@ -97,6 +97,15 @@ Type Objects from a type's base class. Return ``0`` on success, or return ``-1`` and sets an exception on error. + .. note:: + If some of the base classes implements the GC protocol and the provided + type does not include the :const:`Py_TPFLAGS_HAVE_GC` in its flags, then + the GC protocol will be automatically implemented from its parents. On + the contrary, if the type being created does include + :const:`Py_TPFLAGS_HAVE_GC` in its flags then it **must** implement the + GC protocol itself by at least implementing the + :c:member:`~PyTypeObject.tp_traverse` handle. + .. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot) Return the function pointer stored in the given slot. If the @@ -165,7 +174,7 @@ The following functions and structs are used to create The *module* argument can be used to record the module in which the new class is defined. It must be a module object or ``NULL``. If not ``NULL``, the module is associated with the new type and can later be - retreived with :c:func:`PyType_GetModule`. + retrieved with :c:func:`PyType_GetModule`. The associated module is not inherited by subclasses; it must be specified for each class individually. diff --git a/Doc/c-api/typehints.rst b/Doc/c-api/typehints.rst new file mode 100644 index 00000000000000..dfda96a47243bd --- /dev/null +++ b/Doc/c-api/typehints.rst @@ -0,0 +1,47 @@ +.. highlight:: c + +.. _typehintobjects: + +Objects for Type Hinting +------------------------ + +Various built-in types for type hinting are provided. Currently, +two types exist -- :ref:`GenericAlias ` and +:ref:`Union `. Only ``GenericAlias`` is exposed to C. + +.. c:function:: PyObject* Py_GenericAlias(PyObject *origin, PyObject *args) + + Create a :ref:`GenericAlias ` object. + Equivalent to calling the Python class + :class:`types.GenericAlias`. The *origin* and *args* arguments set the + ``GenericAlias``\ 's ``__origin__`` and ``__args__`` attributes respectively. + *origin* should be a :c:type:`PyTypeObject*`, and *args* can be a + :c:type:`PyTupleObject*` or any ``PyObject*``. If *args* passed is + not a tuple, a 1-tuple is automatically constructed and ``__args__`` is set + to ``(args,)``. + Minimal checking is done for the arguments, so the function will succeed even + if *origin* is not a type. + The ``GenericAlias``\ 's ``__parameters__`` attribute is constructed lazily + from ``__args__``. On failure, an exception is raised and ``NULL`` is + returned. + + Here's an example of how to make an extension type generic:: + + ... + static PyMethodDef my_obj_methods[] = { + // Other methods. + ... + {"__class_getitem__", (PyCFunction)Py_GenericAlias, METH_O|METH_CLASS, "See PEP 585"} + ... + } + + .. seealso:: The data model method :meth:`__class_getitem__`. + + .. versionadded:: 3.9 + +.. c:var:: PyTypeObject Py_GenericAliasType + + The C type of the object returned by :c:func:`Py_GenericAlias`. Equivalent to + :class:`types.GenericAlias` in Python. + + .. versionadded:: 3.9 diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 82f2ab53451166..e491c26f981b5f 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -189,138 +189,138 @@ sub-slots .. table:: :widths: 26,17,12 - +---------------------------------------------------------+-----------------------------------+--------------+ - | Slot | :ref:`Type ` | special | - | | | methods | - +=========================================================+===================================+==============+ - | :c:member:`~PyAsyncMethods.am_await` | :c:type:`unaryfunc` | __await__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyAsyncMethods.am_aiter` | :c:type:`unaryfunc` | __aiter__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyAsyncMethods.am_anext` | :c:type:`unaryfunc` | __anext__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyAsyncMethods.am_send` | :c:type:`sendfunc` | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_add` | :c:type:`binaryfunc` | __add__ | - | | | __radd__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_add` | :c:type:`binaryfunc` | __iadd__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_subtract` | :c:type:`binaryfunc` | __sub__ | - | | | __rsub__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_subtract` | :c:type:`binaryfunc` | __sub__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_multiply` | :c:type:`binaryfunc` | __mul__ | - | | | __rmul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_multiply` | :c:type:`binaryfunc` | __mul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_remainder` | :c:type:`binaryfunc` | __mod__ | - | | | __rmod__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_remainder` | :c:type:`binaryfunc` | __mod__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_divmod` | :c:type:`binaryfunc` | __divmod__ | - | | | __rdivmod__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_power` | :c:type:`ternaryfunc` | __pow__ | - | | | __rpow__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_power` | :c:type:`ternaryfunc` | __pow__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_negative` | :c:type:`unaryfunc` | __neg__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_positive` | :c:type:`unaryfunc` | __pos__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_absolute` | :c:type:`unaryfunc` | __abs__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_bool` | :c:type:`inquiry` | __bool__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_invert` | :c:type:`unaryfunc` | __invert__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_lshift` | :c:type:`binaryfunc` | __lshift__ | - | | | __rlshift__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_lshift` | :c:type:`binaryfunc` | __lshift__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_rshift` | :c:type:`binaryfunc` | __rshift__ | - | | | __rrshift__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_rshift` | :c:type:`binaryfunc` | __rshift__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_and` | :c:type:`binaryfunc` | __and__ | - | | | __rand__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_and` | :c:type:`binaryfunc` | __and__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_xor` | :c:type:`binaryfunc` | __xor__ | - | | | __rxor__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_xor` | :c:type:`binaryfunc` | __xor__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_or` | :c:type:`binaryfunc` | __or__ | - | | | __ror__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_or` | :c:type:`binaryfunc` | __or__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_int` | :c:type:`unaryfunc` | __int__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_reserved` | void * | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_float` | :c:type:`unaryfunc` | __float__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_floor_divide` | :c:type:`binaryfunc` | __floordiv__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_floor_divide` | :c:type:`binaryfunc` | __floordiv__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_true_divide` | :c:type:`binaryfunc` | __truediv__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_true_divide` | :c:type:`binaryfunc` | __truediv__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_index` | :c:type:`unaryfunc` | __index__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_matrix_multiply` | :c:type:`binaryfunc` | __matmul__ | - | | | __rmatmul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyNumberMethods.nb_inplace_matrix_multiply` | :c:type:`binaryfunc` | __matmul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyMappingMethods.mp_length` | :c:type:`lenfunc` | __len__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyMappingMethods.mp_subscript` | :c:type:`binaryfunc` | __getitem__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyMappingMethods.mp_ass_subscript` | :c:type:`objobjargproc` | __setitem__, | - | | | __delitem__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_length` | :c:type:`lenfunc` | __len__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_concat` | :c:type:`binaryfunc` | __add__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_repeat` | :c:type:`ssizeargfunc` | __mul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_item` | :c:type:`ssizeargfunc` | __getitem__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_ass_item` | :c:type:`ssizeobjargproc` | __setitem__ | - | | | __delitem__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_contains` | :c:type:`objobjproc` | __contains__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_inplace_concat` | :c:type:`binaryfunc` | __iadd__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PySequenceMethods.sq_inplace_repeat` | :c:type:`ssizeargfunc` | __imul__ | - +---------------------------------------------------------+-----------------------------------+--------------+ - | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyBufferProcs.bf_getbuffer` | :c:func:`getbufferproc` | | - +---------------------------------------------------------+-----------------------------------+--------------+ - | :c:member:`~PyBufferProcs.bf_releasebuffer` | :c:func:`releasebufferproc` | | - +---------------------------------------------------------+-----------------------------------+--------------+ + +---------------------------------------------------------+-----------------------------------+---------------+ + | Slot | :ref:`Type ` | special | + | | | methods | + +=========================================================+===================================+===============+ + | :c:member:`~PyAsyncMethods.am_await` | :c:type:`unaryfunc` | __await__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyAsyncMethods.am_aiter` | :c:type:`unaryfunc` | __aiter__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyAsyncMethods.am_anext` | :c:type:`unaryfunc` | __anext__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyAsyncMethods.am_send` | :c:type:`sendfunc` | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_add` | :c:type:`binaryfunc` | __add__ | + | | | __radd__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_add` | :c:type:`binaryfunc` | __iadd__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_subtract` | :c:type:`binaryfunc` | __sub__ | + | | | __rsub__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_subtract` | :c:type:`binaryfunc` | __isub__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_multiply` | :c:type:`binaryfunc` | __mul__ | + | | | __rmul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_multiply` | :c:type:`binaryfunc` | __imul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_remainder` | :c:type:`binaryfunc` | __mod__ | + | | | __rmod__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_remainder` | :c:type:`binaryfunc` | __imod__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_divmod` | :c:type:`binaryfunc` | __divmod__ | + | | | __rdivmod__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_power` | :c:type:`ternaryfunc` | __pow__ | + | | | __rpow__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_power` | :c:type:`ternaryfunc` | __ipow__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_negative` | :c:type:`unaryfunc` | __neg__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_positive` | :c:type:`unaryfunc` | __pos__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_absolute` | :c:type:`unaryfunc` | __abs__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_bool` | :c:type:`inquiry` | __bool__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_invert` | :c:type:`unaryfunc` | __invert__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_lshift` | :c:type:`binaryfunc` | __lshift__ | + | | | __rlshift__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_lshift` | :c:type:`binaryfunc` | __ilshift__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_rshift` | :c:type:`binaryfunc` | __rshift__ | + | | | __rrshift__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_rshift` | :c:type:`binaryfunc` | __irshift__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_and` | :c:type:`binaryfunc` | __and__ | + | | | __rand__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_and` | :c:type:`binaryfunc` | __iand__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_xor` | :c:type:`binaryfunc` | __xor__ | + | | | __rxor__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_xor` | :c:type:`binaryfunc` | __ixor__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_or` | :c:type:`binaryfunc` | __or__ | + | | | __ror__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_or` | :c:type:`binaryfunc` | __ior__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_int` | :c:type:`unaryfunc` | __int__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_reserved` | void * | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_float` | :c:type:`unaryfunc` | __float__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_floor_divide` | :c:type:`binaryfunc` | __floordiv__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_floor_divide` | :c:type:`binaryfunc` | __ifloordiv__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_true_divide` | :c:type:`binaryfunc` | __truediv__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_true_divide` | :c:type:`binaryfunc` | __itruediv__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_index` | :c:type:`unaryfunc` | __index__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_matrix_multiply` | :c:type:`binaryfunc` | __matmul__ | + | | | __rmatmul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyNumberMethods.nb_inplace_matrix_multiply` | :c:type:`binaryfunc` | __imatmul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyMappingMethods.mp_length` | :c:type:`lenfunc` | __len__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyMappingMethods.mp_subscript` | :c:type:`binaryfunc` | __getitem__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyMappingMethods.mp_ass_subscript` | :c:type:`objobjargproc` | __setitem__, | + | | | __delitem__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_length` | :c:type:`lenfunc` | __len__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_concat` | :c:type:`binaryfunc` | __add__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_repeat` | :c:type:`ssizeargfunc` | __mul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_item` | :c:type:`ssizeargfunc` | __getitem__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_ass_item` | :c:type:`ssizeobjargproc` | __setitem__ | + | | | __delitem__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_contains` | :c:type:`objobjproc` | __contains__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_inplace_concat` | :c:type:`binaryfunc` | __iadd__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PySequenceMethods.sq_inplace_repeat` | :c:type:`ssizeargfunc` | __imul__ | + +---------------------------------------------------------+-----------------------------------+---------------+ + | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyBufferProcs.bf_getbuffer` | :c:func:`getbufferproc` | | + +---------------------------------------------------------+-----------------------------------+---------------+ + | :c:member:`~PyBufferProcs.bf_releasebuffer` | :c:func:`releasebufferproc` | | + +---------------------------------------------------------+-----------------------------------+---------------+ .. _slot-typedefs-table: @@ -668,6 +668,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) :c:func:`PyObject_GC_Del` if the instance was allocated using :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`. + If the type supports garbage collection (has the :const:`Py_TPFLAGS_HAVE_GC` + flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack` + before clearing any member fields. + + .. code-block:: c + + static void foo_dealloc(foo_object *self) { + PyObject_GC_UnTrack(self); + Py_CLEAR(self->ref); + Py_TYPE(self)->tp_free((PyObject *)self); + } + Finally, if the type is heap allocated (:const:`Py_TPFLAGS_HEAPTYPE`), the deallocator should decrement the reference count for its type object after calling the type deallocator. In order to avoid dangling pointers, the @@ -1097,8 +1109,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) This is a bitmask of all the bits that pertain to the existence of certain fields in the type object and its extension structures. Currently, it includes - the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`, - :const:`Py_TPFLAGS_HAVE_VERSION_TAG`. + the following bits: :const:`Py_TPFLAGS_HAVE_STACKLESS_EXTENSION`. **Inheritance:** @@ -1178,14 +1189,6 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.9 - - .. data:: Py_TPFLAGS_HAVE_AM_SEND - - This bit is set when the :c:member:`~PyAsyncMethods.am_send` entry is present in the - :c:member:`~PyTypeObject.tp_as_async` slot of type structure. - - .. versionadded:: 3.10 - .. data:: Py_TPFLAGS_IMMUTABLETYPE This bit is set for type objects that are immutable: type attributes cannot be set nor deleted. @@ -1389,6 +1392,12 @@ and :c:type:`PyType_Type` effectively act as defaults.) so that *self* knows the contained object can no longer be used. The :c:func:`Py_CLEAR` macro performs the operations in a safe order. + Note that :c:member:`~PyTypeObject.tp_clear` is not *always* called + before an instance is deallocated. For example, when reference counting + is enough to determine that an object is no longer used, the cyclic garbage + collector is not involved and :c:member:`~PyTypeObject.tp_dealloc` is + called directly. + Because the goal of :c:member:`~PyTypeObject.tp_clear` functions is to break reference cycles, it's not necessary to clear contained objects like Python strings or Python integers, which can't participate in reference cycles. On the other hand, it may @@ -1511,9 +1520,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: getiterfunc PyTypeObject.tp_iter - An optional pointer to a function that returns an iterator for the object. Its - presence normally signals that the instances of this type are iterable (although - sequences may be iterable without this function). + An optional pointer to a function that returns an :term:`iterator` for the + object. Its presence normally signals that the instances of this type are + :term:`iterable` (although sequences may be iterable without this function). This function has the same signature as :c:func:`PyObject_GetIter`:: @@ -1526,8 +1535,8 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: iternextfunc PyTypeObject.tp_iternext - An optional pointer to a function that returns the next item in an iterator. - The signature is:: + An optional pointer to a function that returns the next item in an + :term:`iterator`. The signature is:: PyObject *tp_iternext(PyObject *self); @@ -2419,8 +2428,8 @@ Async Object Structures PyObject *am_await(PyObject *self); - The returned object must be an iterator, i.e. :c:func:`PyIter_Check` must - return ``1`` for it. + The returned object must be an :term:`iterator`, i.e. :c:func:`PyIter_Check` + must return ``1`` for it. This slot may be set to ``NULL`` if an object is not an :term:`awaitable`. @@ -2453,6 +2462,8 @@ Async Object Structures See :c:func:`PyIter_Send` for details. This slot may be set to ``NULL``. + .. versionadded:: 3.10 + .. _slot-typedefs: diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 8d4eef87db9fb6..343eaf1444df6f 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -149,7 +149,7 @@ access internal read-only data of Unicode objects: ``PyUnicode_WCHAR_KIND`` is deprecated. -.. c:function:: int PyUnicode_KIND(PyObject *o) +.. c:function:: unsigned int PyUnicode_KIND(PyObject *o) Return one of the PyUnicode kind constants (see above) that indicate how many bytes per character this Unicode object uses to store its data. *o* has to @@ -268,57 +268,57 @@ are available through these macros which are mapped to C functions depending on the Python configuration. -.. c:function:: int Py_UNICODE_ISSPACE(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISSPACE(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a whitespace character. -.. c:function:: int Py_UNICODE_ISLOWER(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISLOWER(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a lowercase character. -.. c:function:: int Py_UNICODE_ISUPPER(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISUPPER(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is an uppercase character. -.. c:function:: int Py_UNICODE_ISTITLE(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISTITLE(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a titlecase character. -.. c:function:: int Py_UNICODE_ISLINEBREAK(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISLINEBREAK(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a linebreak character. -.. c:function:: int Py_UNICODE_ISDECIMAL(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISDECIMAL(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a decimal character. -.. c:function:: int Py_UNICODE_ISDIGIT(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISDIGIT(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a digit character. -.. c:function:: int Py_UNICODE_ISNUMERIC(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISNUMERIC(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a numeric character. -.. c:function:: int Py_UNICODE_ISALPHA(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISALPHA(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is an alphabetic character. -.. c:function:: int Py_UNICODE_ISALNUM(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISALNUM(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is an alphanumeric character. -.. c:function:: int Py_UNICODE_ISPRINTABLE(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_ISPRINTABLE(Py_UCS4 ch) Return ``1`` or ``0`` depending on whether *ch* is a printable character. Nonprintable characters are those characters defined in the Unicode character @@ -332,7 +332,7 @@ the Python configuration. These APIs can be used for fast direct character conversions: -.. c:function:: Py_UNICODE Py_UNICODE_TOLOWER(Py_UNICODE ch) +.. c:function:: Py_UCS4 Py_UNICODE_TOLOWER(Py_UCS4 ch) Return the character *ch* converted to lower case. @@ -340,7 +340,7 @@ These APIs can be used for fast direct character conversions: This function uses simple case mappings. -.. c:function:: Py_UNICODE Py_UNICODE_TOUPPER(Py_UNICODE ch) +.. c:function:: Py_UCS4 Py_UNICODE_TOUPPER(Py_UCS4 ch) Return the character *ch* converted to upper case. @@ -348,7 +348,7 @@ These APIs can be used for fast direct character conversions: This function uses simple case mappings. -.. c:function:: Py_UNICODE Py_UNICODE_TOTITLE(Py_UNICODE ch) +.. c:function:: Py_UCS4 Py_UNICODE_TOTITLE(Py_UCS4 ch) Return the character *ch* converted to title case. @@ -356,19 +356,19 @@ These APIs can be used for fast direct character conversions: This function uses simple case mappings. -.. c:function:: int Py_UNICODE_TODECIMAL(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_TODECIMAL(Py_UCS4 ch) Return the character *ch* converted to a decimal positive integer. Return ``-1`` if this is not possible. This macro does not raise exceptions. -.. c:function:: int Py_UNICODE_TODIGIT(Py_UNICODE ch) +.. c:function:: int Py_UNICODE_TODIGIT(Py_UCS4 ch) Return the character *ch* converted to a single digit integer. Return ``-1`` if this is not possible. This macro does not raise exceptions. -.. c:function:: double Py_UNICODE_TONUMERIC(Py_UNICODE ch) +.. c:function:: double Py_UNICODE_TONUMERIC(Py_UCS4 ch) Return the character *ch* converted to a double. Return ``-1.0`` if this is not possible. This macro does not raise exceptions. diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 0f760eaa7ad578..3354a2b976f343 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -185,42 +185,6 @@ the same library that the Python runtime is using. :c:func:`PyMem_RawRealloc`, instead of being allocated by :c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`. - -.. c:function:: struct _node* PyParser_SimpleParseString(const char *str, int start) - - This is a simplified interface to - :c:func:`PyParser_SimpleParseStringFlagsFilename` below, leaving *filename* set - to ``NULL`` and *flags* set to ``0``. - - -.. c:function:: struct _node* PyParser_SimpleParseStringFlags( const char *str, int start, int flags) - - This is a simplified interface to - :c:func:`PyParser_SimpleParseStringFlagsFilename` below, leaving *filename* set - to ``NULL``. - - -.. c:function:: struct _node* PyParser_SimpleParseStringFlagsFilename( const char *str, const char *filename, int start, int flags) - - Parse Python source code from *str* using the start token *start* according to - the *flags* argument. The result can be used to create a code object which can - be evaluated efficiently. This is useful if a code fragment must be evaluated - many times. *filename* is decoded from the :term:`filesystem encoding and - error handler`. - - -.. c:function:: struct _node* PyParser_SimpleParseFile(FILE *fp, const char *filename, int start) - - This is a simplified interface to :c:func:`PyParser_SimpleParseFileFlags` below, - leaving *flags* set to ``0``. - - -.. c:function:: struct _node* PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int flags) - - Similar to :c:func:`PyParser_SimpleParseStringFlagsFilename`, but the Python - source code is read from *fp* instead of an in-memory string. - - .. c:function:: PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals) This is a simplified interface to :c:func:`PyRun_StringFlags` below, leaving diff --git a/Doc/conf.py b/Doc/conf.py index cf250981f58752..cbf201a314eec7 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -69,7 +69,8 @@ html_theme_path = ['tools'] html_theme_options = { 'collapsiblesidebar': True, - 'issues_url': 'https://docs.python.org/3/bugs.html', + 'issues_url': '/bugs.html', + 'license_url': '/license.html', 'root_include_title': False # We use the version switcher instead. } @@ -85,7 +86,7 @@ # Custom sidebar templates, filenames relative to this file. html_sidebars = { - # Defaults taken from http://www.sphinx-doc.org/en/stable/config.html#confval-html_sidebars + # Defaults taken from https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_sidebars # Removes the quick search block '**': ['localtoc.html', 'relations.html', 'customsourcelink.html'], 'index': ['indexsidebar.html'], @@ -225,8 +226,9 @@ # Options for extensions # ---------------------- -# Relative filename of the reference count data file. +# Relative filename of the data files refcount_file = 'data/refcounts.dat' +stable_abi_file = 'data/stable_abi.dat' # Sphinx 2 and Sphinx 3 compatibility # ----------------------------------- diff --git a/Doc/copyright.rst b/Doc/copyright.rst index 4191c0bb63a2c1..e64a49328b4723 100644 --- a/Doc/copyright.rst +++ b/Doc/copyright.rst @@ -4,7 +4,7 @@ Copyright Python and this documentation is: -Copyright © 2001-2021 Python Software Foundation. All rights reserved. +Copyright © 2001-2022 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff --git a/Doc/data/python3.10.abi b/Doc/data/python3.10.abi new file mode 100644 index 00000000000000..b7886ae28f7007 --- /dev/null +++ b/Doc/data/python3.10.abi @@ -0,0 +1,20719 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 505f1203dd1bdd..89b64e6c083155 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1073,8 +1073,8 @@ PyInterpreterState_New:PyInterpreterState*::: PyIter_Check:int::: PyIter_Check:PyObject*:o:0: -PyAiter_Check:int::: -PyAiter_Check:PyObject*:o:0: +PyAIter_Check:int::: +PyAIter_Check:PyObject*:o:0: PyIter_Next:PyObject*::+1: PyIter_Next:PyObject*:o:0: @@ -1571,6 +1571,21 @@ PyOS_FSPath:PyObject*:path:0: PyObject_ASCII:PyObject*::+1: PyObject_ASCII:PyObject*:o:0: +PyObject_AsCharBuffer:int::: +PyObject_AsCharBuffer:PyObject*:obj:0: +PyObject_AsCharBuffer:const char**:buffer:: +PyObject_AsCharBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsReadBuffer:int::: +PyObject_AsReadBuffer:PyObject*:obj:0: +PyObject_AsReadBuffer:const void**:buffer:: +PyObject_AsReadBuffer:Py_ssize_t*:buffer_len:: + +PyObject_AsWriteBuffer:int::: +PyObject_AsWriteBuffer:PyObject*:obj:0: +PyObject_AsWriteBuffer:void**:buffer:: +PyObject_AsWriteBuffer:Py_ssize_t*:buffer_len:: + PyObject_Bytes:PyObject*::+1: PyObject_Bytes:PyObject*:o:0: @@ -1606,6 +1621,9 @@ PyObject_CallObject:PyObject*:args:0: PyObject_CheckBuffer:int::: PyObject_CheckBuffer:PyObject*:obj:0: +PyObject_CheckReadBuffer:int::: +PyObject_CheckReadBuffer:PyObject*:o:0: + PyObject_DelAttr:int::: PyObject_DelAttr:PyObject*:o:0: PyObject_DelAttr:PyObject*:attr_name:0: @@ -1682,8 +1700,8 @@ PyObject_GetItem:PyObject*:key:0: PyObject_GetIter:PyObject*::+1: PyObject_GetIter:PyObject*:o:0: -PyObject_GetAiter:PyObject*::+1: -PyObject_GetAiter:PyObject*:o:0: +PyObject_GetAIter:PyObject*::+1: +PyObject_GetAIter:PyObject*:o:0: PyObject_HasAttr:int::: PyObject_HasAttr:PyObject*:o:0: @@ -1791,32 +1809,6 @@ PyObject_TypeCheck:int::: PyObject_TypeCheck:PyObject*:o:0: PyObject_TypeCheck:PyTypeObject*:type:0: -PyParser_SimpleParseFile:struct _node*::: -PyParser_SimpleParseFile:FILE*:fp:: -PyParser_SimpleParseFile:const char*:filename:: -PyParser_SimpleParseFile:int:start:: - -PyParser_SimpleParseFileFlags:struct _node*::: -PyParser_SimpleParseFileFlags:FILE*:fp:: -PyParser_SimpleParseFileFlags:const char*:filename:: -PyParser_SimpleParseFileFlags:int:start:: -PyParser_SimpleParseFileFlags:int:flags:: - -PyParser_SimpleParseString:struct _node*::: -PyParser_SimpleParseString:const char*:str:: -PyParser_SimpleParseString:int:start:: - -PyParser_SimpleParseStringFlags:struct _node*::: -PyParser_SimpleParseStringFlags:const char*:str:: -PyParser_SimpleParseStringFlags:int:start:: -PyParser_SimpleParseStringFlags:int:flags:: - -PyParser_SimpleParseStringFlagsFilename:struct _node*::: -PyParser_SimpleParseStringFlagsFilename:const char*:str:: -PyParser_SimpleParseStringFlagsFilename:const char*:filename:: -PyParser_SimpleParseStringFlagsFilename:int:start:: -PyParser_SimpleParseStringFlagsFilename:int:flags:: - PyRun_AnyFile:int::: PyRun_AnyFile:FILE*:fp:: PyRun_AnyFile:const char*:filename:: diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 833228f7fd755d..ea102b989c8649 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -1,953 +1,863 @@ -# Generated by Tools/scripts/stable_abi.py - -METH_CLASS -METH_COEXIST -METH_FASTCALL -METH_METHOD -METH_NOARGS -METH_O -METH_STATIC -METH_VARARGS -PyAiter_Check -PyArg_Parse -PyArg_ParseTuple -PyArg_ParseTupleAndKeywords -PyArg_UnpackTuple -PyArg_VaParse -PyArg_VaParseTupleAndKeywords -PyArg_ValidateKeywordArguments -PyBaseObject_Type -PyBool_FromLong -PyBool_Type -PyByteArrayIter_Type -PyByteArray_AsString -PyByteArray_Concat -PyByteArray_FromObject -PyByteArray_FromStringAndSize -PyByteArray_Resize -PyByteArray_Size -PyByteArray_Type -PyBytesIter_Type -PyBytes_AsString -PyBytes_AsStringAndSize -PyBytes_Concat -PyBytes_ConcatAndDel -PyBytes_DecodeEscape -PyBytes_FromFormat -PyBytes_FromFormatV -PyBytes_FromObject -PyBytes_FromString -PyBytes_FromStringAndSize -PyBytes_Repr -PyBytes_Size -PyBytes_Type -PyCFunction -PyCFunctionWithKeywords -PyCFunction_Call -PyCFunction_GetFlags -PyCFunction_GetFunction -PyCFunction_GetSelf -PyCFunction_New -PyCFunction_NewEx -PyCFunction_Type -PyCMethod_New -PyCallIter_New -PyCallIter_Type -PyCallable_Check -PyCapsule_Destructor -PyCapsule_GetContext -PyCapsule_GetDestructor -PyCapsule_GetName -PyCapsule_GetPointer -PyCapsule_Import -PyCapsule_IsValid -PyCapsule_New -PyCapsule_SetContext -PyCapsule_SetDestructor -PyCapsule_SetName -PyCapsule_SetPointer -PyCapsule_Type -PyClassMethodDescr_Type -PyCodec_BackslashReplaceErrors -PyCodec_Decode -PyCodec_Decoder -PyCodec_Encode -PyCodec_Encoder -PyCodec_IgnoreErrors -PyCodec_IncrementalDecoder -PyCodec_IncrementalEncoder -PyCodec_KnownEncoding -PyCodec_LookupError -PyCodec_NameReplaceErrors -PyCodec_Register -PyCodec_RegisterError -PyCodec_ReplaceErrors -PyCodec_StreamReader -PyCodec_StreamWriter -PyCodec_StrictErrors -PyCodec_Unregister -PyCodec_XMLCharRefReplaceErrors -PyComplex_FromDoubles -PyComplex_ImagAsDouble -PyComplex_RealAsDouble -PyComplex_Type -PyDescr_NewClassMethod -PyDescr_NewGetSet -PyDescr_NewMember -PyDescr_NewMethod -PyDictItems_Type -PyDictIterItem_Type -PyDictIterKey_Type -PyDictIterValue_Type -PyDictKeys_Type -PyDictProxy_New -PyDictProxy_Type -PyDictRevIterItem_Type -PyDictRevIterKey_Type -PyDictRevIterValue_Type -PyDictValues_Type -PyDict_Clear -PyDict_Contains -PyDict_Copy -PyDict_DelItem -PyDict_DelItemString -PyDict_GetItem -PyDict_GetItemString -PyDict_GetItemWithError -PyDict_Items -PyDict_Keys -PyDict_Merge -PyDict_MergeFromSeq2 -PyDict_New -PyDict_Next -PyDict_SetItem -PyDict_SetItemString -PyDict_Size -PyDict_Type -PyDict_Update -PyDict_Values -PyEllipsis_Type -PyEnum_Type -PyErr_BadArgument -PyErr_BadInternalCall -PyErr_CheckSignals -PyErr_Clear -PyErr_Display -PyErr_ExceptionMatches -PyErr_Fetch -PyErr_Format -PyErr_FormatV -PyErr_GetExcInfo -PyErr_GivenExceptionMatches -PyErr_NewException -PyErr_NewExceptionWithDoc -PyErr_NoMemory -PyErr_NormalizeException -PyErr_Occurred -PyErr_Print -PyErr_PrintEx -PyErr_ProgramText -PyErr_ResourceWarning -PyErr_Restore -PyErr_SetExcFromWindowsErr -PyErr_SetExcFromWindowsErrWithFilename -PyErr_SetExcFromWindowsErrWithFilenameObject -PyErr_SetExcFromWindowsErrWithFilenameObjects -PyErr_SetExcInfo -PyErr_SetFromErrno -PyErr_SetFromErrnoWithFilename -PyErr_SetFromErrnoWithFilenameObject -PyErr_SetFromErrnoWithFilenameObjects -PyErr_SetFromWindowsErr -PyErr_SetFromWindowsErrWithFilename -PyErr_SetImportError -PyErr_SetImportErrorSubclass -PyErr_SetInterrupt -PyErr_SetInterruptEx -PyErr_SetNone -PyErr_SetObject -PyErr_SetString -PyErr_SyntaxLocation -PyErr_SyntaxLocationEx -PyErr_WarnEx -PyErr_WarnExplicit -PyErr_WarnFormat -PyErr_WriteUnraisable -PyEval_AcquireLock -PyEval_AcquireThread -PyEval_CallFunction -PyEval_CallMethod -PyEval_CallObjectWithKeywords -PyEval_EvalCode -PyEval_EvalCodeEx -PyEval_EvalFrame -PyEval_EvalFrameEx -PyEval_GetBuiltins -PyEval_GetFrame -PyEval_GetFuncDesc -PyEval_GetFuncName -PyEval_GetGlobals -PyEval_GetLocals -PyEval_InitThreads -PyEval_ReleaseLock -PyEval_ReleaseThread -PyEval_RestoreThread -PyEval_SaveThread -PyEval_ThreadsInitialized -PyExc_ArithmeticError -PyExc_AssertionError -PyExc_AttributeError -PyExc_BaseException -PyExc_BlockingIOError -PyExc_BrokenPipeError -PyExc_BufferError -PyExc_BytesWarning -PyExc_ChildProcessError -PyExc_ConnectionAbortedError -PyExc_ConnectionError -PyExc_ConnectionRefusedError -PyExc_ConnectionResetError -PyExc_DeprecationWarning -PyExc_EOFError -PyExc_EncodingWarning -PyExc_EnvironmentError -PyExc_Exception -PyExc_FileExistsError -PyExc_FileNotFoundError -PyExc_FloatingPointError -PyExc_FutureWarning -PyExc_GeneratorExit -PyExc_IOError -PyExc_ImportError -PyExc_ImportWarning -PyExc_IndentationError -PyExc_IndexError -PyExc_InterruptedError -PyExc_IsADirectoryError -PyExc_KeyError -PyExc_KeyboardInterrupt -PyExc_LookupError -PyExc_MemoryError -PyExc_ModuleNotFoundError -PyExc_NameError -PyExc_NotADirectoryError -PyExc_NotImplementedError -PyExc_OSError -PyExc_OverflowError -PyExc_PendingDeprecationWarning -PyExc_PermissionError -PyExc_ProcessLookupError -PyExc_RecursionError -PyExc_ReferenceError -PyExc_ResourceWarning -PyExc_RuntimeError -PyExc_RuntimeWarning -PyExc_StopAsyncIteration -PyExc_StopIteration -PyExc_SyntaxError -PyExc_SyntaxWarning -PyExc_SystemError -PyExc_SystemExit -PyExc_TabError -PyExc_TimeoutError -PyExc_TypeError -PyExc_UnboundLocalError -PyExc_UnicodeDecodeError -PyExc_UnicodeEncodeError -PyExc_UnicodeError -PyExc_UnicodeTranslateError -PyExc_UnicodeWarning -PyExc_UserWarning -PyExc_ValueError -PyExc_Warning -PyExc_WindowsError -PyExc_ZeroDivisionError -PyExceptionClass_Name -PyException_GetCause -PyException_GetContext -PyException_GetTraceback -PyException_SetCause -PyException_SetContext -PyException_SetTraceback -PyFile_FromFd -PyFile_GetLine -PyFile_WriteObject -PyFile_WriteString -PyFilter_Type -PyFloat_AsDouble -PyFloat_FromDouble -PyFloat_FromString -PyFloat_GetInfo -PyFloat_GetMax -PyFloat_GetMin -PyFloat_Type -PyFrame_GetCode -PyFrame_GetLineNumber -PyFrozenSet_New -PyFrozenSet_Type -PyGC_Collect -PyGC_Disable -PyGC_Enable -PyGC_IsEnabled -PyGILState_Ensure -PyGILState_GetThisThreadState -PyGILState_Release -PyGILState_STATE -PyGetSetDef -PyGetSetDescr_Type -PyImport_AddModule -PyImport_AddModuleObject -PyImport_AppendInittab -PyImport_ExecCodeModule -PyImport_ExecCodeModuleEx -PyImport_ExecCodeModuleObject -PyImport_ExecCodeModuleWithPathnames -PyImport_GetImporter -PyImport_GetMagicNumber -PyImport_GetMagicTag -PyImport_GetModule -PyImport_GetModuleDict -PyImport_Import -PyImport_ImportFrozenModule -PyImport_ImportFrozenModuleObject -PyImport_ImportModule -PyImport_ImportModuleLevel -PyImport_ImportModuleLevelObject -PyImport_ImportModuleNoBlock -PyImport_ReloadModule -PyIndex_Check -PyInterpreterState -PyInterpreterState_Clear -PyInterpreterState_Delete -PyInterpreterState_Get -PyInterpreterState_GetDict -PyInterpreterState_GetID -PyInterpreterState_New -PyIter_Check -PyIter_Next -PyIter_Send -PyListIter_Type -PyListRevIter_Type -PyList_Append -PyList_AsTuple -PyList_GetItem -PyList_GetSlice -PyList_Insert -PyList_New -PyList_Reverse -PyList_SetItem -PyList_SetSlice -PyList_Size -PyList_Sort -PyList_Type -PyLongObject -PyLongRangeIter_Type -PyLong_AsDouble -PyLong_AsLong -PyLong_AsLongAndOverflow -PyLong_AsLongLong -PyLong_AsLongLongAndOverflow -PyLong_AsSize_t -PyLong_AsSsize_t -PyLong_AsUnsignedLong -PyLong_AsUnsignedLongLong -PyLong_AsUnsignedLongLongMask -PyLong_AsUnsignedLongMask -PyLong_AsVoidPtr -PyLong_FromDouble -PyLong_FromLong -PyLong_FromLongLong -PyLong_FromSize_t -PyLong_FromSsize_t -PyLong_FromString -PyLong_FromUnsignedLong -PyLong_FromUnsignedLongLong -PyLong_FromVoidPtr -PyLong_GetInfo -PyLong_Type -PyMap_Type -PyMapping_Check -PyMapping_GetItemString -PyMapping_HasKey -PyMapping_HasKeyString -PyMapping_Items -PyMapping_Keys -PyMapping_Length -PyMapping_SetItemString -PyMapping_Size -PyMapping_Values -PyMem_Calloc -PyMem_Free -PyMem_Malloc -PyMem_Realloc -PyMemberDef -PyMemberDescr_Type -PyMemoryView_FromMemory -PyMemoryView_FromObject -PyMemoryView_GetContiguous -PyMemoryView_Type -PyMethodDef -PyMethodDescr_Type -PyModuleDef -PyModuleDef_Base -PyModuleDef_Init -PyModuleDef_Type -PyModule_AddFunctions -PyModule_AddIntConstant -PyModule_AddObject -PyModule_AddObjectRef -PyModule_AddStringConstant -PyModule_AddType -PyModule_Create2 -PyModule_ExecDef -PyModule_FromDefAndSpec2 -PyModule_GetDef -PyModule_GetDict -PyModule_GetFilename -PyModule_GetFilenameObject -PyModule_GetName -PyModule_GetNameObject -PyModule_GetState -PyModule_New -PyModule_NewObject -PyModule_SetDocString -PyModule_Type -PyNumber_Absolute -PyNumber_Add -PyNumber_And -PyNumber_AsSsize_t -PyNumber_Check -PyNumber_Divmod -PyNumber_Float -PyNumber_FloorDivide -PyNumber_InPlaceAdd -PyNumber_InPlaceAnd -PyNumber_InPlaceFloorDivide -PyNumber_InPlaceLshift -PyNumber_InPlaceMatrixMultiply -PyNumber_InPlaceMultiply -PyNumber_InPlaceOr -PyNumber_InPlacePower -PyNumber_InPlaceRemainder -PyNumber_InPlaceRshift -PyNumber_InPlaceSubtract -PyNumber_InPlaceTrueDivide -PyNumber_InPlaceXor -PyNumber_Index -PyNumber_Invert -PyNumber_Long -PyNumber_Lshift -PyNumber_MatrixMultiply -PyNumber_Multiply -PyNumber_Negative -PyNumber_Or -PyNumber_Positive -PyNumber_Power -PyNumber_Remainder -PyNumber_Rshift -PyNumber_Subtract -PyNumber_ToBase -PyNumber_TrueDivide -PyNumber_Xor -PyOS_AfterFork -PyOS_AfterFork_Child -PyOS_AfterFork_Parent -PyOS_BeforeFork -PyOS_CheckStack -PyOS_FSPath -PyOS_InputHook -PyOS_InterruptOccurred -PyOS_double_to_string -PyOS_getsig -PyOS_mystricmp -PyOS_mystrnicmp -PyOS_setsig -PyOS_sighandler_t -PyOS_snprintf -PyOS_string_to_double -PyOS_strtol -PyOS_strtoul -PyOS_vsnprintf -PyObject -PyObject_ASCII -PyObject_AsFileDescriptor -PyObject_Bytes -PyObject_Call -PyObject_CallFunction -PyObject_CallFunctionObjArgs -PyObject_CallMethod -PyObject_CallMethodObjArgs -PyObject_CallNoArgs -PyObject_CallObject -PyObject_Calloc -PyObject_ClearWeakRefs -PyObject_DelItem -PyObject_DelItemString -PyObject_Dir -PyObject_Format -PyObject_Free -PyObject_GC_Del -PyObject_GC_IsFinalized -PyObject_GC_IsTracked -PyObject_GC_Track -PyObject_GC_UnTrack -PyObject_GenericGetAttr -PyObject_GenericGetDict -PyObject_GenericSetAttr -PyObject_GenericSetDict -PyObject_GetAiter -PyObject_GetAttr -PyObject_GetAttrString -PyObject_GetItem -PyObject_GetIter -PyObject_HasAttr -PyObject_HasAttrString -PyObject_Hash -PyObject_HashNotImplemented -PyObject_Init -PyObject_InitVar -PyObject_IsInstance -PyObject_IsSubclass -PyObject_IsTrue -PyObject_Length -PyObject_Malloc -PyObject_Not -PyObject_Realloc -PyObject_Repr -PyObject_RichCompare -PyObject_RichCompareBool -PyObject_SelfIter -PyObject_SetAttr -PyObject_SetAttrString -PyObject_SetItem -PyObject_Size -PyObject_Str -PyObject_Type -PyProperty_Type -PyRangeIter_Type -PyRange_Type -PyReversed_Type -PySeqIter_New -PySeqIter_Type -PySequence_Check -PySequence_Concat -PySequence_Contains -PySequence_Count -PySequence_DelItem -PySequence_DelSlice -PySequence_Fast -PySequence_GetItem -PySequence_GetSlice -PySequence_In -PySequence_InPlaceConcat -PySequence_InPlaceRepeat -PySequence_Index -PySequence_Length -PySequence_List -PySequence_Repeat -PySequence_SetItem -PySequence_SetSlice -PySequence_Size -PySequence_Tuple -PySetIter_Type -PySet_Add -PySet_Clear -PySet_Contains -PySet_Discard -PySet_New -PySet_Pop -PySet_Size -PySet_Type -PySlice_AdjustIndices -PySlice_GetIndices -PySlice_GetIndicesEx -PySlice_New -PySlice_Type -PySlice_Unpack -PyState_AddModule -PyState_FindModule -PyState_RemoveModule -PyStructSequence_Desc -PyStructSequence_Field -PyStructSequence_GetItem -PyStructSequence_New -PyStructSequence_NewType -PyStructSequence_SetItem -PySuper_Type -PySys_AddWarnOption -PySys_AddWarnOptionUnicode -PySys_AddXOption -PySys_FormatStderr -PySys_FormatStdout -PySys_GetObject -PySys_GetXOptions -PySys_HasWarnOptions -PySys_ResetWarnOptions -PySys_SetArgv -PySys_SetArgvEx -PySys_SetObject -PySys_SetPath -PySys_WriteStderr -PySys_WriteStdout -PyThreadState -PyThreadState_Clear -PyThreadState_Delete -PyThreadState_Get -PyThreadState_GetDict -PyThreadState_GetFrame -PyThreadState_GetID -PyThreadState_GetInterpreter -PyThreadState_New -PyThreadState_SetAsyncExc -PyThreadState_Swap -PyThread_GetInfo -PyThread_ReInitTLS -PyThread_acquire_lock -PyThread_acquire_lock_timed -PyThread_allocate_lock -PyThread_create_key -PyThread_delete_key -PyThread_delete_key_value -PyThread_exit_thread -PyThread_free_lock -PyThread_get_key_value -PyThread_get_stacksize -PyThread_get_thread_ident -PyThread_get_thread_native_id -PyThread_init_thread -PyThread_release_lock -PyThread_set_key_value -PyThread_set_stacksize -PyThread_start_new_thread -PyThread_tss_alloc -PyThread_tss_create -PyThread_tss_delete -PyThread_tss_free -PyThread_tss_get -PyThread_tss_is_created -PyThread_tss_set -PyTraceBack_Here -PyTraceBack_Print -PyTraceBack_Type -PyTupleIter_Type -PyTuple_GetItem -PyTuple_GetSlice -PyTuple_New -PyTuple_Pack -PyTuple_SetItem -PyTuple_Size -PyTuple_Type -PyTypeObject -PyType_ClearCache -PyType_FromModuleAndSpec -PyType_FromSpec -PyType_FromSpecWithBases -PyType_GenericAlloc -PyType_GenericNew -PyType_GetFlags -PyType_GetModule -PyType_GetModuleState -PyType_GetSlot -PyType_IsSubtype -PyType_Modified -PyType_Ready -PyType_Slot -PyType_Spec -PyType_Type -PyUnicodeDecodeError_Create -PyUnicodeDecodeError_GetEncoding -PyUnicodeDecodeError_GetEnd -PyUnicodeDecodeError_GetObject -PyUnicodeDecodeError_GetReason -PyUnicodeDecodeError_GetStart -PyUnicodeDecodeError_SetEnd -PyUnicodeDecodeError_SetReason -PyUnicodeDecodeError_SetStart -PyUnicodeEncodeError_GetEncoding -PyUnicodeEncodeError_GetEnd -PyUnicodeEncodeError_GetObject -PyUnicodeEncodeError_GetReason -PyUnicodeEncodeError_GetStart -PyUnicodeEncodeError_SetEnd -PyUnicodeEncodeError_SetReason -PyUnicodeEncodeError_SetStart -PyUnicodeIter_Type -PyUnicodeTranslateError_GetEnd -PyUnicodeTranslateError_GetObject -PyUnicodeTranslateError_GetReason -PyUnicodeTranslateError_GetStart -PyUnicodeTranslateError_SetEnd -PyUnicodeTranslateError_SetReason -PyUnicodeTranslateError_SetStart -PyUnicode_Append -PyUnicode_AppendAndDel -PyUnicode_AsASCIIString -PyUnicode_AsCharmapString -PyUnicode_AsDecodedObject -PyUnicode_AsDecodedUnicode -PyUnicode_AsEncodedObject -PyUnicode_AsEncodedString -PyUnicode_AsEncodedUnicode -PyUnicode_AsLatin1String -PyUnicode_AsMBCSString -PyUnicode_AsRawUnicodeEscapeString -PyUnicode_AsUCS4 -PyUnicode_AsUCS4Copy -PyUnicode_AsUTF16String -PyUnicode_AsUTF32String -PyUnicode_AsUTF8AndSize -PyUnicode_AsUTF8String -PyUnicode_AsUnicodeEscapeString -PyUnicode_AsWideChar -PyUnicode_AsWideCharString -PyUnicode_BuildEncodingMap -PyUnicode_Compare -PyUnicode_CompareWithASCIIString -PyUnicode_Concat -PyUnicode_Contains -PyUnicode_Count -PyUnicode_Decode -PyUnicode_DecodeASCII -PyUnicode_DecodeCharmap -PyUnicode_DecodeCodePageStateful -PyUnicode_DecodeFSDefault -PyUnicode_DecodeFSDefaultAndSize -PyUnicode_DecodeLatin1 -PyUnicode_DecodeLocale -PyUnicode_DecodeLocaleAndSize -PyUnicode_DecodeMBCS -PyUnicode_DecodeMBCSStateful -PyUnicode_DecodeRawUnicodeEscape -PyUnicode_DecodeUTF16 -PyUnicode_DecodeUTF16Stateful -PyUnicode_DecodeUTF32 -PyUnicode_DecodeUTF32Stateful -PyUnicode_DecodeUTF7 -PyUnicode_DecodeUTF7Stateful -PyUnicode_DecodeUTF8 -PyUnicode_DecodeUTF8Stateful -PyUnicode_DecodeUnicodeEscape -PyUnicode_EncodeCodePage -PyUnicode_EncodeFSDefault -PyUnicode_EncodeLocale -PyUnicode_FSConverter -PyUnicode_FSDecoder -PyUnicode_Find -PyUnicode_FindChar -PyUnicode_Format -PyUnicode_FromEncodedObject -PyUnicode_FromFormat -PyUnicode_FromFormatV -PyUnicode_FromObject -PyUnicode_FromOrdinal -PyUnicode_FromString -PyUnicode_FromStringAndSize -PyUnicode_FromWideChar -PyUnicode_GetDefaultEncoding -PyUnicode_GetLength -PyUnicode_GetSize -PyUnicode_InternFromString -PyUnicode_InternImmortal -PyUnicode_InternInPlace -PyUnicode_IsIdentifier -PyUnicode_Join -PyUnicode_Partition -PyUnicode_RPartition -PyUnicode_RSplit -PyUnicode_ReadChar -PyUnicode_Replace -PyUnicode_Resize -PyUnicode_RichCompare -PyUnicode_Split -PyUnicode_Splitlines -PyUnicode_Substring -PyUnicode_Tailmatch -PyUnicode_Translate -PyUnicode_Type -PyUnicode_WriteChar -PyVarObject -PyWeakReference -PyWeakref_GetObject -PyWeakref_NewProxy -PyWeakref_NewRef -PyWrapperDescr_Type -PyWrapper_New -PyZip_Type -Py_AddPendingCall -Py_AtExit -Py_BEGIN_ALLOW_THREADS -Py_BLOCK_THREADS -Py_BuildValue -Py_BytesMain -Py_CompileString -Py_DecRef -Py_DecodeLocale -Py_END_ALLOW_THREADS -Py_EncodeLocale -Py_EndInterpreter -Py_EnterRecursiveCall -Py_Exit -Py_FatalError -Py_FileSystemDefaultEncodeErrors -Py_FileSystemDefaultEncoding -Py_Finalize -Py_FinalizeEx -Py_FrozenMain -Py_GenericAlias -Py_GenericAliasType -Py_GetBuildInfo -Py_GetCompiler -Py_GetCopyright -Py_GetExecPrefix -Py_GetPath -Py_GetPlatform -Py_GetPrefix -Py_GetProgramFullPath -Py_GetProgramName -Py_GetPythonHome -Py_GetRecursionLimit -Py_GetVersion -Py_HasFileSystemDefaultEncoding -Py_IncRef -Py_Initialize -Py_InitializeEx -Py_Is -Py_IsFalse -Py_IsInitialized -Py_IsNone -Py_IsTrue -Py_LeaveRecursiveCall -Py_Main -Py_MakePendingCalls -Py_NewInterpreter -Py_NewRef -Py_ReprEnter -Py_ReprLeave -Py_SetPath -Py_SetProgramName -Py_SetPythonHome -Py_SetRecursionLimit -Py_TPFLAGS_BASETYPE -Py_TPFLAGS_DEFAULT -Py_TPFLAGS_HAVE_GC -Py_TPFLAGS_METHOD_DESCRIPTOR -Py_UCS4 -Py_UNBLOCK_THREADS -Py_UTF8Mode -Py_VaBuildValue -Py_XNewRef -Py_am_aiter -Py_am_anext -Py_am_await -Py_am_send -Py_intptr_t -Py_mp_ass_subscript -Py_mp_length -Py_mp_subscript -Py_nb_absolute -Py_nb_add -Py_nb_and -Py_nb_bool -Py_nb_divmod -Py_nb_float -Py_nb_floor_divide -Py_nb_index -Py_nb_inplace_add -Py_nb_inplace_and -Py_nb_inplace_floor_divide -Py_nb_inplace_lshift -Py_nb_inplace_matrix_multiply -Py_nb_inplace_multiply -Py_nb_inplace_or -Py_nb_inplace_power -Py_nb_inplace_remainder -Py_nb_inplace_rshift -Py_nb_inplace_subtract -Py_nb_inplace_true_divide -Py_nb_inplace_xor -Py_nb_int -Py_nb_invert -Py_nb_lshift -Py_nb_matrix_multiply -Py_nb_multiply -Py_nb_negative -Py_nb_or -Py_nb_positive -Py_nb_power -Py_nb_remainder -Py_nb_rshift -Py_nb_subtract -Py_nb_true_divide -Py_nb_xor -Py_sq_ass_item -Py_sq_concat -Py_sq_contains -Py_sq_inplace_concat -Py_sq_inplace_repeat -Py_sq_item -Py_sq_length -Py_sq_repeat -Py_ssize_t -Py_tp_alloc -Py_tp_base -Py_tp_bases -Py_tp_call -Py_tp_clear -Py_tp_dealloc -Py_tp_del -Py_tp_descr_get -Py_tp_descr_set -Py_tp_doc -Py_tp_finalize -Py_tp_free -Py_tp_getattr -Py_tp_getattro -Py_tp_getset -Py_tp_hash -Py_tp_init -Py_tp_is_gc -Py_tp_iter -Py_tp_iternext -Py_tp_members -Py_tp_methods -Py_tp_new -Py_tp_repr -Py_tp_richcompare -Py_tp_setattr -Py_tp_setattro -Py_tp_str -Py_tp_traverse -Py_uintptr_t -_frame -_node -allocfunc -binaryfunc -descrgetfunc -descrsetfunc -destructor -getattrfunc -getattrofunc -getiterfunc -getter -hashfunc -initproc -inquiry -iternextfunc -lenfunc -newfunc -objobjargproc -objobjproc -reprfunc -richcmpfunc -setattrfunc -setattrofunc -setter -ssizeargfunc -ssizeobjargproc -ssizessizeargfunc -ssizessizeobjargproc -symtable -ternaryfunc -traverseproc -unaryfunc -visitproc +role,name,added,ifdef_note +function,PyAIter_Check,3.10, +function,PyArg_Parse,3.2, +function,PyArg_ParseTuple,3.2, +function,PyArg_ParseTupleAndKeywords,3.2, +function,PyArg_UnpackTuple,3.2, +function,PyArg_VaParse,3.2, +function,PyArg_VaParseTupleAndKeywords,3.2, +function,PyArg_ValidateKeywordArguments,3.2, +var,PyBaseObject_Type,3.2, +function,PyBool_FromLong,3.2, +var,PyBool_Type,3.2, +var,PyByteArrayIter_Type,3.2, +function,PyByteArray_AsString,3.2, +function,PyByteArray_Concat,3.2, +function,PyByteArray_FromObject,3.2, +function,PyByteArray_FromStringAndSize,3.2, +function,PyByteArray_Resize,3.2, +function,PyByteArray_Size,3.2, +var,PyByteArray_Type,3.2, +var,PyBytesIter_Type,3.2, +function,PyBytes_AsString,3.2, +function,PyBytes_AsStringAndSize,3.2, +function,PyBytes_Concat,3.2, +function,PyBytes_ConcatAndDel,3.2, +function,PyBytes_DecodeEscape,3.2, +function,PyBytes_FromFormat,3.2, +function,PyBytes_FromFormatV,3.2, +function,PyBytes_FromObject,3.2, +function,PyBytes_FromString,3.2, +function,PyBytes_FromStringAndSize,3.2, +function,PyBytes_Repr,3.2, +function,PyBytes_Size,3.2, +var,PyBytes_Type,3.2, +type,PyCFunction,3.2, +type,PyCFunctionWithKeywords,3.2, +function,PyCFunction_Call,3.2, +function,PyCFunction_GetFlags,3.2, +function,PyCFunction_GetFunction,3.2, +function,PyCFunction_GetSelf,3.2, +function,PyCFunction_New,3.4, +function,PyCFunction_NewEx,3.2, +var,PyCFunction_Type,3.2, +function,PyCMethod_New,3.9, +function,PyCallIter_New,3.2, +var,PyCallIter_Type,3.2, +function,PyCallable_Check,3.2, +type,PyCapsule_Destructor,3.2, +function,PyCapsule_GetContext,3.2, +function,PyCapsule_GetDestructor,3.2, +function,PyCapsule_GetName,3.2, +function,PyCapsule_GetPointer,3.2, +function,PyCapsule_Import,3.2, +function,PyCapsule_IsValid,3.2, +function,PyCapsule_New,3.2, +function,PyCapsule_SetContext,3.2, +function,PyCapsule_SetDestructor,3.2, +function,PyCapsule_SetName,3.2, +function,PyCapsule_SetPointer,3.2, +var,PyCapsule_Type,3.2, +var,PyClassMethodDescr_Type,3.2, +function,PyCodec_BackslashReplaceErrors,3.2, +function,PyCodec_Decode,3.2, +function,PyCodec_Decoder,3.2, +function,PyCodec_Encode,3.2, +function,PyCodec_Encoder,3.2, +function,PyCodec_IgnoreErrors,3.2, +function,PyCodec_IncrementalDecoder,3.2, +function,PyCodec_IncrementalEncoder,3.2, +function,PyCodec_KnownEncoding,3.2, +function,PyCodec_LookupError,3.2, +function,PyCodec_NameReplaceErrors,3.7, +function,PyCodec_Register,3.2, +function,PyCodec_RegisterError,3.2, +function,PyCodec_ReplaceErrors,3.2, +function,PyCodec_StreamReader,3.2, +function,PyCodec_StreamWriter,3.2, +function,PyCodec_StrictErrors,3.2, +function,PyCodec_Unregister,3.10, +function,PyCodec_XMLCharRefReplaceErrors,3.2, +function,PyComplex_FromDoubles,3.2, +function,PyComplex_ImagAsDouble,3.2, +function,PyComplex_RealAsDouble,3.2, +var,PyComplex_Type,3.2, +function,PyDescr_NewClassMethod,3.2, +function,PyDescr_NewGetSet,3.2, +function,PyDescr_NewMember,3.2, +function,PyDescr_NewMethod,3.2, +var,PyDictItems_Type,3.2, +var,PyDictIterItem_Type,3.2, +var,PyDictIterKey_Type,3.2, +var,PyDictIterValue_Type,3.2, +var,PyDictKeys_Type,3.2, +function,PyDictProxy_New,3.2, +var,PyDictProxy_Type,3.2, +var,PyDictRevIterItem_Type,3.8, +var,PyDictRevIterKey_Type,3.8, +var,PyDictRevIterValue_Type,3.8, +var,PyDictValues_Type,3.2, +function,PyDict_Clear,3.2, +function,PyDict_Contains,3.2, +function,PyDict_Copy,3.2, +function,PyDict_DelItem,3.2, +function,PyDict_DelItemString,3.2, +function,PyDict_GetItem,3.2, +function,PyDict_GetItemString,3.2, +function,PyDict_GetItemWithError,3.2, +function,PyDict_Items,3.2, +function,PyDict_Keys,3.2, +function,PyDict_Merge,3.2, +function,PyDict_MergeFromSeq2,3.2, +function,PyDict_New,3.2, +function,PyDict_Next,3.2, +function,PyDict_SetItem,3.2, +function,PyDict_SetItemString,3.2, +function,PyDict_Size,3.2, +var,PyDict_Type,3.2, +function,PyDict_Update,3.2, +function,PyDict_Values,3.2, +var,PyEllipsis_Type,3.2, +var,PyEnum_Type,3.2, +function,PyErr_BadArgument,3.2, +function,PyErr_BadInternalCall,3.2, +function,PyErr_CheckSignals,3.2, +function,PyErr_Clear,3.2, +function,PyErr_Display,3.2, +function,PyErr_ExceptionMatches,3.2, +function,PyErr_Fetch,3.2, +function,PyErr_Format,3.2, +function,PyErr_FormatV,3.5, +function,PyErr_GetExcInfo,3.7, +function,PyErr_GivenExceptionMatches,3.2, +function,PyErr_NewException,3.2, +function,PyErr_NewExceptionWithDoc,3.2, +function,PyErr_NoMemory,3.2, +function,PyErr_NormalizeException,3.2, +function,PyErr_Occurred,3.2, +function,PyErr_Print,3.2, +function,PyErr_PrintEx,3.2, +function,PyErr_ProgramText,3.2, +function,PyErr_ResourceWarning,3.6, +function,PyErr_Restore,3.2, +function,PyErr_SetExcFromWindowsErr,3.7,on Windows +function,PyErr_SetExcFromWindowsErrWithFilename,3.7,on Windows +function,PyErr_SetExcFromWindowsErrWithFilenameObject,3.7,on Windows +function,PyErr_SetExcFromWindowsErrWithFilenameObjects,3.7,on Windows +function,PyErr_SetExcInfo,3.7, +function,PyErr_SetFromErrno,3.2, +function,PyErr_SetFromErrnoWithFilename,3.2, +function,PyErr_SetFromErrnoWithFilenameObject,3.2, +function,PyErr_SetFromErrnoWithFilenameObjects,3.7, +function,PyErr_SetFromWindowsErr,3.7,on Windows +function,PyErr_SetFromWindowsErrWithFilename,3.7,on Windows +function,PyErr_SetImportError,3.7, +function,PyErr_SetImportErrorSubclass,3.6, +function,PyErr_SetInterrupt,3.2, +function,PyErr_SetInterruptEx,3.10, +function,PyErr_SetNone,3.2, +function,PyErr_SetObject,3.2, +function,PyErr_SetString,3.2, +function,PyErr_SyntaxLocation,3.2, +function,PyErr_SyntaxLocationEx,3.7, +function,PyErr_WarnEx,3.2, +function,PyErr_WarnExplicit,3.2, +function,PyErr_WarnFormat,3.2, +function,PyErr_WriteUnraisable,3.2, +function,PyEval_AcquireLock,3.2, +function,PyEval_AcquireThread,3.2, +function,PyEval_CallFunction,3.2, +function,PyEval_CallMethod,3.2, +function,PyEval_CallObjectWithKeywords,3.2, +function,PyEval_EvalCode,3.2, +function,PyEval_EvalCodeEx,3.2, +function,PyEval_EvalFrame,3.2, +function,PyEval_EvalFrameEx,3.2, +function,PyEval_GetBuiltins,3.2, +function,PyEval_GetFrame,3.2, +function,PyEval_GetFuncDesc,3.2, +function,PyEval_GetFuncName,3.2, +function,PyEval_GetGlobals,3.2, +function,PyEval_GetLocals,3.2, +function,PyEval_InitThreads,3.2, +function,PyEval_ReleaseLock,3.2, +function,PyEval_ReleaseThread,3.2, +function,PyEval_RestoreThread,3.2, +function,PyEval_SaveThread,3.2, +function,PyEval_ThreadsInitialized,3.2, +var,PyExc_ArithmeticError,3.2, +var,PyExc_AssertionError,3.2, +var,PyExc_AttributeError,3.2, +var,PyExc_BaseException,3.2, +var,PyExc_BlockingIOError,3.7, +var,PyExc_BrokenPipeError,3.7, +var,PyExc_BufferError,3.2, +var,PyExc_BytesWarning,3.2, +var,PyExc_ChildProcessError,3.7, +var,PyExc_ConnectionAbortedError,3.7, +var,PyExc_ConnectionError,3.7, +var,PyExc_ConnectionRefusedError,3.7, +var,PyExc_ConnectionResetError,3.7, +var,PyExc_DeprecationWarning,3.2, +var,PyExc_EOFError,3.2, +var,PyExc_EncodingWarning,3.10, +var,PyExc_EnvironmentError,3.2, +var,PyExc_Exception,3.2, +var,PyExc_FileExistsError,3.7, +var,PyExc_FileNotFoundError,3.7, +var,PyExc_FloatingPointError,3.2, +var,PyExc_FutureWarning,3.2, +var,PyExc_GeneratorExit,3.2, +var,PyExc_IOError,3.2, +var,PyExc_ImportError,3.2, +var,PyExc_ImportWarning,3.2, +var,PyExc_IndentationError,3.2, +var,PyExc_IndexError,3.2, +var,PyExc_InterruptedError,3.7, +var,PyExc_IsADirectoryError,3.7, +var,PyExc_KeyError,3.2, +var,PyExc_KeyboardInterrupt,3.2, +var,PyExc_LookupError,3.2, +var,PyExc_MemoryError,3.2, +var,PyExc_ModuleNotFoundError,3.6, +var,PyExc_NameError,3.2, +var,PyExc_NotADirectoryError,3.7, +var,PyExc_NotImplementedError,3.2, +var,PyExc_OSError,3.2, +var,PyExc_OverflowError,3.2, +var,PyExc_PendingDeprecationWarning,3.2, +var,PyExc_PermissionError,3.7, +var,PyExc_ProcessLookupError,3.7, +var,PyExc_RecursionError,3.7, +var,PyExc_ReferenceError,3.2, +var,PyExc_ResourceWarning,3.7, +var,PyExc_RuntimeError,3.2, +var,PyExc_RuntimeWarning,3.2, +var,PyExc_StopAsyncIteration,3.7, +var,PyExc_StopIteration,3.2, +var,PyExc_SyntaxError,3.2, +var,PyExc_SyntaxWarning,3.2, +var,PyExc_SystemError,3.2, +var,PyExc_SystemExit,3.2, +var,PyExc_TabError,3.2, +var,PyExc_TimeoutError,3.7, +var,PyExc_TypeError,3.2, +var,PyExc_UnboundLocalError,3.2, +var,PyExc_UnicodeDecodeError,3.2, +var,PyExc_UnicodeEncodeError,3.2, +var,PyExc_UnicodeError,3.2, +var,PyExc_UnicodeTranslateError,3.2, +var,PyExc_UnicodeWarning,3.2, +var,PyExc_UserWarning,3.2, +var,PyExc_ValueError,3.2, +var,PyExc_Warning,3.2, +var,PyExc_WindowsError,3.7,on Windows +var,PyExc_ZeroDivisionError,3.2, +function,PyExceptionClass_Name,3.8, +function,PyException_GetCause,3.2, +function,PyException_GetContext,3.2, +function,PyException_GetTraceback,3.2, +function,PyException_SetCause,3.2, +function,PyException_SetContext,3.2, +function,PyException_SetTraceback,3.2, +function,PyFile_FromFd,3.2, +function,PyFile_GetLine,3.2, +function,PyFile_WriteObject,3.2, +function,PyFile_WriteString,3.2, +var,PyFilter_Type,3.2, +function,PyFloat_AsDouble,3.2, +function,PyFloat_FromDouble,3.2, +function,PyFloat_FromString,3.2, +function,PyFloat_GetInfo,3.2, +function,PyFloat_GetMax,3.2, +function,PyFloat_GetMin,3.2, +var,PyFloat_Type,3.2, +type,PyFrameObject,3.2, +function,PyFrame_GetCode,3.10, +function,PyFrame_GetLineNumber,3.10, +function,PyFrozenSet_New,3.2, +var,PyFrozenSet_Type,3.2, +function,PyGC_Collect,3.2, +function,PyGC_Disable,3.10, +function,PyGC_Enable,3.10, +function,PyGC_IsEnabled,3.10, +function,PyGILState_Ensure,3.2, +function,PyGILState_GetThisThreadState,3.2, +function,PyGILState_Release,3.2, +type,PyGILState_STATE,3.2, +type,PyGetSetDef,3.2, +var,PyGetSetDescr_Type,3.2, +function,PyImport_AddModule,3.2, +function,PyImport_AddModuleObject,3.7, +function,PyImport_AppendInittab,3.2, +function,PyImport_ExecCodeModule,3.2, +function,PyImport_ExecCodeModuleEx,3.2, +function,PyImport_ExecCodeModuleObject,3.7, +function,PyImport_ExecCodeModuleWithPathnames,3.2, +function,PyImport_GetImporter,3.2, +function,PyImport_GetMagicNumber,3.2, +function,PyImport_GetMagicTag,3.2, +function,PyImport_GetModule,3.8, +function,PyImport_GetModuleDict,3.2, +function,PyImport_Import,3.2, +function,PyImport_ImportFrozenModule,3.2, +function,PyImport_ImportFrozenModuleObject,3.7, +function,PyImport_ImportModule,3.2, +function,PyImport_ImportModuleLevel,3.2, +function,PyImport_ImportModuleLevelObject,3.7, +function,PyImport_ImportModuleNoBlock,3.2, +function,PyImport_ReloadModule,3.2, +function,PyIndex_Check,3.8, +type,PyInterpreterState,3.2, +function,PyInterpreterState_Clear,3.2, +function,PyInterpreterState_Delete,3.2, +function,PyInterpreterState_Get,3.9, +function,PyInterpreterState_GetDict,3.8, +function,PyInterpreterState_GetID,3.7, +function,PyInterpreterState_New,3.2, +function,PyIter_Check,3.8, +function,PyIter_Next,3.2, +function,PyIter_Send,3.10, +var,PyListIter_Type,3.2, +var,PyListRevIter_Type,3.2, +function,PyList_Append,3.2, +function,PyList_AsTuple,3.2, +function,PyList_GetItem,3.2, +function,PyList_GetSlice,3.2, +function,PyList_Insert,3.2, +function,PyList_New,3.2, +function,PyList_Reverse,3.2, +function,PyList_SetItem,3.2, +function,PyList_SetSlice,3.2, +function,PyList_Size,3.2, +function,PyList_Sort,3.2, +var,PyList_Type,3.2, +type,PyLongObject,3.2, +var,PyLongRangeIter_Type,3.2, +function,PyLong_AsDouble,3.2, +function,PyLong_AsLong,3.2, +function,PyLong_AsLongAndOverflow,3.2, +function,PyLong_AsLongLong,3.2, +function,PyLong_AsLongLongAndOverflow,3.2, +function,PyLong_AsSize_t,3.2, +function,PyLong_AsSsize_t,3.2, +function,PyLong_AsUnsignedLong,3.2, +function,PyLong_AsUnsignedLongLong,3.2, +function,PyLong_AsUnsignedLongLongMask,3.2, +function,PyLong_AsUnsignedLongMask,3.2, +function,PyLong_AsVoidPtr,3.2, +function,PyLong_FromDouble,3.2, +function,PyLong_FromLong,3.2, +function,PyLong_FromLongLong,3.2, +function,PyLong_FromSize_t,3.2, +function,PyLong_FromSsize_t,3.2, +function,PyLong_FromString,3.2, +function,PyLong_FromUnsignedLong,3.2, +function,PyLong_FromUnsignedLongLong,3.2, +function,PyLong_FromVoidPtr,3.2, +function,PyLong_GetInfo,3.2, +var,PyLong_Type,3.2, +var,PyMap_Type,3.2, +function,PyMapping_Check,3.2, +function,PyMapping_GetItemString,3.2, +function,PyMapping_HasKey,3.2, +function,PyMapping_HasKeyString,3.2, +function,PyMapping_Items,3.2, +function,PyMapping_Keys,3.2, +function,PyMapping_Length,3.2, +function,PyMapping_SetItemString,3.2, +function,PyMapping_Size,3.2, +function,PyMapping_Values,3.2, +function,PyMem_Calloc,3.7, +function,PyMem_Free,3.2, +function,PyMem_Malloc,3.2, +function,PyMem_Realloc,3.2, +type,PyMemberDef,3.2, +var,PyMemberDescr_Type,3.2, +function,PyMemoryView_FromMemory,3.7, +function,PyMemoryView_FromObject,3.2, +function,PyMemoryView_GetContiguous,3.2, +var,PyMemoryView_Type,3.2, +type,PyMethodDef,3.2, +var,PyMethodDescr_Type,3.2, +type,PyModuleDef,3.2, +type,PyModuleDef_Base,3.2, +function,PyModuleDef_Init,3.5, +var,PyModuleDef_Type,3.5, +function,PyModule_AddFunctions,3.7, +function,PyModule_AddIntConstant,3.2, +function,PyModule_AddObject,3.2, +function,PyModule_AddObjectRef,3.10, +function,PyModule_AddStringConstant,3.2, +function,PyModule_AddType,3.10, +function,PyModule_Create2,3.2, +function,PyModule_ExecDef,3.7, +function,PyModule_FromDefAndSpec2,3.7, +function,PyModule_GetDef,3.2, +function,PyModule_GetDict,3.2, +function,PyModule_GetFilename,3.2, +function,PyModule_GetFilenameObject,3.2, +function,PyModule_GetName,3.2, +function,PyModule_GetNameObject,3.7, +function,PyModule_GetState,3.2, +function,PyModule_New,3.2, +function,PyModule_NewObject,3.7, +function,PyModule_SetDocString,3.7, +var,PyModule_Type,3.2, +function,PyNumber_Absolute,3.2, +function,PyNumber_Add,3.2, +function,PyNumber_And,3.2, +function,PyNumber_AsSsize_t,3.2, +function,PyNumber_Check,3.2, +function,PyNumber_Divmod,3.2, +function,PyNumber_Float,3.2, +function,PyNumber_FloorDivide,3.2, +function,PyNumber_InPlaceAdd,3.2, +function,PyNumber_InPlaceAnd,3.2, +function,PyNumber_InPlaceFloorDivide,3.2, +function,PyNumber_InPlaceLshift,3.2, +function,PyNumber_InPlaceMatrixMultiply,3.7, +function,PyNumber_InPlaceMultiply,3.2, +function,PyNumber_InPlaceOr,3.2, +function,PyNumber_InPlacePower,3.2, +function,PyNumber_InPlaceRemainder,3.2, +function,PyNumber_InPlaceRshift,3.2, +function,PyNumber_InPlaceSubtract,3.2, +function,PyNumber_InPlaceTrueDivide,3.2, +function,PyNumber_InPlaceXor,3.2, +function,PyNumber_Index,3.2, +function,PyNumber_Invert,3.2, +function,PyNumber_Long,3.2, +function,PyNumber_Lshift,3.2, +function,PyNumber_MatrixMultiply,3.7, +function,PyNumber_Multiply,3.2, +function,PyNumber_Negative,3.2, +function,PyNumber_Or,3.2, +function,PyNumber_Positive,3.2, +function,PyNumber_Power,3.2, +function,PyNumber_Remainder,3.2, +function,PyNumber_Rshift,3.2, +function,PyNumber_Subtract,3.2, +function,PyNumber_ToBase,3.2, +function,PyNumber_TrueDivide,3.2, +function,PyNumber_Xor,3.2, +function,PyOS_AfterFork,3.2,on platforms with fork() +function,PyOS_AfterFork_Child,3.7,on platforms with fork() +function,PyOS_AfterFork_Parent,3.7,on platforms with fork() +function,PyOS_BeforeFork,3.7,on platforms with fork() +function,PyOS_CheckStack,3.7,on platforms with USE_STACKCHECK +function,PyOS_FSPath,3.6, +var,PyOS_InputHook,3.2, +function,PyOS_InterruptOccurred,3.2, +function,PyOS_double_to_string,3.2, +function,PyOS_getsig,3.2, +function,PyOS_mystricmp,3.2, +function,PyOS_mystrnicmp,3.2, +function,PyOS_setsig,3.2, +type,PyOS_sighandler_t,3.2, +function,PyOS_snprintf,3.2, +function,PyOS_string_to_double,3.2, +function,PyOS_strtol,3.2, +function,PyOS_strtoul,3.2, +function,PyOS_vsnprintf,3.2, +type,PyObject,3.2, +function,PyObject_ASCII,3.2, +function,PyObject_AsCharBuffer,3.2, +function,PyObject_AsFileDescriptor,3.2, +function,PyObject_AsReadBuffer,3.2, +function,PyObject_AsWriteBuffer,3.2, +function,PyObject_Bytes,3.2, +function,PyObject_Call,3.2, +function,PyObject_CallFunction,3.2, +function,PyObject_CallFunctionObjArgs,3.2, +function,PyObject_CallMethod,3.2, +function,PyObject_CallMethodObjArgs,3.2, +function,PyObject_CallNoArgs,3.10, +function,PyObject_CallObject,3.2, +function,PyObject_Calloc,3.7, +function,PyObject_CheckReadBuffer,3.2, +function,PyObject_ClearWeakRefs,3.2, +function,PyObject_DelItem,3.2, +function,PyObject_DelItemString,3.2, +function,PyObject_Dir,3.2, +function,PyObject_Format,3.2, +function,PyObject_Free,3.2, +function,PyObject_GC_Del,3.2, +function,PyObject_GC_IsFinalized,3.9, +function,PyObject_GC_IsTracked,3.9, +function,PyObject_GC_Track,3.2, +function,PyObject_GC_UnTrack,3.2, +function,PyObject_GenericGetAttr,3.2, +function,PyObject_GenericGetDict,3.10, +function,PyObject_GenericSetAttr,3.2, +function,PyObject_GenericSetDict,3.7, +function,PyObject_GetAIter,3.10, +function,PyObject_GetAttr,3.2, +function,PyObject_GetAttrString,3.2, +function,PyObject_GetItem,3.2, +function,PyObject_GetIter,3.2, +function,PyObject_HasAttr,3.2, +function,PyObject_HasAttrString,3.2, +function,PyObject_Hash,3.2, +function,PyObject_HashNotImplemented,3.2, +function,PyObject_Init,3.2, +function,PyObject_InitVar,3.2, +function,PyObject_IsInstance,3.2, +function,PyObject_IsSubclass,3.2, +function,PyObject_IsTrue,3.2, +function,PyObject_Length,3.2, +function,PyObject_Malloc,3.2, +function,PyObject_Not,3.2, +function,PyObject_Realloc,3.2, +function,PyObject_Repr,3.2, +function,PyObject_RichCompare,3.2, +function,PyObject_RichCompareBool,3.2, +function,PyObject_SelfIter,3.2, +function,PyObject_SetAttr,3.2, +function,PyObject_SetAttrString,3.2, +function,PyObject_SetItem,3.2, +function,PyObject_Size,3.2, +function,PyObject_Str,3.2, +function,PyObject_Type,3.2, +var,PyProperty_Type,3.2, +var,PyRangeIter_Type,3.2, +var,PyRange_Type,3.2, +var,PyReversed_Type,3.2, +function,PySeqIter_New,3.2, +var,PySeqIter_Type,3.2, +function,PySequence_Check,3.2, +function,PySequence_Concat,3.2, +function,PySequence_Contains,3.2, +function,PySequence_Count,3.2, +function,PySequence_DelItem,3.2, +function,PySequence_DelSlice,3.2, +function,PySequence_Fast,3.2, +function,PySequence_GetItem,3.2, +function,PySequence_GetSlice,3.2, +function,PySequence_In,3.2, +function,PySequence_InPlaceConcat,3.2, +function,PySequence_InPlaceRepeat,3.2, +function,PySequence_Index,3.2, +function,PySequence_Length,3.2, +function,PySequence_List,3.2, +function,PySequence_Repeat,3.2, +function,PySequence_SetItem,3.2, +function,PySequence_SetSlice,3.2, +function,PySequence_Size,3.2, +function,PySequence_Tuple,3.2, +var,PySetIter_Type,3.2, +function,PySet_Add,3.2, +function,PySet_Clear,3.2, +function,PySet_Contains,3.2, +function,PySet_Discard,3.2, +function,PySet_New,3.2, +function,PySet_Pop,3.2, +function,PySet_Size,3.2, +var,PySet_Type,3.2, +function,PySlice_AdjustIndices,3.7, +function,PySlice_GetIndices,3.2, +function,PySlice_GetIndicesEx,3.2, +function,PySlice_New,3.2, +var,PySlice_Type,3.2, +function,PySlice_Unpack,3.7, +function,PyState_AddModule,3.3, +function,PyState_FindModule,3.2, +function,PyState_RemoveModule,3.3, +type,PyStructSequence_Desc,3.2, +type,PyStructSequence_Field,3.2, +function,PyStructSequence_GetItem,3.2, +function,PyStructSequence_New,3.2, +function,PyStructSequence_NewType,3.2, +function,PyStructSequence_SetItem,3.2, +var,PySuper_Type,3.2, +function,PySys_AddWarnOption,3.2, +function,PySys_AddWarnOptionUnicode,3.2, +function,PySys_AddXOption,3.7, +function,PySys_FormatStderr,3.2, +function,PySys_FormatStdout,3.2, +function,PySys_GetObject,3.2, +function,PySys_GetXOptions,3.7, +function,PySys_HasWarnOptions,3.2, +function,PySys_ResetWarnOptions,3.2, +function,PySys_SetArgv,3.2, +function,PySys_SetArgvEx,3.2, +function,PySys_SetObject,3.2, +function,PySys_SetPath,3.2, +function,PySys_WriteStderr,3.2, +function,PySys_WriteStdout,3.2, +type,PyThreadState,3.2, +function,PyThreadState_Clear,3.2, +function,PyThreadState_Delete,3.2, +function,PyThreadState_Get,3.2, +function,PyThreadState_GetDict,3.2, +function,PyThreadState_GetFrame,3.10, +function,PyThreadState_GetID,3.10, +function,PyThreadState_GetInterpreter,3.10, +function,PyThreadState_New,3.2, +function,PyThreadState_SetAsyncExc,3.2, +function,PyThreadState_Swap,3.2, +function,PyThread_GetInfo,3.3, +function,PyThread_ReInitTLS,3.2, +function,PyThread_acquire_lock,3.2, +function,PyThread_acquire_lock_timed,3.2, +function,PyThread_allocate_lock,3.2, +function,PyThread_create_key,3.2, +function,PyThread_delete_key,3.2, +function,PyThread_delete_key_value,3.2, +function,PyThread_exit_thread,3.2, +function,PyThread_free_lock,3.2, +function,PyThread_get_key_value,3.2, +function,PyThread_get_stacksize,3.2, +function,PyThread_get_thread_ident,3.2, +function,PyThread_get_thread_native_id,3.2, +function,PyThread_init_thread,3.2, +function,PyThread_release_lock,3.2, +function,PyThread_set_key_value,3.2, +function,PyThread_set_stacksize,3.2, +function,PyThread_start_new_thread,3.2, +function,PyThread_tss_alloc,3.7, +function,PyThread_tss_create,3.7, +function,PyThread_tss_delete,3.7, +function,PyThread_tss_free,3.7, +function,PyThread_tss_get,3.7, +function,PyThread_tss_is_created,3.7, +function,PyThread_tss_set,3.7, +function,PyTraceBack_Here,3.2, +function,PyTraceBack_Print,3.2, +var,PyTraceBack_Type,3.2, +var,PyTupleIter_Type,3.2, +function,PyTuple_GetItem,3.2, +function,PyTuple_GetSlice,3.2, +function,PyTuple_New,3.2, +function,PyTuple_Pack,3.2, +function,PyTuple_SetItem,3.2, +function,PyTuple_Size,3.2, +var,PyTuple_Type,3.2, +type,PyTypeObject,3.2, +function,PyType_ClearCache,3.2, +function,PyType_FromModuleAndSpec,3.10, +function,PyType_FromSpec,3.2, +function,PyType_FromSpecWithBases,3.3, +function,PyType_GenericAlloc,3.2, +function,PyType_GenericNew,3.2, +function,PyType_GetFlags,3.2, +function,PyType_GetModule,3.10, +function,PyType_GetModuleState,3.10, +function,PyType_GetSlot,3.4, +function,PyType_IsSubtype,3.2, +function,PyType_Modified,3.2, +function,PyType_Ready,3.2, +type,PyType_Slot,3.2, +type,PyType_Spec,3.2, +var,PyType_Type,3.2, +function,PyUnicodeDecodeError_Create,3.2, +function,PyUnicodeDecodeError_GetEncoding,3.2, +function,PyUnicodeDecodeError_GetEnd,3.2, +function,PyUnicodeDecodeError_GetObject,3.2, +function,PyUnicodeDecodeError_GetReason,3.2, +function,PyUnicodeDecodeError_GetStart,3.2, +function,PyUnicodeDecodeError_SetEnd,3.2, +function,PyUnicodeDecodeError_SetReason,3.2, +function,PyUnicodeDecodeError_SetStart,3.2, +function,PyUnicodeEncodeError_GetEncoding,3.2, +function,PyUnicodeEncodeError_GetEnd,3.2, +function,PyUnicodeEncodeError_GetObject,3.2, +function,PyUnicodeEncodeError_GetReason,3.2, +function,PyUnicodeEncodeError_GetStart,3.2, +function,PyUnicodeEncodeError_SetEnd,3.2, +function,PyUnicodeEncodeError_SetReason,3.2, +function,PyUnicodeEncodeError_SetStart,3.2, +var,PyUnicodeIter_Type,3.2, +function,PyUnicodeTranslateError_GetEnd,3.2, +function,PyUnicodeTranslateError_GetObject,3.2, +function,PyUnicodeTranslateError_GetReason,3.2, +function,PyUnicodeTranslateError_GetStart,3.2, +function,PyUnicodeTranslateError_SetEnd,3.2, +function,PyUnicodeTranslateError_SetReason,3.2, +function,PyUnicodeTranslateError_SetStart,3.2, +function,PyUnicode_Append,3.2, +function,PyUnicode_AppendAndDel,3.2, +function,PyUnicode_AsASCIIString,3.2, +function,PyUnicode_AsCharmapString,3.2, +function,PyUnicode_AsDecodedObject,3.2, +function,PyUnicode_AsDecodedUnicode,3.2, +function,PyUnicode_AsEncodedObject,3.2, +function,PyUnicode_AsEncodedString,3.2, +function,PyUnicode_AsEncodedUnicode,3.2, +function,PyUnicode_AsLatin1String,3.2, +function,PyUnicode_AsMBCSString,3.7,on Windows +function,PyUnicode_AsRawUnicodeEscapeString,3.2, +function,PyUnicode_AsUCS4,3.7, +function,PyUnicode_AsUCS4Copy,3.7, +function,PyUnicode_AsUTF16String,3.2, +function,PyUnicode_AsUTF32String,3.2, +function,PyUnicode_AsUTF8AndSize,3.10, +function,PyUnicode_AsUTF8String,3.2, +function,PyUnicode_AsUnicodeEscapeString,3.2, +function,PyUnicode_AsWideChar,3.2, +function,PyUnicode_AsWideCharString,3.7, +function,PyUnicode_BuildEncodingMap,3.2, +function,PyUnicode_Compare,3.2, +function,PyUnicode_CompareWithASCIIString,3.2, +function,PyUnicode_Concat,3.2, +function,PyUnicode_Contains,3.2, +function,PyUnicode_Count,3.2, +function,PyUnicode_Decode,3.2, +function,PyUnicode_DecodeASCII,3.2, +function,PyUnicode_DecodeCharmap,3.2, +function,PyUnicode_DecodeCodePageStateful,3.7,on Windows +function,PyUnicode_DecodeFSDefault,3.2, +function,PyUnicode_DecodeFSDefaultAndSize,3.2, +function,PyUnicode_DecodeLatin1,3.2, +function,PyUnicode_DecodeLocale,3.7, +function,PyUnicode_DecodeLocaleAndSize,3.7, +function,PyUnicode_DecodeMBCS,3.7,on Windows +function,PyUnicode_DecodeMBCSStateful,3.7,on Windows +function,PyUnicode_DecodeRawUnicodeEscape,3.2, +function,PyUnicode_DecodeUTF16,3.2, +function,PyUnicode_DecodeUTF16Stateful,3.2, +function,PyUnicode_DecodeUTF32,3.2, +function,PyUnicode_DecodeUTF32Stateful,3.2, +function,PyUnicode_DecodeUTF7,3.2, +function,PyUnicode_DecodeUTF7Stateful,3.2, +function,PyUnicode_DecodeUTF8,3.2, +function,PyUnicode_DecodeUTF8Stateful,3.2, +function,PyUnicode_DecodeUnicodeEscape,3.2, +function,PyUnicode_EncodeCodePage,3.7,on Windows +function,PyUnicode_EncodeFSDefault,3.2, +function,PyUnicode_EncodeLocale,3.7, +function,PyUnicode_FSConverter,3.2, +function,PyUnicode_FSDecoder,3.2, +function,PyUnicode_Find,3.2, +function,PyUnicode_FindChar,3.7, +function,PyUnicode_Format,3.2, +function,PyUnicode_FromEncodedObject,3.2, +function,PyUnicode_FromFormat,3.2, +function,PyUnicode_FromFormatV,3.2, +function,PyUnicode_FromObject,3.2, +function,PyUnicode_FromOrdinal,3.2, +function,PyUnicode_FromString,3.2, +function,PyUnicode_FromStringAndSize,3.2, +function,PyUnicode_FromWideChar,3.2, +function,PyUnicode_GetDefaultEncoding,3.2, +function,PyUnicode_GetLength,3.7, +function,PyUnicode_GetSize,3.2, +function,PyUnicode_InternFromString,3.2, +function,PyUnicode_InternImmortal,3.2, +function,PyUnicode_InternInPlace,3.2, +function,PyUnicode_IsIdentifier,3.2, +function,PyUnicode_Join,3.2, +function,PyUnicode_Partition,3.2, +function,PyUnicode_RPartition,3.2, +function,PyUnicode_RSplit,3.2, +function,PyUnicode_ReadChar,3.7, +function,PyUnicode_Replace,3.2, +function,PyUnicode_Resize,3.2, +function,PyUnicode_RichCompare,3.2, +function,PyUnicode_Split,3.2, +function,PyUnicode_Splitlines,3.2, +function,PyUnicode_Substring,3.7, +function,PyUnicode_Tailmatch,3.2, +function,PyUnicode_Translate,3.2, +var,PyUnicode_Type,3.2, +function,PyUnicode_WriteChar,3.7, +type,PyVarObject,3.2, +type,PyWeakReference,3.2, +function,PyWeakref_GetObject,3.2, +function,PyWeakref_NewProxy,3.2, +function,PyWeakref_NewRef,3.2, +var,PyWrapperDescr_Type,3.2, +function,PyWrapper_New,3.2, +var,PyZip_Type,3.2, +function,Py_AddPendingCall,3.2, +function,Py_AtExit,3.2, +macro,Py_BEGIN_ALLOW_THREADS,3.2, +macro,Py_BLOCK_THREADS,3.2, +function,Py_BuildValue,3.2, +function,Py_BytesMain,3.8, +function,Py_CompileString,3.2, +function,Py_DecRef,3.2, +function,Py_DecodeLocale,3.7, +macro,Py_END_ALLOW_THREADS,3.2, +function,Py_EncodeLocale,3.7, +function,Py_EndInterpreter,3.2, +function,Py_EnterRecursiveCall,3.9, +function,Py_Exit,3.2, +function,Py_FatalError,3.2, +var,Py_FileSystemDefaultEncodeErrors,3.10, +var,Py_FileSystemDefaultEncoding,3.2, +function,Py_Finalize,3.2, +function,Py_FinalizeEx,3.6, +function,Py_GenericAlias,3.9, +var,Py_GenericAliasType,3.9, +function,Py_GetBuildInfo,3.2, +function,Py_GetCompiler,3.2, +function,Py_GetCopyright,3.2, +function,Py_GetExecPrefix,3.2, +function,Py_GetPath,3.2, +function,Py_GetPlatform,3.2, +function,Py_GetPrefix,3.2, +function,Py_GetProgramFullPath,3.2, +function,Py_GetProgramName,3.2, +function,Py_GetPythonHome,3.2, +function,Py_GetRecursionLimit,3.2, +function,Py_GetVersion,3.2, +var,Py_HasFileSystemDefaultEncoding,3.2, +function,Py_IncRef,3.2, +function,Py_Initialize,3.2, +function,Py_InitializeEx,3.2, +function,Py_Is,3.10, +function,Py_IsFalse,3.10, +function,Py_IsInitialized,3.2, +function,Py_IsNone,3.10, +function,Py_IsTrue,3.10, +function,Py_LeaveRecursiveCall,3.9, +function,Py_Main,3.2, +function,Py_MakePendingCalls,3.2, +function,Py_NewInterpreter,3.2, +function,Py_NewRef,3.10, +function,Py_ReprEnter,3.2, +function,Py_ReprLeave,3.2, +function,Py_SetPath,3.7, +function,Py_SetProgramName,3.2, +function,Py_SetPythonHome,3.2, +function,Py_SetRecursionLimit,3.2, +type,Py_UCS4,3.2, +macro,Py_UNBLOCK_THREADS,3.2, +var,Py_UTF8Mode,3.8, +function,Py_VaBuildValue,3.2, +function,Py_XNewRef,3.10, +type,Py_intptr_t,3.2, +type,Py_ssize_t,3.2, +type,Py_uintptr_t,3.2, +type,allocfunc,3.2, +type,binaryfunc,3.2, +type,descrgetfunc,3.2, +type,descrsetfunc,3.2, +type,destructor,3.2, +type,getattrfunc,3.2, +type,getattrofunc,3.2, +type,getiterfunc,3.2, +type,getter,3.2, +type,hashfunc,3.2, +type,initproc,3.2, +type,inquiry,3.2, +type,iternextfunc,3.2, +type,lenfunc,3.2, +type,newfunc,3.2, +type,objobjargproc,3.2, +type,objobjproc,3.2, +type,reprfunc,3.2, +type,richcmpfunc,3.2, +type,setattrfunc,3.2, +type,setattrofunc,3.2, +type,setter,3.2, +type,ssizeargfunc,3.2, +type,ssizeobjargproc,3.2, +type,ssizessizeargfunc,3.2, +type,ssizessizeobjargproc,3.2, +type,symtable,3.2, +type,ternaryfunc,3.2, +type,traverseproc,3.2, +type,unaryfunc,3.2, +type,visitproc,3.2, diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index 02379946244d84..136cf4e77b1543 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -31,7 +31,7 @@ installing other Python projects, refer to the Key terms ========= -* the `Python Packaging Index `__ is a public +* the `Python Package Index `__ is a public repository of open source licensed packages made available for use by other Python users * the `Python Packaging Authority @@ -101,7 +101,7 @@ by invoking the ``pip`` module at the command line:: .. note:: - For POSIX users (including Mac OS X and Linux users), these instructions + For POSIX users (including macOS and Linux users), these instructions assume the use of a :term:`virtual environment`. For Windows users, these instructions assume that the option to @@ -127,15 +127,15 @@ involved in creating and publishing a project: * `Project structure`_ * `Building and packaging the project`_ -* `Uploading the project to the Python Packaging Index`_ +* `Uploading the project to the Python Package Index`_ * `The .pypirc file`_ .. _Project structure: \ - https://packaging.python.org/tutorials/distributing-packages/ + https://packaging.python.org/tutorials/packaging-projects/#packaging-python-projects .. _Building and packaging the project: \ - https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project -.. _Uploading the project to the Python Packaging Index: \ - https://packaging.python.org/tutorials/distributing-packages/#uploading-your-project-to-pypi + https://packaging.python.org/tutorials/packaging-projects/#creating-the-package-files +.. _Uploading the project to the Python Package Index: \ + https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives .. _The .pypirc file: \ https://packaging.python.org/specifications/pypirc/ @@ -150,7 +150,7 @@ These are quick answers or links for some common tasks. This isn't an easy topic, but here are a few tips: -* check the Python Packaging Index to see if the name is already in use +* check the Python Package Index to see if the name is already in use * check popular hosting sites like GitHub, Bitbucket, etc to see if there is already a project with that name * check what comes up in a web search for the name you're considering diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index e4437f4106b519..3291303ccd84bd 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -373,7 +373,7 @@ This module provides the following functions. compiler object under Unix---if you supply a value for *compiler*, *plat* is ignored. - .. % Is the posix/nt only thing still true? Mac OS X seems to work, and + .. % Is the posix/nt only thing still true? macOS seems to work, and .. % returns a UnixCCompiler instance. How to document this... hmm. @@ -1119,11 +1119,11 @@ other utility module. For non-POSIX platforms, currently just returns ``sys.platform``. - For Mac OS X systems the OS version reflects the minimal version on which + For macOS systems the OS version reflects the minimal version on which binaries will run (that is, the value of ``MACOSX_DEPLOYMENT_TARGET`` during the build of Python), not the OS version of the current system. - For universal binary builds on Mac OS X the architecture value reflects + For universal binary builds on macOS the architecture value reflects the universal binary status instead of the architecture of the current processor. For 32-bit universal binaries the architecture is ``fat``, for 64-bit universal binaries the architecture is ``fat64``, and @@ -1132,7 +1132,7 @@ other utility module. a 3-way universal build (ppc, i386, x86_64) and ``intel`` is used for a universal build with the i386 and x86_64 architectures - Examples of returned values on Mac OS X: + Examples of returned values on macOS: * ``macosx-10.3-ppc`` diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst index 0600663d00e9dc..7b1e22f824e8ce 100644 --- a/Doc/distutils/sourcedist.rst +++ b/Doc/distutils/sourcedist.rst @@ -23,25 +23,25 @@ option, for example:: to create a gzipped tarball and a zip file. The available formats are: -+-----------+-------------------------+---------+ -| Format | Description | Notes | -+===========+=========================+=========+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+---------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+---------+ -| ``bztar`` | bzip2'ed tar file | | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+---------+ -| ``xztar`` | xz'ed tar file | | -| | (:file:`.tar.xz`) | | -+-----------+-------------------------+---------+ -| ``ztar`` | compressed tar file | \(4) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-----------+-------------------------+---------+ ++-----------+-------------------------+-------------+ +| Format | Description | Notes | ++===========+=========================+=============+ +| ``zip`` | zip file (:file:`.zip`) | (1),(3) | ++-----------+-------------------------+-------------+ +| ``gztar`` | gzip'ed tar file | \(2) | +| | (:file:`.tar.gz`) | | ++-----------+-------------------------+-------------+ +| ``bztar`` | bzip2'ed tar file | \(5) | +| | (:file:`.tar.bz2`) | | ++-----------+-------------------------+-------------+ +| ``xztar`` | xz'ed tar file | \(5) | +| | (:file:`.tar.xz`) | | ++-----------+-------------------------+-------------+ +| ``ztar`` | compressed tar file | (4),(5) | +| | (:file:`.tar.Z`) | | ++-----------+-------------------------+-------------+ +| ``tar`` | tar file (:file:`.tar`) | \(5) | ++-----------+-------------------------+-------------+ .. versionchanged:: 3.5 Added support for the ``xztar`` format. @@ -61,6 +61,9 @@ Notes: (4) requires the :program:`compress` program. Notice that this format is now pending for deprecation and will be removed in the future versions of Python. +(5) + deprecated by `PEP 527 `_; + `PyPI `_ only accepts ``.zip`` and ``.tar.gz`` files. When using any ``tar`` format (``gztar``, ``bztar``, ``xztar``, ``ztar`` or ``tar``), under Unix you can specify the ``owner`` and ``group`` names diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index 561d1c616cc10e..2e3362b834e6fb 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -127,13 +127,11 @@ Intermezzo: Errors and Exceptions An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value -(usually a ``NULL`` pointer). Exceptions are stored in a static global variable -inside the interpreter; if this variable is ``NULL`` no exception has occurred. A -second global variable stores the "associated value" of the exception (the -second argument to :keyword:`raise`). A third variable contains the stack -traceback in case the error originated in Python code. These three variables -are the C equivalents of the result in Python of :meth:`sys.exc_info` (see the -section on module :mod:`sys` in the Python Library Reference). It is important +(usually ``-1`` or a ``NULL`` pointer). Exception information is stored in +three members of the interpreter's thread state. These are ``NULL`` if +there is no exception. Otherwise they are the C equivalents of the members +of the Python tuple returned by :meth:`sys.exc_info`. These are the +exception type, exception instance, and a traceback object. It is important to know about them to understand how errors are passed around. The Python API defines a number of functions to set various types of exceptions. diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 6e17897ed2c805..f75bee9e6f2a2b 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -73,7 +73,19 @@ function:: newdatatype_dealloc(newdatatypeobject *obj) { free(obj->obj_UnderlyingDatatypePtr); - Py_TYPE(obj)->tp_free(obj); + Py_TYPE(obj)->tp_free((PyObject *)obj); + } + +If your type supports garbage collection, the destructor should call +:c:func:`PyObject_GC_UnTrack` before clearing any member fields:: + + static void + newdatatype_dealloc(newdatatypeobject *obj) + { + PyObject_GC_UnTrack(obj); + Py_CLEAR(obj->other_obj); + ... + Py_TYPE(obj)->tp_free((PyObject *)obj); } .. index:: @@ -381,7 +393,7 @@ analogous to the :ref:`rich comparison methods `, like :c:func:`PyObject_RichCompareBool`. This function is called with two Python objects and the operator as arguments, -where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GT``, +where the operator is one of ``Py_EQ``, ``Py_NE``, ``Py_LE``, ``Py_GE``, ``Py_LT`` or ``Py_GT``. It should compare the two objects with respect to the specified operator and return ``Py_True`` or ``Py_False`` if the comparison is successful, ``Py_NotImplemented`` to indicate that comparison is not diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst index 68570b33e2f626..0437b59d55da6e 100644 --- a/Doc/faq/design.rst +++ b/Doc/faq/design.rst @@ -708,6 +708,15 @@ bindings are resolved at run-time in Python, and the second version only needs to perform the resolution once. +Why don't generators support the with statement? +------------------------------------------------ + +For technical reasons, a generator used directly as a context manager +would not work correctly. When, as is most common, a generator is used as +an iterator run to completion, no closing is needed. When it is, wrap +it as "contextlib.closing(generator)" in the 'with' statement. + + Why are colons required for the if/while/def/class statements? -------------------------------------------------------------- diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index aecb56eaa4fd2f..3379e41d9de072 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -275,39 +275,8 @@ for more hints. However sometimes you have to run the embedded Python interpreter in the same thread as your rest application and you can't allow the -:c:func:`PyRun_InteractiveLoop` to stop while waiting for user input. The one -solution then is to call :c:func:`PyParser_ParseString` and test for ``e.error`` -equal to ``E_EOF``, which means the input is incomplete. Here's a sample code -fragment, untested, inspired by code from Alex Farber:: - - #define PY_SSIZE_T_CLEAN - #include - #include - #include - #include - #include - #include - - int testcomplete(char *code) - /* code should end in \n */ - /* return -1 for error, 0 for incomplete, 1 for complete */ - { - node *n; - perrdetail e; - - n = PyParser_ParseString(code, &_PyParser_Grammar, - Py_file_input, &e); - if (n == NULL) { - if (e.error == E_EOF) - return 0; - return -1; - } - - PyNode_Free(n); - return 1; - } - -Another solution is trying to compile the received string with +:c:func:`PyRun_InteractiveLoop` to stop while waiting for user input. +A solution is trying to compile the received string with :c:func:`Py_CompileString`. If it compiles without errors, try to execute the returned code object by calling :c:func:`PyEval_EvalCode`. Otherwise save the input for later. If the compilation fails, find out if it's an error or just diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index cf70f16c6fe328..7723114bcc18d3 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -113,7 +113,7 @@ to many different classes of problems. The language comes with a large standard library that covers areas such as string processing (regular expressions, Unicode, calculating differences between -files), Internet protocols (HTTP, FTP, SMTP, XML-RPC, POP, IMAP, CGI +files), internet protocols (HTTP, FTP, SMTP, XML-RPC, POP, IMAP, CGI programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets). Look at the table of contents for :ref:`library-index` to get an idea diff --git a/Doc/faq/gui.rst b/Doc/faq/gui.rst index 781da467d18013..86c56d957cdfec 100644 --- a/Doc/faq/gui.rst +++ b/Doc/faq/gui.rst @@ -14,17 +14,8 @@ Graphic User Interface FAQ General GUI Questions ===================== -What platform-independent GUI toolkits exist for Python? -======================================================== - -Depending on what platform(s) you are aiming at, there are several. Some -of them haven't been ported to Python 3 yet. At least `Tkinter`_ and `Qt`_ -are known to be Python 3-compatible. - -.. XXX check links - -Tkinter -------- +What GUI toolkits exist for Python? +=================================== Standard builds of Python include an object-oriented interface to the Tcl/Tk widget set, called :ref:`tkinter `. This is probably the easiest to @@ -32,85 +23,14 @@ install (since it comes included with most `binary distributions `_ of Python) and use. For more info about Tk, including pointers to the source, see the `Tcl/Tk home page `_. Tcl/Tk is fully portable to the -Mac OS X, Windows, and Unix platforms. - -wxWidgets ---------- - -wxWidgets (https://www.wxwidgets.org) is a free, portable GUI class -library written in C++ that provides a native look and feel on a -number of platforms, with Windows, Mac OS X, GTK, X11, all listed as -current stable targets. Language bindings are available for a number -of languages including Python, Perl, Ruby, etc. - -`wxPython `_ is the Python binding for -wxwidgets. While it often lags slightly behind the official wxWidgets -releases, it also offers a number of features via pure Python -extensions that are not available in other language bindings. There -is an active wxPython user and developer community. - -Both wxWidgets and wxPython are free, open source, software with -permissive licences that allow their use in commercial products as -well as in freeware or shareware. - - -Qt ---- - -There are bindings available for the Qt toolkit (using either `PyQt -`_ or `PySide -`_) and for KDE (`PyKDE4 `__). -PyQt is currently more mature than PySide, but you must buy a PyQt license from -`Riverbank Computing `_ -if you want to write proprietary applications. PySide is free for all applications. - -Qt 4.5 upwards is licensed under the LGPL license; also, commercial licenses -are available from `The Qt Company `_. - -Gtk+ ----- - -The `GObject introspection bindings `_ -for Python allow you to write GTK+ 3 applications. There is also a -`Python GTK+ 3 Tutorial `_. - -The older PyGtk bindings for the `Gtk+ 2 toolkit `_ have -been implemented by James Henstridge; see . - -Kivy ----- - -`Kivy `_ is a cross-platform GUI library supporting both -desktop operating systems (Windows, macOS, Linux) and mobile devices (Android, -iOS). It is written in Python and Cython, and can use a range of windowing -backends. - -Kivy is free and open source software distributed under the MIT license. - -FLTK ----- - -Python bindings for `the FLTK toolkit `_, a simple yet -powerful and mature cross-platform windowing system, are available from `the -PyFLTK project `_. - -OpenGL ------- - -For OpenGL bindings, see `PyOpenGL `_. - - -What platform-specific GUI toolkits exist for Python? -======================================================== - -By installing the `PyObjc Objective-C bridge -`_, Python programs can use Mac OS X's -Cocoa libraries. - -:ref:`Pythonwin ` by Mark Hammond includes an interface to the -Microsoft Foundation Classes and a Python programming environment -that's written mostly in Python using the MFC classes. - +macOS, Windows, and Unix platforms. + +Depending on what platform(s) you are aiming at, there are also several +alternatives. A `list of cross-platform +`_ and +`platform-specific +`_ GUI +frameworks can be found on the python wiki. Tkinter questions ================= diff --git a/Doc/faq/installed.rst b/Doc/faq/installed.rst index 42296533e26f32..16c9a74daffb1d 100644 --- a/Doc/faq/installed.rst +++ b/Doc/faq/installed.rst @@ -29,7 +29,7 @@ there are several possible ways it could have gotten there. * Some Windows machines also have Python installed. At this writing we're aware of computers from Hewlett-Packard and Compaq that include Python. Apparently some of HP/Compaq's administrative tools are written in Python. -* Many Unix-compatible operating systems, such as Mac OS X and some Linux +* Many Unix-compatible operating systems, such as macOS and some Linux distributions, have Python installed by default; it's included in the base installation. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 4d27abd4351ec0..faca834e965455 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -20,7 +20,7 @@ library and will be able to skip this step.) For third-party packages, search the `Python Package Index `_ or try `Google `_ or -another Web search engine. Searching for "Python" plus a keyword or two for +another web search engine. Searching for "Python" plus a keyword or two for your topic of interest will usually find something helpful. @@ -243,9 +243,6 @@ Be sure to use the :mod:`threading` module and not the :mod:`_thread` module. The :mod:`threading` module builds convenient abstractions on top of the low-level primitives provided by the :mod:`_thread` module. -Aahz has a set of slides from his threading tutorial that are helpful; see -http://www.pythoncraft.com/OSCON2001/. - None of my threads seem to run: why? ------------------------------------ @@ -617,9 +614,9 @@ use ``p.read(n)``. How do I access the serial (RS232) port? ---------------------------------------- -For Win32, POSIX (Linux, BSD, etc.), Jython: +For Win32, OSX, Linux, BSD, Jython, IronPython: - http://pyserial.sourceforge.net + https://pypi.org/project/pyserial/ For Unix, see a Usenet post by Mitch Chapman: diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index ed03c494388805..154563a859e31b 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -66,6 +66,8 @@ Static type checkers such as `Mypy `_, source code. +.. _faq-create-standalone-binary: + How can I create a stand-alone binary from a Python script? ----------------------------------------------------------- @@ -89,14 +91,15 @@ only contains those built-in modules which are actually used in the program. It then compiles the generated C code and links it with the rest of the Python interpreter to form a self-contained binary which acts exactly like your script. -Obviously, freeze requires a C compiler. There are several other utilities -which don't: - -* `py2exe `_ for Windows binaries -* `py2app `_ for Mac OS X binaries -* `cx_Freeze `_ for cross-platform - binaries +The following packages can help with the creation of console and GUI +executables: +* `Nuitka `_ (Cross-platform) +* `PyInstaller `_ (Cross-platform) +* `PyOxidizer `_ (Cross-platform) +* `cx_Freeze `_ (Cross-platform) +* `py2app `_ (macOS only) +* `py2exe `_ (Windows only) Are there coding standards or a style guide for Python programs? ---------------------------------------------------------------- @@ -833,6 +836,27 @@ ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to bite. +How do I get int literal attribute instead of SyntaxError? +---------------------------------------------------------- + +Trying to lookup an ``int`` literal attribute in the normal manner gives +a syntax error because the period is seen as a decimal point:: + + >>> 1.__class__ + File "", line 1 + 1.__class__ + ^ + SyntaxError: invalid decimal literal + +The solution is to separate the literal from the period +with either a space or parentheses. + + >>> 1 .__class__ + + >>> (1).__class__ + + + How do I convert a string to a number? -------------------------------------- @@ -1824,6 +1848,134 @@ For example, here is the implementation of return False +How can a subclass control what data is stored in an immutable instance? +------------------------------------------------------------------------ + +When subclassing an immutable type, override the :meth:`__new__` method +instead of the :meth:`__init__` method. The latter only runs *after* an +instance is created, which is too late to alter data in an immutable +instance. + +All of these immutable classes have a different signature than their +parent class: + +.. testcode:: + + from datetime import date + + class FirstOfMonthDate(date): + "Always choose the first day of the month" + def __new__(cls, year, month, day): + return super().__new__(cls, year, month, 1) + + class NamedInt(int): + "Allow text names for some numbers" + xlat = {'zero': 0, 'one': 1, 'ten': 10} + def __new__(cls, value): + value = cls.xlat.get(value, value) + return super().__new__(cls, value) + + class TitleStr(str): + "Convert str to name suitable for a URL path" + def __new__(cls, s): + s = s.lower().replace(' ', '-') + s = ''.join([c for c in s if c.isalnum() or c == '-']) + return super().__new__(cls, s) + +The classes can be used like this: + +.. doctest:: + + >>> FirstOfMonthDate(2012, 2, 14) + FirstOfMonthDate(2012, 2, 1) + >>> NamedInt('ten') + 10 + >>> NamedInt(20) + 20 + >>> TitleStr('Blog: Why Python Rocks') + 'blog-why-python-rocks' + + +How do I cache method calls? +---------------------------- + +The two principal tools for caching methods are +:func:`functools.cached_property` and :func:`functools.lru_cache`. The +former stores results at the instance level and the latter at the class +level. + +The *cached_property* approach only works with methods that do not take +any arguments. It does not create a reference to the instance. The +cached method result will be kept only as long as the instance is alive. + +The advantage is that when an instance is not longer used, the cached +method result will be released right away. The disadvantage is that if +instances accumulate, so too will the accumulated method results. They +can grow without bound. + +The *lru_cache* approach works with methods that have hashable +arguments. It creates a reference to the instance unless special +efforts are made to pass in weak references. + +The advantage of the least recently used algorithm is that the cache is +bounded by the specified *maxsize*. The disadvantage is that instances +are kept alive until they age out of the cache or until the cache is +cleared. + +This example shows the various techniques:: + + class Weather: + "Lookup weather information on a government website" + + def __init__(self, station_id): + self._station_id = station_id + # The _station_id is private and immutable + + def current_temperature(self): + "Latest hourly observation" + # Do not cache this because old results + # can be out of date. + + @cached_property + def location(self): + "Return the longitude/latitude coordinates of the station" + # Result only depends on the station_id + + @lru_cache(maxsize=20) + def historic_rainfall(self, date, units='mm'): + "Rainfall on a given date" + # Depends on the station_id, date, and units. + +The above example assumes that the *station_id* never changes. If the +relevant instance attributes are mutable, the *cached_property* approach +can't be made to work because it cannot detect changes to the +attributes. + +The *lru_cache* approach can be made to work, but the class needs to define the +*__eq__* and *__hash__* methods so the cache can detect relevant attribute +updates:: + + class Weather: + "Example with a mutable station identifier" + + def __init__(self, station_id): + self.station_id = station_id + + def change_station(self, station_id): + self.station_id = station_id + + def __eq__(self, other): + return self.station_id == other.station_id + + def __hash__(self): + return hash(self.station_id) + + @lru_cache(maxsize=20) + def historic_rainfall(self, date, units='cm'): + 'Rainfall on a given date' + # Depends on the station_id, date, and units. + + Modules ======= @@ -1940,7 +2092,7 @@ Jim Roskind suggests performing steps in the following order in each module: * ``import`` statements * active code (including globals that are initialized from imported values). -van Rossum doesn't like this approach much because the imports appear in a +Van Rossum doesn't like this approach much because the imports appear in a strange place, but it does work. Matthias Urlichs recommends restructuring your code so that the recursive import diff --git a/Doc/faq/windows.rst b/Doc/faq/windows.rst index 186dac2e255b37..0153a4f316ee82 100644 --- a/Doc/faq/windows.rst +++ b/Doc/faq/windows.rst @@ -140,9 +140,8 @@ offender. How do I make an executable from a Python script? ------------------------------------------------- -See `cx_Freeze `_ and -`py2exe `_, both are distutils extensions -that allow you to create console and GUI executables from Python code. +See :ref:`faq-create-standalone-binary` for a list of tools that can be used to +make executables. Is a ``*.pyd`` file the same as a DLL? diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 29c68ed72c6d70..1bbd05a5bcecd0 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -461,12 +461,13 @@ Glossary for best practices on working with annotations. __future__ - A pseudo-module which programmers can use to enable new language features - which are not compatible with the current interpreter. - - By importing the :mod:`__future__` module and evaluating its variables, - you can see when a new feature was first added to the language and when it - becomes the default:: + A :ref:`future statement `, ``from __future__ import ``, + directs the compiler to compile the current module using syntax or + semantics that will become standard in a future release of Python. + The :mod:`__future__` module documents the possible values of + *feature*. By importing this module and evaluating its variables, + you can see when a new feature was first added to the language and + when it will (or did) become the default:: >>> import __future__ >>> __future__.division @@ -519,12 +520,13 @@ Glossary :func:`functools.singledispatch` decorator, and :pep:`443`. generic type - A :term:`type` that can be parameterized; typically a container like - :class:`list`. Used for :term:`type hints ` and + A :term:`type` that can be parameterized; typically a + :ref:`container class` such as :class:`list` or + :class:`dict`. Used for :term:`type hints ` and :term:`annotations `. - See :pep:`483` for more details, and :mod:`typing` or - :ref:`generic alias type ` for its uses. + For more details, see :ref:`generic alias types`, + :pep:`483`, :pep:`484`, :pep:`585`, and the :mod:`typing` module. GIL See :term:`global interpreter lock`. @@ -667,6 +669,11 @@ Glossary More information can be found in :ref:`typeiter`. + .. impl-detail:: + + CPython does not consistently apply the requirement that an iterator + define :meth:`__iter__`. + key function A key function or collation function is a callable that returns a value used for sorting or ordering. For example, :func:`locale.strxfrm` is @@ -712,7 +719,7 @@ Glossary On Unix, it is the encoding of the LC_CTYPE locale. It can be set with ``locale.setlocale(locale.LC_CTYPE, new_locale)``. - On Windows, it is is the ANSI code page (ex: ``cp1252``). + On Windows, it is the ANSI code page (ex: ``cp1252``). ``locale.getpreferredencoding(False)`` can be used to get the locale encoding. diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst index 3e61103e99c9a6..2bc2f2d4c839e2 100644 --- a/Doc/howto/annotations.rst +++ b/Doc/howto/annotations.rst @@ -156,7 +156,7 @@ Manually Un-Stringizing Stringized Annotations require annotating with string values that specifically *can't* be evaluated. For example: - * :pep:`604` union types using `|`, before support for this + * :pep:`604` union types using ``|``, before support for this was added to Python 3.10. * Definitions that aren't needed at runtime, only imported when :const:`typing.TYPE_CHECKING` is true. diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 575caeb720f3d0..6ce062d0fa853e 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -1264,6 +1264,9 @@ Using the non-data descriptor protocol, a pure Python version of def __get__(self, obj, objtype=None): return self.f + def __call__(self, *args, **kwds): + return self.f(*args, **kwds) + .. testcode:: :hide: @@ -1272,6 +1275,8 @@ Using the non-data descriptor protocol, a pure Python version of def f(x): return x * 10 + wrapped_ord = StaticMethod(ord) + .. doctest:: :hide: @@ -1279,6 +1284,8 @@ Using the non-data descriptor protocol, a pure Python version of 30 >>> E_sim().f(3) 30 + >>> wrapped_ord('A') + 65 Class methods @@ -1344,7 +1351,7 @@ Using the non-data descriptor protocol, a pure Python version of if cls is None: cls = type(obj) if hasattr(type(self.f), '__get__'): - return self.f.__get__(cls) + return self.f.__get__(cls, cls) return MethodType(self.f, cls) .. testcode:: diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst deleted file mode 100644 index 9ece93e660504f..00000000000000 --- a/Doc/howto/enum.rst +++ /dev/null @@ -1,1416 +0,0 @@ -========== -Enum HOWTO -========== - -:Author: Ethan Furman - -.. _enum-basic-tutorial: - -.. currentmodule:: enum - -Basic Enum Tutorial -------------------- - -An :class:`Enum` is a set of symbolic names bound to unique values. They are -similar to global variables, but they offer a more useful :func:`repr()`, -grouping, type-safety, and a few other features. - -They are most useful when you have a variable that can take one of a limited -selection of values. For example, the days of the week:: - - >>> from enum import Enum - >>> class Weekday(Enum): - ... MONDAY = 1 - ... TUESDAY = 2 - ... WEDNESDAY = 3 - ... THURSDAY = 4 - ... FRIDAY = 5 - ... SATURDAY = 6 - ... SUNDAY = 7 - -As you can see, creating an :class:`Enum` is as simple as writing a class that -inherits from :class:`Enum` itself. - -.. note:: Case of Enum Members - - Because Enums are used to represent constants we recommend using - UPPER_CASE names for members, and will be using that style in our examples. - -Depending on the nature of the enum a member's value may or may not be -important, but either way that value can be used to get the corresponding -member:: - - >>> Weekday(3) - Weekday.WEDNESDAY - -As you can see, the ``repr()`` of a member shows the enum name and the -member name. The ``str()`` on a member shows only its name:: - - >>> print(Weekday.THURSDAY) - THURSDAY - -The *type* of an enumeration member is the enum it belongs to:: - - >>> type(Weekday.MONDAY) - - >>> isinstance(Weekday.FRIDAY, Weekday) - True - -Enum members have an attribute that contains just their :attr:`name`:: - - >>> print(Weekday.TUESDAY.name) - TUESDAY - -Likewise, they have an attribute for their :attr:`value`:: - - - >>> Weekday.WEDNESDAY.value - 3 - -Unlike many languages that treat enumerations solely as name/value pairs, -Python Enums can have behavior added. For example, :class:`datetime.date` -has two methods for returning the weekday: :meth:`weekday` and :meth:`isoweekday`. -The difference is that one of them counts from 0-6 and the other from 1-7. -Rather than keep track of that ourselves we can add a method to the :class:`Weekday` -enum to extract the day from the :class:`date` instance and return the matching -enum member:: - - @classmethod - def from_date(cls, date): - return cls(date.isoweekday()) - -The complete :class:`Weekday` enum now looks like this:: - - >>> class Weekday(Enum): - ... MONDAY = 1 - ... TUESDAY = 2 - ... WEDNESDAY = 3 - ... THURSDAY = 4 - ... FRIDAY = 5 - ... SATURDAY = 6 - ... SUNDAY = 7 - ... # - ... @classmethod - ... def from_date(cls, date): - ... return cls(date.isoweekday()) - -Now we can find out what today is! Observe:: - - >>> from datetime import date - >>> Weekday.from_date(date.today()) - Weekday.TUESDAY - -Of course, if you're reading this on some other day, you'll see that day instead. - -This :class:`Weekday` enum is great if our variable only needs one day, but -what if we need several? Maybe we're writing a function to plot chores during -a week, and don't want to use a :class:`list` -- we could use a different type -of :class:`Enum`:: - - >>> from enum import Flag - >>> class Weekday(Flag): - ... MONDAY = 1 - ... TUESDAY = 2 - ... WEDNESDAY = 4 - ... THURSDAY = 8 - ... FRIDAY = 16 - ... SATURDAY = 32 - ... SUNDAY = 64 - -We've changed two things: we're inherited from :class:`Flag`, and the values are -all powers of 2. - -Just like the original :class:`Weekday` enum above, we can have a single selection:: - - >>> first_week_day = Weekday.MONDAY - >>> first_week_day - Weekday.MONDAY - -But :class:`Flag` also allows us to combine several members into a single -variable:: - - >>> weekend = Weekday.SATURDAY | Weekday.SUNDAY - >>> weekend - Weekday.SATURDAY|Weekday.SUNDAY - -You can even iterate over a :class:`Flag` variable:: - - >>> for day in weekend: - ... print(day) - SATURDAY - SUNDAY - -Okay, let's get some chores set up:: - - >>> chores_for_ethan = { - ... 'feed the cat': Weekday.MONDAY | Weekday.WEDNESDAY | Weekday.FRIDAY, - ... 'do the dishes': Weekday.TUESDAY | Weekday.THURSDAY, - ... 'answer SO questions': Weekday.SATURDAY, - ... } - -And a function to display the chores for a given day:: - - >>> def show_chores(chores, day): - ... for chore, days in chores.items(): - ... if day in days: - ... print(chore) - >>> show_chores(chores_for_ethan, Weekday.SATURDAY) - answer SO questions - -In cases where the actual values of the members do not matter, you can save -yourself some work and use :func:`auto()` for the values:: - - >>> from enum import auto - >>> class Weekday(Flag): - ... MONDAY = auto() - ... TUESDAY = auto() - ... WEDNESDAY = auto() - ... THURSDAY = auto() - ... FRIDAY = auto() - ... SATURDAY = auto() - ... SUNDAY = auto() - - -.. _enum-advanced-tutorial: - -Programmatic access to enumeration members and their attributes ---------------------------------------------------------------- - -Sometimes it's useful to access members in enumerations programmatically (i.e. -situations where ``Color.RED`` won't do because the exact color is not known -at program-writing time). ``Enum`` allows such access:: - - >>> Color(1) - Color.RED - >>> Color(3) - Color.BLUE - -If you want to access enum members by *name*, use item access:: - - >>> Color['RED'] - Color.RED - >>> Color['GREEN'] - Color.GREEN - -If you have an enum member and need its :attr:`name` or :attr:`value`:: - - >>> member = Color.RED - >>> member.name - 'RED' - >>> member.value - 1 - - -Duplicating enum members and values ------------------------------------ - -Having two enum members with the same name is invalid:: - - >>> class Shape(Enum): - ... SQUARE = 2 - ... SQUARE = 3 - ... - Traceback (most recent call last): - ... - TypeError: 'SQUARE' already defined as: 2 - -However, an enum member can have other names associated with it. Given two -entries ``A`` and ``B`` with the same value (and ``A`` defined first), ``B`` -is an alias for the member ``A``. By-value lookup of the value of ``A`` will -return the member ``A``. By-name lookup of ``A`` will return the member ``A``. -By-name lookup of ``B`` will also return the member ``A``:: - - >>> class Shape(Enum): - ... SQUARE = 2 - ... DIAMOND = 1 - ... CIRCLE = 3 - ... ALIAS_FOR_SQUARE = 2 - ... - >>> Shape.SQUARE - Shape.SQUARE - >>> Shape.ALIAS_FOR_SQUARE - Shape.SQUARE - >>> Shape(2) - Shape.SQUARE - -.. note:: - - Attempting to create a member with the same name as an already - defined attribute (another member, a method, etc.) or attempting to create - an attribute with the same name as a member is not allowed. - - -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:: - - >>> from enum import Enum, unique - >>> @unique - ... class Mistake(Enum): - ... ONE = 1 - ... TWO = 2 - ... THREE = 3 - ... FOUR = 3 - ... - Traceback (most recent call last): - ... - ValueError: duplicate values found in : FOUR -> THREE - - -Using automatic values ----------------------- - -If the exact value is unimportant you can use :class:`auto`:: - - >>> from enum import Enum, auto - >>> class Color(Enum): - ... RED = auto() - ... BLUE = auto() - ... GREEN = auto() - ... - >>> [member.value for member in Color] - [1, 2, 3] - -The values are chosen by :func:`_generate_next_value_`, which can be -overridden:: - - >>> class AutoName(Enum): - ... def _generate_next_value_(name, start, count, last_values): - ... return name - ... - >>> class Ordinal(AutoName): - ... NORTH = auto() - ... SOUTH = auto() - ... EAST = auto() - ... WEST = auto() - ... - >>> [member.value for member in Color] - ['NORTH', 'SOUTH', 'EAST', 'WEST'] - -.. note:: - - The :meth:`_generate_next_value_` method must be defined before any members. - -Iteration ---------- - -Iterating over the members of an enum does not provide the aliases:: - - >>> list(Shape) - [Shape.SQUARE, Shape.DIAMOND, Shape.CIRCLE] - -The special attribute ``__members__`` is a read-only ordered mapping of names -to members. It includes all names defined in the enumeration, including the -aliases:: - - >>> for name, member in Shape.__members__.items(): - ... name, member - ... - ('SQUARE', Shape.SQUARE) - ('DIAMOND', Shape.DIAMOND) - ('CIRCLE', Shape.CIRCLE) - ('ALIAS_FOR_SQUARE', Shape.SQUARE) - -The ``__members__`` attribute can be used for detailed programmatic access to -the enumeration members. For example, finding all the aliases:: - - >>> [name for name, member in Shape.__members__.items() if member.name != name] - ['ALIAS_FOR_SQUARE'] - - -Comparisons ------------ - -Enumeration members are compared by identity:: - - >>> Color.RED is Color.RED - True - >>> Color.RED is Color.BLUE - False - >>> Color.RED is not Color.BLUE - True - -Ordered comparisons between enumeration values are *not* supported. Enum -members are not integers (but see `IntEnum`_ below):: - - >>> Color.RED < Color.BLUE - Traceback (most recent call last): - File "", line 1, in - TypeError: '<' not supported between instances of 'Color' and 'Color' - -Equality comparisons are defined though:: - - >>> Color.BLUE == Color.RED - False - >>> Color.BLUE != Color.RED - True - >>> Color.BLUE == Color.BLUE - True - -Comparisons against non-enumeration values will always compare not equal -(again, :class:`IntEnum` was explicitly designed to behave differently, see -below):: - - >>> Color.BLUE == 2 - False - - -Allowed members and attributes of enumerations ----------------------------------------------- - -Most of the examples above use integers for enumeration values. Using integers is -short and handy (and provided by default by the `Functional API`_), but not -strictly enforced. In the vast majority of use-cases, one doesn't care what -the actual value of an enumeration is. But if the value *is* important, -enumerations can have arbitrary values. - -Enumerations are Python classes, and can have methods and special methods as -usual. If we have this enumeration:: - - >>> class Mood(Enum): - ... FUNKY = 1 - ... HAPPY = 3 - ... - ... def describe(self): - ... # self is the member here - ... return self.name, self.value - ... - ... def __str__(self): - ... return 'my custom str! {0}'.format(self.value) - ... - ... @classmethod - ... def favorite_mood(cls): - ... # cls here is the enumeration - ... return cls.HAPPY - ... - -Then:: - - >>> Mood.favorite_mood() - Mood.HAPPY - >>> Mood.HAPPY.describe() - ('HAPPY', 3) - >>> str(Mood.FUNKY) - 'my custom str! 1' - -The rules for what is allowed are as follows: names that start and end with -a single underscore are reserved by enum and cannot be used; all other -attributes defined within an enumeration will become members of this -enumeration, with the exception of special methods (:meth:`__str__`, -:meth:`__add__`, etc.), descriptors (methods are also descriptors), and -variable names listed in :attr:`_ignore_`. - -Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then -any value(s) given to the enum member will be passed into those methods. -See `Planet`_ for an example. - - -Restricted Enum subclassing ---------------------------- - -A new :class:`Enum` class must have one base enum class, up to one concrete -data type, and as many :class:`object`-based mixin classes as needed. The -order of these base classes is:: - - class EnumName([mix-in, ...,] [data-type,] base-enum): - pass - -Also, subclassing an enumeration is allowed only if the enumeration does not define -any members. So this is forbidden:: - - >>> class MoreColor(Color): - ... PINK = 17 - ... - Traceback (most recent call last): - ... - TypeError: MoreColor: cannot extend enumeration 'Color' - -But this is allowed:: - - >>> class Foo(Enum): - ... def some_behavior(self): - ... pass - ... - >>> class Bar(Foo): - ... HAPPY = 1 - ... SAD = 2 - ... - -Allowing subclassing of enums that define members would lead to a violation of -some important invariants of types and instances. On the other hand, it makes -sense to allow sharing some common behavior between a group of enumerations. -(See `OrderedEnum`_ for an example.) - - -Pickling --------- - -Enumerations can be pickled and unpickled:: - - >>> from test.test_enum import Fruit - >>> from pickle import dumps, loads - >>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO)) - True - -The usual restrictions for pickling apply: picklable enums must be defined in -the top level of a module, since unpickling requires them to be importable -from that module. - -.. note:: - - With pickle protocol version 4 it is possible to easily pickle enums - nested in other classes. - -It is possible to modify how enum members are pickled/unpickled by defining -:meth:`__reduce_ex__` in the enumeration class. - - -Functional API --------------- - -The :class:`Enum` class is callable, providing the following functional API:: - - >>> Animal = Enum('Animal', 'ANT BEE CAT DOG') - >>> Animal - - >>> Animal.ANT - Animal.ANT - >>> Animal.ANT.value - 1 - >>> list(Animal) - [Animal.ANT, Animal.BEE, Animal.CAT, Animal.DOG] - -The semantics of this API resemble :class:`~collections.namedtuple`. The first -argument of the call to :class:`Enum` is the name of the enumeration. - -The second argument is the *source* of enumeration member names. It can be a -whitespace-separated string of names, a sequence of names, a sequence of -2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to -values. The last two options enable assigning arbitrary values to -enumerations; the others auto-assign increasing integers starting with 1 (use -the ``start`` parameter to specify a different starting value). A -new class derived from :class:`Enum` is returned. In other words, the above -assignment to :class:`Animal` is equivalent to:: - - >>> class Animal(Enum): - ... ANT = 1 - ... BEE = 2 - ... CAT = 3 - ... DOG = 4 - ... - -The reason for defaulting to ``1`` as the starting number and not ``0`` is -that ``0`` is ``False`` in a boolean sense, but by default enum members all -evaluate to ``True``. - -Pickling enums created with the functional API can be tricky as frame stack -implementation details are used to try and figure out which module the -enumeration is being created in (e.g. it will fail if you use a utility -function in separate module, and also may not work on IronPython or Jython). -The solution is to specify the module name explicitly as follows:: - - >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__) - -.. warning:: - - If ``module`` is not supplied, and Enum cannot determine what it is, - the new Enum members will not be unpicklable; to keep errors closer to - the source, pickling will be disabled. - -The new pickle protocol 4 also, in some circumstances, relies on -:attr:`~definition.__qualname__` being set to the location where pickle will be able -to find the class. For example, if the class was made available in class -SomeData in the global scope:: - - >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal') - -The complete signature is:: - - Enum( - value='NewEnumName', - names=<...>, - *, - module='...', - qualname='...', - type=, - start=1, - ) - -:value: What the new enum class will record as its name. - -:names: The enum members. This can be a whitespace or comma separated string - (values will start at 1 unless otherwise specified):: - - 'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE' - - or an iterator of names:: - - ['RED', 'GREEN', 'BLUE'] - - or an iterator of (name, value) pairs:: - - [('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)] - - or a mapping:: - - {'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42} - -:module: name of module where new enum class can be found. - -:qualname: where in module new enum class can be found. - -:type: type to mix in to new enum class. - -:start: number to start counting at if only names are passed in. - -.. versionchanged:: 3.5 - The *start* parameter was added. - - -Derived Enumerations --------------------- - -IntEnum -^^^^^^^ - -The first variation of :class:`Enum` that is provided is also a subclass of -:class:`int`. Members of an :class:`IntEnum` can be compared to integers; -by extension, integer enumerations of different types can also be compared -to each other:: - - >>> from enum import IntEnum - >>> class Shape(IntEnum): - ... CIRCLE = 1 - ... SQUARE = 2 - ... - >>> class Request(IntEnum): - ... POST = 1 - ... GET = 2 - ... - >>> Shape == 1 - False - >>> Shape.CIRCLE == 1 - True - >>> Shape.CIRCLE == Request.POST - True - -However, they still can't be compared to standard :class:`Enum` enumerations:: - - >>> class Shape(IntEnum): - ... CIRCLE = 1 - ... SQUARE = 2 - ... - >>> class Color(Enum): - ... RED = 1 - ... GREEN = 2 - ... - >>> Shape.CIRCLE == Color.RED - False - -:class:`IntEnum` values behave like integers in other ways you'd expect:: - - >>> int(Shape.CIRCLE) - 1 - >>> ['a', 'b', 'c'][Shape.CIRCLE] - 'b' - >>> [i for i in range(Shape.SQUARE)] - [0, 1] - - -StrEnum -^^^^^^^ - -The second variation of :class:`Enum` that is provided is also a subclass of -:class:`str`. Members of a :class:`StrEnum` can be compared to strings; -by extension, string enumerations of different types can also be compared -to each other. :class:`StrEnum` exists to help avoid the problem of getting -an incorrect member:: - - >>> from enum import StrEnum - >>> class Directions(StrEnum): - ... NORTH = 'north', # notice the trailing comma - ... SOUTH = 'south' - -Before :class:`StrEnum`, ``Directions.NORTH`` would have been the :class:`tuple` -``('north',)``. - -.. versionadded:: 3.10 - - -IntFlag -^^^^^^^ - -The next variation of :class:`Enum` provided, :class:`IntFlag`, is also based -on :class:`int`. The difference being :class:`IntFlag` members can be combined -using the bitwise operators (&, \|, ^, ~) and the result is still an -:class:`IntFlag` member, if possible. However, as the name implies, :class:`IntFlag` -members also subclass :class:`int` and can be used wherever an :class:`int` is -used. - -.. note:: - - Any operation on an :class:`IntFlag` member besides the bit-wise operations will - lose the :class:`IntFlag` membership. - - Bit-wise operations that result in invalid :class:`IntFlag` values will lose the - :class:`IntFlag` membership. See :class:`FlagBoundary` for - details. - -.. versionadded:: 3.6 -.. versionchanged:: 3.10 - -Sample :class:`IntFlag` class:: - - >>> from enum import IntFlag - >>> class Perm(IntFlag): - ... R = 4 - ... W = 2 - ... X = 1 - ... - >>> Perm.R | Perm.W - Perm.R|Perm.W - >>> Perm.R + Perm.W - 6 - >>> RW = Perm.R | Perm.W - >>> Perm.R in RW - True - -It is also possible to name the combinations:: - - >>> class Perm(IntFlag): - ... R = 4 - ... W = 2 - ... X = 1 - ... RWX = 7 - >>> Perm.RWX - Perm.RWX - >>> ~Perm.RWX - Perm(0) - >>> Perm(7) - Perm.RWX - -.. note:: - - Named combinations are considered aliases. Aliases do not show up during - iteration, but can be returned from by-value lookups. - -.. versionchanged:: 3.10 - -Another important difference between :class:`IntFlag` and :class:`Enum` is that -if no flags are set (the value is 0), its boolean evaluation is :data:`False`:: - - >>> Perm.R & Perm.X - Perm(0) - >>> bool(Perm.R & Perm.X) - False - -Because :class:`IntFlag` members are also subclasses of :class:`int` they can -be combined with them (but may lose :class:`IntFlag` membership:: - - >>> Perm.X | 4 - Perm.R|Perm.X - - >>> Perm.X | 8 - 9 - -.. note:: - - The negation operator, ``~``, always returns an :class:`IntFlag` member with a - positive value:: - - >>> (~Perm.X).value == (Perm.R|Perm.W).value == 6 - True - -:class:`IntFlag` members can also be iterated over:: - - >>> list(RW) - [Perm.R, Perm.W] - -.. versionadded:: 3.10 - - -Flag -^^^^ - -The last variation is :class:`Flag`. Like :class:`IntFlag`, :class:`Flag` -members can be combined using the bitwise operators (&, \|, ^, ~). Unlike -:class:`IntFlag`, they cannot be combined with, nor compared against, any -other :class:`Flag` enumeration, nor :class:`int`. While it is possible to -specify the values directly it is recommended to use :class:`auto` as the -value and let :class:`Flag` select an appropriate value. - -.. versionadded:: 3.6 - -Like :class:`IntFlag`, if a combination of :class:`Flag` members results in no -flags being set, the boolean evaluation is :data:`False`:: - - >>> from enum import Flag, auto - >>> class Color(Flag): - ... RED = auto() - ... BLUE = auto() - ... GREEN = auto() - ... - >>> Color.RED & Color.GREEN - Color(0) - >>> bool(Color.RED & Color.GREEN) - False - -Individual flags should have values that are powers of two (1, 2, 4, 8, ...), -while combinations of flags won't:: - - >>> class Color(Flag): - ... RED = auto() - ... BLUE = auto() - ... GREEN = auto() - ... WHITE = RED | BLUE | GREEN - ... - >>> Color.WHITE - Color.WHITE - -Giving a name to the "no flags set" condition does not change its boolean -value:: - - >>> class Color(Flag): - ... BLACK = 0 - ... RED = auto() - ... BLUE = auto() - ... GREEN = auto() - ... - >>> Color.BLACK - Color.BLACK - >>> bool(Color.BLACK) - False - -:class:`Flag` members can also be iterated over:: - - >>> purple = Color.RED | Color.BLUE - >>> list(purple) - [Color.RED, Color.BLUE] - -.. versionadded:: 3.10 - -.. note:: - - For the majority of new code, :class:`Enum` and :class:`Flag` are strongly - recommended, since :class:`IntEnum` and :class:`IntFlag` break some - semantic promises of an enumeration (by being comparable to integers, and - thus by transitivity to other unrelated enumerations). :class:`IntEnum` - and :class:`IntFlag` should be used only in cases where :class:`Enum` and - :class:`Flag` will not do; for example, when integer constants are replaced - with enumerations, or for interoperability with other systems. - - -Others -^^^^^^ - -While :class:`IntEnum` is part of the :mod:`enum` module, it would be very -simple to implement independently:: - - class IntEnum(int, Enum): - pass - -This demonstrates how similar derived enumerations can be defined; for example -a :class:`StrEnum` that mixes in :class:`str` instead of :class:`int`. - -Some rules: - -1. When subclassing :class:`Enum`, mix-in types must appear before - :class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum` - example above. -2. While :class:`Enum` can have members of any type, once you mix in an - additional type, all the members must have values of that type, e.g. - :class:`int` above. This restriction does not apply to mix-ins which only - add methods and don't specify another type. -3. When another data type is mixed in, the :attr:`value` attribute is *not the - same* as the enum member itself, although it is equivalent and will compare - equal. -4. %-style formatting: `%s` and `%r` call the :class:`Enum` class's - :meth:`__str__` and :meth:`__repr__` respectively; other codes (such as - `%i` or `%h` for IntEnum) treat the enum member as its mixed-in type. -5. :ref:`Formatted string literals `, :meth:`str.format`, - and :func:`format` will use the mixed-in type's :meth:`__format__` - unless :meth:`__str__` or :meth:`__format__` is overridden in the subclass, - in which case the overridden methods or :class:`Enum` methods will be used. - Use the !s and !r format codes to force usage of the :class:`Enum` class's - :meth:`__str__` and :meth:`__repr__` methods. - -When to use :meth:`__new__` vs. :meth:`__init__` ------------------------------------------------- - -:meth:`__new__` must be used whenever you want to customize the actual value of -the :class:`Enum` member. Any other modifications may go in either -:meth:`__new__` or :meth:`__init__`, with :meth:`__init__` being preferred. - -For example, if you want to pass several items to the constructor, but only -want one of them to be the value:: - - >>> class Coordinate(bytes, Enum): - ... """ - ... Coordinate with binary codes that can be indexed by the int code. - ... """ - ... def __new__(cls, value, label, unit): - ... obj = bytes.__new__(cls, [value]) - ... obj._value_ = value - ... obj.label = label - ... obj.unit = unit - ... return obj - ... PX = (0, 'P.X', 'km') - ... PY = (1, 'P.Y', 'km') - ... VX = (2, 'V.X', 'km/s') - ... VY = (3, 'V.Y', 'km/s') - ... - - >>> print(Coordinate['PY']) - PY - - >>> print(Coordinate(3)) - VY - - -Finer Points -^^^^^^^^^^^^ - -Supported ``__dunder__`` names -"""""""""""""""""""""""""""""" - -:attr:`__members__` is a read-only ordered mapping of ``member_name``:``member`` -items. It is only available on the class. - -:meth:`__new__`, if specified, must create and return the enum members; it is -also a very good idea to set the member's :attr:`_value_` appropriately. Once -all the members are created it is no longer used. - - -Supported ``_sunder_`` names -"""""""""""""""""""""""""""" - -- ``_name_`` -- name of the member -- ``_value_`` -- value of the member; can be set / modified in ``__new__`` - -- ``_missing_`` -- a lookup function used when a value is not found; may be - overridden -- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, - that will not be transformed into members, and will be removed from the final - class -- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent - (class attribute, removed during class creation) -- ``_generate_next_value_`` -- used by the `Functional API`_ and by - :class:`auto` to get an appropriate value for an enum member; may be - overridden - -.. note:: - - For standard :class:`Enum` classes the next value chosen is the last value seen - incremented by one. - - For :class:`Flag` classes the next value chosen will be the next highest - power-of-two, regardless of the last value seen. - -.. versionadded:: 3.6 ``_missing_``, ``_order_``, ``_generate_next_value_`` -.. versionadded:: 3.7 ``_ignore_`` - -To help keep Python 2 / Python 3 code in sync an :attr:`_order_` attribute can -be provided. It will be checked against the actual order of the enumeration -and raise an error if the two do not match:: - - >>> class Color(Enum): - ... _order_ = 'RED GREEN BLUE' - ... RED = 1 - ... BLUE = 3 - ... GREEN = 2 - ... - Traceback (most recent call last): - ... - TypeError: member order does not match _order_: - ['RED', 'BLUE', 'GREEN'] - ['RED', 'GREEN', 'BLUE'] - -.. note:: - - In Python 2 code the :attr:`_order_` attribute is necessary as definition - order is lost before it can be recorded. - - -_Private__names -""""""""""""""" - -Private names are not converted to enum members, but remain normal attributes. - -.. versionchanged:: 3.10 - - -``Enum`` member type -"""""""""""""""""""" - -Enum members are instances of their enum class, and are normally accessed as -``EnumClass.member``. In Python versions ``3.5`` to ``3.9`` you could access -members from other members -- this practice was discouraged, and in ``3.12`` -:class:`Enum` will return to not allowing it, while in ``3.10`` and ``3.11`` -it will raise a :exc:`DeprecationWarning`:: - - >>> class FieldTypes(Enum): - ... name = 0 - ... value = 1 - ... size = 2 - ... - >>> FieldTypes.value.size # doctest: +SKIP - DeprecationWarning: accessing one member from another is not supported, - and will be disabled in 3.12 - - -.. versionchanged:: 3.5 -.. versionchanged:: 3.10 - - -Creating members that are mixed with other data types -""""""""""""""""""""""""""""""""""""""""""""""""""""" - -When subclassing other data types, such as :class:`int` or :class:`str`, with -an :class:`Enum`, all values after the `=` are passed to that data type's -constructor. For example:: - - >>> class MyEnum(IntEnum): - ... example = '11', 16 # '11' will be interpreted as a hexadecimal - ... # number - >>> MyEnum.example.value - 17 - - -Boolean value of ``Enum`` classes and members -""""""""""""""""""""""""""""""""""""""""""""" - -Enum classes that are mixed with non-:class:`Enum` types (such as -:class:`int`, :class:`str`, etc.) are evaluated according to the mixed-in -type's rules; otherwise, all members evaluate as :data:`True`. To make your -own enum's boolean evaluation depend on the member's value add the following to -your class:: - - def __bool__(self): - return bool(self.value) - -Plain :class:`Enum` classes always evaluate as :data:`True`. - - -``Enum`` classes with methods -""""""""""""""""""""""""""""" - -If you give your enum subclass extra methods, like the `Planet`_ -class above, those methods will show up in a :func:`dir` of the member, -but not of the class:: - - >>> dir(Planet) - ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__'] - >>> dir(Planet.EARTH) - ['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value'] - - -Combining members of ``Flag`` -""""""""""""""""""""""""""""" - -Iterating over a combination of :class:`Flag` members will only return the members that -are comprised of a single bit:: - - >>> class Color(Flag): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - ... MAGENTA = RED | BLUE - ... YELLOW = RED | GREEN - ... CYAN = GREEN | BLUE - ... - >>> Color(3) # named combination - Color.YELLOW - >>> Color(7) # not named combination - Color.RED|Color.GREEN|Color.BLUE - -``StrEnum`` and :meth:`str.__str__` -""""""""""""""""""""""""""""""""""" - -An important difference between :class:`StrEnum` and other Enums is the -:meth:`__str__` method; because :class:`StrEnum` members are strings, some -parts of Python will read the string data directly, while others will call -:meth:`str()`. To make those two operations have the same result, -:meth:`StrEnum.__str__` will be the same as :meth:`str.__str__` so that -``str(StrEnum.member) == StrEnum.member`` is true. - -``Flag`` and ``IntFlag`` minutia -"""""""""""""""""""""""""""""""" - -Using the following snippet for our examples:: - - >>> class Color(IntFlag): - ... BLACK = 0 - ... RED = 1 - ... GREEN = 2 - ... BLUE = 4 - ... PURPLE = RED | BLUE - ... WHITE = RED | GREEN | BLUE - ... - -the following are true: - -- single-bit flags are canonical -- multi-bit and zero-bit flags are aliases -- only canonical flags are returned during iteration:: - - >>> list(Color.WHITE) - [Color.RED, Color.GREEN, Color.BLUE] - -- negating a flag or flag set returns a new flag/flag set with the - corresponding positive integer value:: - - >>> Color.BLUE - Color.BLUE - - >>> ~Color.BLUE - Color.RED|Color.GREEN - -- names of pseudo-flags are constructed from their members' names:: - - >>> (Color.RED | Color.GREEN).name - 'RED|GREEN' - -- multi-bit flags, aka aliases, can be returned from operations:: - - >>> Color.RED | Color.BLUE - Color.PURPLE - - >>> Color(7) # or Color(-1) - Color.WHITE - - >>> Color(0) - Color.BLACK - -- membership / containment checking has changed slightly -- zero valued flags - are never considered to be contained:: - - >>> Color.BLACK in Color.WHITE - False - - otherwise, if all bits of one flag are in the other flag, True is returned:: - - >>> Color.PURPLE in Color.WHITE - True - -There is a new boundary mechanism that controls how out-of-range / invalid -bits are handled: ``STRICT``, ``CONFORM``, ``EJECT``, and ``KEEP``: - - * STRICT --> raises an exception when presented with invalid values - * CONFORM --> discards any invalid bits - * EJECT --> lose Flag status and become a normal int with the given value - * KEEP --> keep the extra bits - - keeps Flag status and extra bits - - extra bits do not show up in iteration - - extra bits do show up in repr() and str() - -The default for Flag is ``STRICT``, the default for ``IntFlag`` is ``EJECT``, -and the default for ``_convert_`` is ``KEEP`` (see ``ssl.Options`` for an -example of when ``KEEP`` is needed). - - -.. _enum-class-differences: - -How are Enums different? ------------------------- - -Enums have a custom metaclass that affects many aspects of both derived :class:`Enum` -classes and their instances (members). - - -Enum Classes -^^^^^^^^^^^^ - -The :class:`EnumType` metaclass is responsible for providing the -:meth:`__contains__`, :meth:`__dir__`, :meth:`__iter__` and other methods that -allow one to do things with an :class:`Enum` class that fail on a typical -class, such as `list(Color)` or `some_enum_var in Color`. :class:`EnumType` is -responsible for ensuring that various other methods on the final :class:`Enum` -class are correct (such as :meth:`__new__`, :meth:`__getnewargs__`, -:meth:`__str__` and :meth:`__repr__`). - - -Enum Members (aka instances) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The most interesting thing about enum members is that they are singletons. -:class:`EnumType` creates them all while it is creating the enum class itself, -and then puts a custom :meth:`__new__` in place to ensure that no new ones are -ever instantiated by returning only the existing member instances. - - -.. _enum-cookbook: - - -While :class:`Enum`, :class:`IntEnum`, :class:`StrEnum`, :class:`Flag`, and -:class:`IntFlag` are expected to cover the majority of use-cases, they cannot -cover them all. Here are recipes for some different types of enumerations -that can be used directly, or as examples for creating one's own. - - -Omitting values -^^^^^^^^^^^^^^^ - -In many use-cases one doesn't care what the actual value of an enumeration -is. There are several ways to define this type of simple enumeration: - -- use instances of :class:`auto` for the value -- use instances of :class:`object` as the value -- use a descriptive string as the value -- use a tuple as the value and a custom :meth:`__new__` to replace the - tuple with an :class:`int` value - -Using any of these methods signifies to the user that these values are not -important, and also enables one to add, remove, or reorder members without -having to renumber the remaining members. - - -Using :class:`auto` -""""""""""""""""""" - -Using :class:`auto` would look like:: - - >>> class Color(Enum): - ... RED = auto() - ... BLUE = auto() - ... GREEN = auto() - ... - >>> Color.GREEN - - - -Using :class:`object` -""""""""""""""""""""" - -Using :class:`object` would look like:: - - >>> class Color(Enum): - ... RED = object() - ... GREEN = object() - ... BLUE = object() - ... - >>> Color.GREEN - - - -Using a descriptive string -"""""""""""""""""""""""""" - -Using a string as the value would look like:: - - >>> class Color(Enum): - ... RED = 'stop' - ... GREEN = 'go' - ... BLUE = 'too fast!' - ... - >>> Color.GREEN - - >>> Color.GREEN.value - 'go' - - -Using a custom :meth:`__new__` -"""""""""""""""""""""""""""""" - -Using an auto-numbering :meth:`__new__` would look like:: - - >>> class AutoNumber(Enum): - ... def __new__(cls): - ... value = len(cls.__members__) + 1 - ... obj = object.__new__(cls) - ... obj._value_ = value - ... return obj - ... - >>> class Color(AutoNumber): - ... RED = () - ... GREEN = () - ... BLUE = () - ... - >>> Color.GREEN - - >>> Color.GREEN.value - 2 - -To make a more general purpose ``AutoNumber``, add ``*args`` to the signature:: - - >>> class AutoNumber(Enum): - ... def __new__(cls, *args): # this is the only change from above - ... value = len(cls.__members__) + 1 - ... obj = object.__new__(cls) - ... obj._value_ = value - ... return obj - ... - -Then when you inherit from ``AutoNumber`` you can write your own ``__init__`` -to handle any extra arguments:: - - >>> class Swatch(AutoNumber): - ... def __init__(self, pantone='unknown'): - ... self.pantone = pantone - ... AUBURN = '3497' - ... SEA_GREEN = '1246' - ... BLEACHED_CORAL = () # New color, no Pantone code yet! - ... - >>> Swatch.SEA_GREEN - - >>> Swatch.SEA_GREEN.pantone - '1246' - >>> Swatch.BLEACHED_CORAL.pantone - 'unknown' - -.. note:: - - The :meth:`__new__` method, if defined, is used during creation of the Enum - members; it is then replaced by Enum's :meth:`__new__` which is used after - class creation for lookup of existing members. - - -OrderedEnum -^^^^^^^^^^^ - -An ordered enumeration that is not based on :class:`IntEnum` and so maintains -the normal :class:`Enum` invariants (such as not being comparable to other -enumerations):: - - >>> class OrderedEnum(Enum): - ... def __ge__(self, other): - ... if self.__class__ is other.__class__: - ... return self.value >= other.value - ... return NotImplemented - ... def __gt__(self, other): - ... if self.__class__ is other.__class__: - ... return self.value > other.value - ... return NotImplemented - ... def __le__(self, other): - ... if self.__class__ is other.__class__: - ... return self.value <= other.value - ... return NotImplemented - ... def __lt__(self, other): - ... if self.__class__ is other.__class__: - ... return self.value < other.value - ... return NotImplemented - ... - >>> class Grade(OrderedEnum): - ... A = 5 - ... B = 4 - ... C = 3 - ... D = 2 - ... F = 1 - ... - >>> Grade.C < Grade.A - True - - -DuplicateFreeEnum -^^^^^^^^^^^^^^^^^ - -Raises an error if a duplicate member name is found instead of creating an -alias:: - - >>> class DuplicateFreeEnum(Enum): - ... def __init__(self, *args): - ... cls = self.__class__ - ... if any(self.value == e.value for e in cls): - ... a = self.name - ... e = cls(self.value).name - ... raise ValueError( - ... "aliases not allowed in DuplicateFreeEnum: %r --> %r" - ... % (a, e)) - ... - >>> class Color(DuplicateFreeEnum): - ... RED = 1 - ... GREEN = 2 - ... BLUE = 3 - ... GRENE = 2 - ... - Traceback (most recent call last): - ... - ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN' - -.. note:: - - This is a useful example for subclassing Enum to add or change other - behaviors as well as disallowing aliases. If the only desired change is - disallowing aliases, the :func:`unique` decorator can be used instead. - - -Planet -^^^^^^ - -If :meth:`__new__` or :meth:`__init__` is defined the value of the enum member -will be passed to those methods:: - - >>> class Planet(Enum): - ... MERCURY = (3.303e+23, 2.4397e6) - ... VENUS = (4.869e+24, 6.0518e6) - ... EARTH = (5.976e+24, 6.37814e6) - ... MARS = (6.421e+23, 3.3972e6) - ... JUPITER = (1.9e+27, 7.1492e7) - ... SATURN = (5.688e+26, 6.0268e7) - ... URANUS = (8.686e+25, 2.5559e7) - ... NEPTUNE = (1.024e+26, 2.4746e7) - ... def __init__(self, mass, radius): - ... self.mass = mass # in kilograms - ... self.radius = radius # in meters - ... @property - ... def surface_gravity(self): - ... # universal gravitational constant (m3 kg-1 s-2) - ... G = 6.67300E-11 - ... return G * self.mass / (self.radius * self.radius) - ... - >>> Planet.EARTH.value - (5.976e+24, 6378140.0) - >>> Planet.EARTH.surface_gravity - 9.802652743337129 - -.. _enum-time-period: - -TimePeriod -^^^^^^^^^^ - -An example to show the :attr:`_ignore_` attribute in use:: - - >>> from datetime import timedelta - >>> class Period(timedelta, Enum): - ... "different lengths of time" - ... _ignore_ = 'Period i' - ... Period = vars() - ... for i in range(367): - ... Period['day_%d' % i] = i - ... - >>> list(Period)[:2] - [Period.day_0, Period.day_1] - >>> list(Period)[-2:] - [Period.day_365, Period.day_366] - - -Conforming input to Flag -^^^^^^^^^^^^^^^^^^^^^^^^ - -Creating a :class:`Flag` enum that is more resilient out-of-bounds results to -mathematical operations, you can use the :attr:`FlagBoundary.CONFORM` setting:: - - >>> from enum import Flag, CONFORM, auto - >>> class Weekday(Flag, boundary=CONFORM): - ... MONDAY = auto() - ... TUESDAY = auto() - ... WEDNESDAY = auto() - ... THURSDAY = auto() - ... FRIDAY = auto() - ... SATURDAY = auto() - ... SUNDAY = auto() - >>> today = Weekday.TUESDAY - >>> Weekday(today + 22) # what day is three weeks from tomorrow? - >>> Weekday.WEDNESDAY - - -.. _enumtype-examples: - -Subclassing EnumType --------------------- - -While most enum needs can be met by customizing :class:`Enum` subclasses, -either with class decorators or custom functions, :class:`EnumType` can be -subclassed to provide a different Enum experience. - diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst index 74e861480d2ff8..c7f8bc8f17f43b 100644 --- a/Doc/howto/functional.rst +++ b/Doc/howto/functional.rst @@ -65,11 +65,10 @@ output must only depend on its input. Some languages are very strict about purity and don't even have assignment statements such as ``a=3`` or ``c = a + b``, but it's difficult to avoid all -side effects. Printing to the screen or writing to a disk file are side -effects, for example. For example, in Python a call to the :func:`print` or -:func:`time.sleep` function both return no useful value; they're only called for -their side effects of sending some text to the screen or pausing execution for a -second. +side effects, such as printing to the screen or writing to a disk file. Another +example is a call to the :func:`print` or :func:`time.sleep` function, neither +of which returns a useful value. Both are called only for their side effects +of sending some text to the screen or pausing execution for a second. Python programs written in functional style usually won't go to the extreme of avoiding all I/O or all assignments; instead, they'll provide a diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index eae8f143ee206f..01a78a556591c9 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -17,7 +17,6 @@ Currently, the HOWTOs are: cporting.rst curses.rst descriptor.rst - enum.rst functional.rst logging.rst logging-cookbook.rst diff --git a/Doc/howto/ipaddress.rst b/Doc/howto/ipaddress.rst index 452e3671060a5e..e852db98156fac 100644 --- a/Doc/howto/ipaddress.rst +++ b/Doc/howto/ipaddress.rst @@ -32,7 +32,7 @@ A Note on IP Versions --------------------- For readers that aren't particularly familiar with IP addressing, it's -important to know that the Internet Protocol is currently in the process +important to know that the Internet Protocol (IP) is currently in the process of moving from version 4 of the protocol to version 6. This transition is occurring largely because version 4 of the protocol doesn't provide enough addresses to handle the needs of the whole world, especially given the diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 5777a4c5031f85..f82150a4f2e020 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -332,7 +332,7 @@ Dealing with handlers that block .. currentmodule:: logging.handlers Sometimes you have to get your logging handlers to do their work without -blocking the thread you're logging from. This is common in Web applications, +blocking the thread you're logging from. This is common in web applications, though of course it also occurs in other scenarios. A common culprit which demonstrates sluggish behaviour is the @@ -541,6 +541,17 @@ alternative there, as well as adapting the above script to use your alternative serialization. +Running a logging socket listener in production +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To run a logging listener in production, you may need to use a process-management tool +such as `Supervisor `_. `Here +`_ is a Gist which +provides the bare-bones files to run the above functionality using Supervisor: you +will need to change the `/path/to/` parts in the Gist to reflect the actual paths you +want to use. + + .. _context-info: Adding contextual information to your logging output @@ -982,6 +993,17 @@ to this (remembering to first import :mod:`concurrent.futures`):: for i in range(10): executor.submit(worker_process, queue, worker_configurer) +Deploying Web applications using Gunicorn and uWSGI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When deploying Web applications using `Gunicorn `_ or `uWSGI +`_ (or similar), multiple worker +processes are created to handle client requests. In such environments, avoid creating +file-based handlers directly in your web application. Instead, use a +:class:`SocketHandler` to log from the web application to a listener in a separate +process. This can be set up using a process management tool such as Supervisor - see +`Running a logging socket listener in production`_ for more details. + Using file rotation ------------------- @@ -2979,3 +3001,82 @@ refer to the comments in the code snippet for more detailed information. if __name__=='__main__': main() + + +.. patterns-to-avoid: + +Patterns to avoid +----------------- + +Although the preceding sections have described ways of doing things you might +need to do or deal with, it is worth mentioning some usage patterns which are +*unhelpful*, and which should therefore be avoided in most cases. The following +sections are in no particular order. + + +Opening the same log file multiple times +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On Windows, you will generally not be able to open the same file multiple times +as this will lead to a "file is in use by another process" error. However, on +POSIX platforms you'll not get any errors if you open the same file multiple +times. This could be done accidentally, for example by: + +* Adding a file handler more than once which references the same file (e.g. by + a copy/paste/forget-to-change error). + +* Opening two files that look different, as they have different names, but are + the same because one is a symbolic link to the other. + +* Forking a process, following which both parent and child have a reference to + the same file. This might be through use of the :mod:`multiprocessing` module, + for example. + +Opening a file multiple times might *appear* to work most of the time, but can +lead to a number of problems in practice: + +* Logging output can be garbled because multiple threads or processes try to + write to the same file. Although logging guards against concurrent use of the + same handler instance by multiple threads, there is no such protection if + concurrent writes are attempted by two different threads using two different + handler instances which happen to point to the same file. + +* An attempt to delete a file (e.g. during file rotation) silently fails, + because there is another reference pointing to it. This can lead to confusion + and wasted debugging time - log entries end up in unexpected places, or are + lost altogether. + +Use the techniques outlined in :ref:`multiple-processes` to circumvent such +issues. + +Using loggers as attributes in a class or passing them as parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While there might be unusual cases where you'll need to do this, in general +there is no point because loggers are singletons. Code can always access a +given logger instance by name using ``logging.getLogger(name)``, so passing +instances around and holding them as instance attributes is pointless. Note +that in other languages such as Java and C#, loggers are often static class +attributes. However, this pattern doesn't make sense in Python, where the +module (and not the class) is the unit of software decomposition. + + +Adding handlers other than :class:`NullHandler` to a logger in a library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Configuring logging by adding handlers, formatters and filters is the +responsibility of the application developer, not the library developer. If you +are maintaining a library, ensure that you don't add handlers to any of your +loggers other than a :class:`~logging.NullHandler` instance. + + +Creating a lot of loggers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Loggers are singletons that are never freed during a script execution, and so +creating lots of loggers will use up memory which can't then be freed. Rather +than create a logger per e.g. file processed or network connection made, use +the :ref:`existing mechanisms ` for passing contextual +information into your logs and restrict the loggers created to those describing +areas within your application (generally modules, but occasionally slightly +more fine-grained than that). diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 1543823c104c28..abcc34287e3d29 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -20,8 +20,8 @@ Porting Python 2 Code to Python 3 came into existence, you can read Nick Coghlan's `Python 3 Q & A`_ or Brett Cannon's `Why Python 3 exists`_. - For help with porting, you can email the python-porting_ mailing list with - questions. + + For help with porting, you can view the archived python-porting_ mailing list. The Short Explanation ===================== @@ -446,7 +446,7 @@ to make sure everything functions as expected in both versions of Python. .. _pytype: https://github.com/google/pytype .. _python-future: http://python-future.org/ -.. _python-porting: https://mail.python.org/mailman/listinfo/python-porting +.. _python-porting: https://mail.python.org/pipermail/python-porting/ .. _six: https://pypi.org/project/six .. _tox: https://pypi.org/project/tox .. _trove classifier: https://pypi.org/classifiers diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst index d6ed128e073fd6..e58f78a7cb0245 100644 --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -45,7 +45,7 @@ likely to be other forms of IPC that are faster, but for cross-platform communication, sockets are about the only game in town. They were invented in Berkeley as part of the BSD flavor of Unix. They spread -like wildfire with the Internet. With good reason --- the combination of sockets +like wildfire with the internet. With good reason --- the combination of sockets with INET makes talking to arbitrary machines around the world unbelievably easy (at least compared to other schemes). diff --git a/Doc/includes/sqlite3/countcursors.py b/Doc/includes/sqlite3/countcursors.py deleted file mode 100644 index 112f47703a2ff4..00000000000000 --- a/Doc/includes/sqlite3/countcursors.py +++ /dev/null @@ -1,17 +0,0 @@ -import sqlite3 - -class CountCursorsConnection(sqlite3.Connection): - def __init__(self, *args, **kwargs): - sqlite3.Connection.__init__(self, *args, **kwargs) - self.numcursors = 0 - - def cursor(self, *args, **kwargs): - self.numcursors += 1 - return sqlite3.Connection.cursor(self, *args, **kwargs) - -con = sqlite3.connect(":memory:", factory=CountCursorsConnection) -cur1 = con.cursor() -cur2 = con.cursor() -print(con.numcursors) - -con.close() diff --git a/Doc/includes/sqlite3/createdb.py b/Doc/includes/sqlite3/createdb.py deleted file mode 100644 index ee2950bdf81646..00000000000000 --- a/Doc/includes/sqlite3/createdb.py +++ /dev/null @@ -1,28 +0,0 @@ -# Not referenced from the documentation, but builds the database file the other -# code snippets expect. - -import sqlite3 -import os - -DB_FILE = "mydb" - -if os.path.exists(DB_FILE): - os.remove(DB_FILE) - -con = sqlite3.connect(DB_FILE) -cur = con.cursor() -cur.execute(""" - create table people - ( - name_last varchar(20), - age integer - ) - """) - -cur.execute("insert into people (name_last, age) values ('Yeltsin', 72)") -cur.execute("insert into people (name_last, age) values ('Putin', 51)") - -con.commit() - -cur.close() -con.close() diff --git a/Doc/includes/sqlite3/ctx_manager.py b/Doc/includes/sqlite3/ctx_manager.py index 6db77d45046e1f..2e1175ef44c641 100644 --- a/Doc/includes/sqlite3/ctx_manager.py +++ b/Doc/includes/sqlite3/ctx_manager.py @@ -1,19 +1,19 @@ import sqlite3 con = sqlite3.connect(":memory:") -con.execute("create table person (id integer primary key, firstname varchar unique)") +con.execute("create table lang (id integer primary key, name varchar unique)") # Successful, con.commit() is called automatically afterwards with con: - con.execute("insert into person(firstname) values (?)", ("Joe",)) + con.execute("insert into lang(name) values (?)", ("Python",)) # con.rollback() is called after the with block finishes with an exception, the # exception is still raised and must be caught try: with con: - con.execute("insert into person(firstname) values (?)", ("Joe",)) + con.execute("insert into lang(name) values (?)", ("Python",)) except sqlite3.IntegrityError: - print("couldn't add Joe twice") + print("couldn't add Python twice") # Connection object used as context manager only commits or rollbacks transactions, # so the connection object should be closed manually diff --git a/Doc/includes/sqlite3/execsql_fetchonerow.py b/Doc/includes/sqlite3/execsql_fetchonerow.py deleted file mode 100644 index 115bcb50c7c754..00000000000000 --- a/Doc/includes/sqlite3/execsql_fetchonerow.py +++ /dev/null @@ -1,19 +0,0 @@ -import sqlite3 - -con = sqlite3.connect("mydb") - -cur = con.cursor() -SELECT = "select name_last, age from people order by age, name_last" - -# 1. Iterate over the rows available from the cursor, unpacking the -# resulting sequences to yield their elements (name_last, age): -cur.execute(SELECT) -for (name_last, age) in cur: - print('%s is %d years old.' % (name_last, age)) - -# 2. Equivalently: -cur.execute(SELECT) -for row in cur: - print('%s is %d years old.' % (row[0], row[1])) - -con.close() diff --git a/Doc/includes/sqlite3/execsql_printall_1.py b/Doc/includes/sqlite3/execsql_printall_1.py deleted file mode 100644 index 19306e6e3ca7d1..00000000000000 --- a/Doc/includes/sqlite3/execsql_printall_1.py +++ /dev/null @@ -1,15 +0,0 @@ -import sqlite3 - -# Create a connection to the database file "mydb": -con = sqlite3.connect("mydb") - -# Get a Cursor object that operates in the context of Connection con: -cur = con.cursor() - -# Execute the SELECT statement: -cur.execute("select * from people order by age") - -# Retrieve all rows as a sequence and print that sequence: -print(cur.fetchall()) - -con.close() diff --git a/Doc/includes/sqlite3/execute_1.py b/Doc/includes/sqlite3/execute_1.py index 42aad4d5839f06..ee0000e2b94a32 100644 --- a/Doc/includes/sqlite3/execute_1.py +++ b/Doc/includes/sqlite3/execute_1.py @@ -2,22 +2,21 @@ con = sqlite3.connect(":memory:") cur = con.cursor() -cur.execute("create table lang (lang_name, lang_age)") +cur.execute("create table lang (name, first_appeared)") # This is the qmark style: -cur.execute("insert into lang values (?, ?)", ("C", 49)) +cur.execute("insert into lang values (?, ?)", ("C", 1972)) # The qmark style used with executemany(): lang_list = [ - ("Fortran", 64), - ("Python", 30), - ("Go", 11), + ("Fortran", 1957), + ("Python", 1991), + ("Go", 2009), ] cur.executemany("insert into lang values (?, ?)", lang_list) # And this is the named style: -cur.execute("select * from lang where lang_name=:name and lang_age=:age", - {"name": "C", "age": 49}) +cur.execute("select * from lang where first_appeared=:year", {"year": 1972}) print(cur.fetchall()) con.close() diff --git a/Doc/includes/sqlite3/insert_more_people.py b/Doc/includes/sqlite3/insert_more_people.py deleted file mode 100644 index 10cf937243f6da..00000000000000 --- a/Doc/includes/sqlite3/insert_more_people.py +++ /dev/null @@ -1,18 +0,0 @@ -import sqlite3 - -con = sqlite3.connect("mydb") - -cur = con.cursor() - -newPeople = ( - ('Lebed' , 53), - ('Zhirinovsky' , 57), - ) - -for person in newPeople: - cur.execute("insert into people (name_last, age) values (?, ?)", person) - -# The changes will not be saved unless the transaction is committed explicitly: -con.commit() - -con.close() diff --git a/Doc/includes/sqlite3/parse_colnames.py b/Doc/includes/sqlite3/parse_colnames.py deleted file mode 100644 index 5f01dbfe1cb524..00000000000000 --- a/Doc/includes/sqlite3/parse_colnames.py +++ /dev/null @@ -1,10 +0,0 @@ -import sqlite3 -import datetime - -con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) -cur = con.cursor() -cur.execute('select ? as "x [timestamp]"', (datetime.datetime.now(),)) -dt = cur.fetchone()[0] -print(dt, type(dt)) - -con.close() diff --git a/Doc/includes/sqlite3/shared_cache.py b/Doc/includes/sqlite3/shared_cache.py deleted file mode 100644 index 30e71c935ff62e..00000000000000 --- a/Doc/includes/sqlite3/shared_cache.py +++ /dev/null @@ -1,6 +0,0 @@ -import sqlite3 - -# The shared cache is only available in SQLite versions 3.3.3 or later -# See the SQLite documentation for details. - -sqlite3.enable_shared_cache(True) diff --git a/Doc/includes/sqlite3/shortcut_methods.py b/Doc/includes/sqlite3/shortcut_methods.py index 98a39411495cba..48ea6fad15a898 100644 --- a/Doc/includes/sqlite3/shortcut_methods.py +++ b/Doc/includes/sqlite3/shortcut_methods.py @@ -1,23 +1,23 @@ import sqlite3 -persons = [ - ("Hugo", "Boss"), - ("Calvin", "Klein") - ] +langs = [ + ("C++", 1985), + ("Objective-C", 1984), +] con = sqlite3.connect(":memory:") # Create the table -con.execute("create table person(firstname, lastname)") +con.execute("create table lang(name, first_appeared)") # Fill the table -con.executemany("insert into person(firstname, lastname) values (?, ?)", persons) +con.executemany("insert into lang(name, first_appeared) values (?, ?)", langs) # Print the table contents -for row in con.execute("select firstname, lastname from person"): +for row in con.execute("select name, first_appeared from lang"): print(row) -print("I just deleted", con.execute("delete from person").rowcount, "rows") +print("I just deleted", con.execute("delete from lang").rowcount, "rows") # close is not a shortcut method and it's not called automatically, # so the connection object should be closed manually diff --git a/Doc/includes/sqlite3/simple_tableprinter.py b/Doc/includes/sqlite3/simple_tableprinter.py deleted file mode 100644 index 148a1707f948bc..00000000000000 --- a/Doc/includes/sqlite3/simple_tableprinter.py +++ /dev/null @@ -1,28 +0,0 @@ -import sqlite3 - -FIELD_MAX_WIDTH = 20 -TABLE_NAME = 'people' -SELECT = 'select * from %s order by age, name_last' % TABLE_NAME - -con = sqlite3.connect("mydb") - -cur = con.cursor() -cur.execute(SELECT) - -# Print a header. -for fieldDesc in cur.description: - print(fieldDesc[0].ljust(FIELD_MAX_WIDTH), end=' ') -print() # Finish the header with a newline. -print('-' * 78) - -# For each row, print the value of each field left-justified within -# the maximum possible width of that field. -fieldIndices = range(len(cur.description)) -for row in cur: - for fieldIndex in fieldIndices: - fieldValue = str(row[fieldIndex]) - print(fieldValue.ljust(FIELD_MAX_WIDTH), end=' ') - - print() # Finish the row with a newline. - -con.close() diff --git a/Doc/includes/sqlite3/text_factory.py b/Doc/includes/sqlite3/text_factory.py index a857a155cdd4ff..c0d87cd559118c 100644 --- a/Doc/includes/sqlite3/text_factory.py +++ b/Doc/includes/sqlite3/text_factory.py @@ -3,9 +3,9 @@ con = sqlite3.connect(":memory:") cur = con.cursor() -AUSTRIA = "\xd6sterreich" +AUSTRIA = "Österreich" -# by default, rows are returned as Unicode +# by default, rows are returned as str cur.execute("select ?", (AUSTRIA,)) row = cur.fetchone() assert row[0] == AUSTRIA diff --git a/Doc/install/index.rst b/Doc/install/index.rst index 48c6e76a682a46..7f7be117009887 100644 --- a/Doc/install/index.rst +++ b/Doc/install/index.rst @@ -206,7 +206,7 @@ directory. If you don't choose an installation directory---i.e., if you just run ``setup.py install``\ ---then the :command:`install` command installs to the standard location for third-party Python modules. This location varies by platform and -by how you built/installed Python itself. On Unix (and Mac OS X, which is also +by how you built/installed Python itself. On Unix (and macOS, which is also Unix-based), it also depends on whether the module distribution being installed is pure Python or contains extensions ("non-pure"): @@ -236,7 +236,7 @@ Notes: :file:`{prefix}` and :file:`{exec-prefix}` stand for the directories that Python is installed to, and where it finds its libraries at run-time. They are always -the same under Windows, and very often the same under Unix and Mac OS X. You +the same under Windows, and very often the same under Unix and macOS. You can find out what your Python installation uses for :file:`{prefix}` and :file:`{exec-prefix}` by running Python in interactive mode and typing a few simple commands. Under Unix, just type ``python`` at the shell prompt. Under @@ -312,7 +312,7 @@ install into it. It is enabled with a simple option:: Files will be installed into subdirectories of :data:`site.USER_BASE` (written as :file:`{userbase}` hereafter). This scheme installs pure Python modules and extension modules in the same location (also known as :data:`site.USER_SITE`). -Here are the values for UNIX, including Mac OS X: +Here are the values for UNIX, including macOS: =============== =========================================================== Type of file Installation directory @@ -735,7 +735,7 @@ Location and names of config files ---------------------------------- The names and locations of the configuration files vary slightly across -platforms. On Unix and Mac OS X, the three configuration files (in the order +platforms. On Unix and macOS, the three configuration files (in the order they are processed) are: +--------------+----------------------------------------------------------+-------+ @@ -953,7 +953,7 @@ Borland/CodeGear C++ This subsection describes the necessary steps to use Distutils with the Borland C++ compiler version 5.5. First you have to know that Borland's object file format (OMF) is different from the format used by the Python version you can -download from the Python or ActiveState Web site. (Python is built with +download from the Python or ActiveState web site. (Python is built with Microsoft Visual C++, which uses COFF as the object file format.) For this reason you have to convert Python's library :file:`python25.lib` into the Borland format. You can do this as follows: diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 31e9b0bde07244..4bacc7ba0c2cf2 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -44,7 +44,7 @@ Key terms ``venv``. It allows virtual environments to be used on versions of Python prior to 3.4, which either don't provide ``venv`` at all, or aren't able to automatically install ``pip`` into created environments. -* The `Python Packaging Index `__ is a public +* The `Python Package Index `__ is a public repository of open source licensed packages made available for use by other Python users. * the `Python Packaging Authority @@ -78,13 +78,13 @@ The standard packaging tools are all designed to be used from the command line. The following command will install the latest version of a module and its -dependencies from the Python Packaging Index:: +dependencies from the Python Package Index:: python -m pip install SomePackage .. note:: - For POSIX users (including Mac OS X and Linux users), the examples in + For POSIX users (including macOS and Linux users), the examples in this guide assume the use of a :term:`virtual environment`. For Windows users, the examples in this guide assume that the option to @@ -163,7 +163,7 @@ rather than attempting to install them with ``pip``. ... work with multiple versions of Python installed in parallel? ---------------------------------------------------------------- -On Linux, Mac OS X, and other POSIX systems, use the versioned Python commands +On Linux, macOS, and other POSIX systems, use the versioned Python commands in combination with the ``-m`` switch to run the appropriate copy of ``pip``:: @@ -225,8 +225,8 @@ users being expected to compile extension modules from source as part of the installation process. With the introduction of support for the binary ``wheel`` format, and the -ability to publish wheels for at least Windows and Mac OS X through the -Python Packaging Index, this problem is expected to diminish over time, +ability to publish wheels for at least Windows and macOS through the +Python Package Index, this problem is expected to diminish over time, as users are more regularly able to install pre-built extensions rather than needing to build them themselves. diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst index 1d7bd262872905..5e1b010e9bb5f2 100644 --- a/Doc/library/2to3.rst +++ b/Doc/library/2to3.rst @@ -333,7 +333,8 @@ and off individually. They are described here in more detail. .. 2to3fixer:: nonzero - Renames :meth:`__nonzero__` to :meth:`~object.__bool__`. + Renames definitions of methods called :meth:`__nonzero__` + to :meth:`~object.__bool__`. .. 2to3fixer:: numliterals @@ -464,12 +465,15 @@ and off individually. They are described here in more detail. -------------- -.. deprecated:: 3.10 - Python 3.9 will switch to a PEG parser (see :pep:`617`), and Python 3.10 may - include new language syntax that is not parsable by lib2to3's LL(1) parser. - The ``lib2to3`` module may be removed from the standard library in a future - Python version. Consider third-party alternatives such as `LibCST`_ or - `parso`_. +.. deprecated-removed:: 3.11 3.13 + Python 3.9 switched to a PEG parser (see :pep:`617`) while lib2to3 is + using a less flexible LL(1) parser. Python 3.10 includes new language + syntax that is not parsable by lib2to3's LL(1) parser (see :pep:`634`). + The ``lib2to3`` module was marked pending for deprecation in Python 3.9 + (raising :exc:`PendingDeprecationWarning` on import) and fully deprecated + in Python 3.11 (raising :exc:`DeprecationWarning`). + It will be removed from the standard library in Python 3.13. + Consider third-party alternatives such as `LibCST`_ or `parso`_. .. note:: diff --git a/Doc/library/__main__.rst b/Doc/library/__main__.rst index a64faf1bbe3c84..c5f36a7fcf0775 100644 --- a/Doc/library/__main__.rst +++ b/Doc/library/__main__.rst @@ -1,25 +1,368 @@ - -:mod:`__main__` --- Top-level script environment -================================================ +:mod:`__main__` --- Top-level code environment +============================================== .. module:: __main__ - :synopsis: The environment where the top-level script is run. + :synopsis: The environment where top-level code is run. Covers command-line + interfaces, import-time behavior, and ``__name__ == '__main__'``. -------------- -``'__main__'`` is the name of the scope in which top-level code executes. -A module's __name__ is set equal to ``'__main__'`` when read from -standard input, a script, or from an interactive prompt. +In Python, the special name ``__main__`` is used for two important constructs: + +1. the name of the top-level environment of the program, which can be + checked using the ``__name__ == '__main__'`` expression; and +2. the ``__main__.py`` file in Python packages. + +Both of these mechanisms are related to Python modules; how users interact with +them and how they interact with each other. They are explained in detail +below. If you're new to Python modules, see the tutorial section +:ref:`tut-modules` for an introduction. + + +.. _name_equals_main: + +``__name__ == '__main__'`` +--------------------------- + +When a Python module or package is imported, ``__name__`` is set to the +module's name. Usually, this is the name of the Python file itself without the +``.py`` extension:: + + >>> import configparser + >>> configparser.__name__ + 'configparser' + +If the file is part of a package, ``__name__`` will also include the parent +package's path:: + + >>> from concurrent.futures import process + >>> process.__name__ + 'concurrent.futures.process' + +However, if the module is executed in the top-level code environment, +its ``__name__`` is set to the string ``'__main__'``. + +What is the "top-level code environment"? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``__main__`` is the name of the environment where top-level code is run. +"Top-level code" is the first user-specified Python module that starts running. +It's "top-level" because it imports all other modules that the program needs. +Sometimes "top-level code" is called an *entry point* to the application. + +The top-level code environment can be: + +* the scope of an interactive prompt:: + + >>> __name__ + '__main__' + +* the Python module passed to the Python interpreter as a file argument: + + .. code-block:: shell-session + + $ python3 helloworld.py + Hello, world! + +* the Python module or package passed to the Python interpreter with the + :option:`-m` argument: + + .. code-block:: shell-session + + $ python3 -m tarfile + usage: tarfile.py [-h] [-v] (...) + +* Python code read by the Python interpreter from standard input: + + .. code-block:: shell-session + + $ echo "import this" | python3 + The Zen of Python, by Tim Peters + + Beautiful is better than ugly. + Explicit is better than implicit. + ... + +* Python code passed to the Python interpreter with the :option:`-c` argument: + + .. code-block:: shell-session + + $ python3 -c "import this" + The Zen of Python, by Tim Peters + + Beautiful is better than ugly. + Explicit is better than implicit. + ... + +In each of these situations, the top-level module's ``__name__`` is set to +``'__main__'``. + +As a result, a module can discover whether or not it is running in the +top-level environment by checking its own ``__name__``, which allows a common +idiom for conditionally executing code when the module is not initialized from +an import statement:: + + if __name__ == '__main__': + # Execute when the module is not initialized from an import statement. + ... + +.. seealso:: + + For a more detailed look at how ``__name__`` is set in all situations, see + the tutorial section :ref:`tut-modules`. + + +Idiomatic Usage +^^^^^^^^^^^^^^^ + +Some modules contain code that is intended for script use only, like parsing +command-line arguments or fetching data from standard input. If a module +like this was imported from a different module, for example to unit test +it, the script code would unintentionally execute as well. + +This is where using the ``if __name__ == '__main__'`` code block comes in +handy. Code within this block won't run unless the module is executed in the +top-level environment. + +Putting as few statements as possible in the block below ``if __name___ == +'__main__'`` can improve code clarity and correctness. Most often, a function +named ``main`` encapsulates the program's primary behavior:: + + # echo.py + + import shlex + import sys + + def echo(phrase: str) -> None: + """A dummy wrapper around print.""" + # for demonstration purposes, you can imagine that there is some + # valuable and reusable logic inside this function + print(phrase) + + def main() -> int: + """Echo the input arguments to standard output""" + phrase = shlex.join(sys.argv) + echo(phrase) + return 0 + + if __name__ == '__main__': + sys.exit(main()) # next section explains the use of sys.exit + +Note that if the module didn't encapsulate code inside the ``main`` function +but instead put it directly within the ``if __name__ == '__main__'`` block, +the ``phrase`` variable would be global to the entire module. This is +error-prone as other functions within the module could be unintentionally using +the global variable instead of a local name. A ``main`` function solves this +problem. + +Using a ``main`` function has the added benefit of the ``echo`` function itself +being isolated and importable elsewhere. When ``echo.py`` is imported, the +``echo`` and ``main`` functions will be defined, but neither of them will be +called, because ``__name__ != '__main__'``. + + +Packaging Considerations +^^^^^^^^^^^^^^^^^^^^^^^^ + +``main`` functions are often used to create command-line tools by specifying +them as entry points for console scripts. When this is done, +`pip `_ inserts the function call into a template script, +where the return value of ``main`` is passed into :func:`sys.exit`. +For example:: + + sys.exit(main()) + +Since the call to ``main`` is wrapped in :func:`sys.exit`, the expectation is +that your function will return some value acceptable as an input to +:func:`sys.exit`; typically, an integer or ``None`` (which is implicitly +returned if your function does not have a return statement). + +By proactively following this convention ourselves, our module will have the +same behavior when run directly (i.e. ``python3 echo.py``) as it will have if +we later package it as a console script entry-point in a pip-installable +package. + +In particular, be careful about returning strings from your ``main`` function. +:func:`sys.exit` will interpret a string argument as a failure message, so +your program will have an exit code of ``1``, indicating failure, and the +string will be written to :data:`sys.stderr`. The ``echo.py`` example from +earlier exemplifies using the ``sys.exit(main())`` convention. + +.. seealso:: + + `Python Packaging User Guide `_ + contains a collection of tutorials and references on how to distribute and + install Python packages with modern tools. + + +``__main__.py`` in Python Packages +---------------------------------- + +If you are not familiar with Python packages, see section :ref:`tut-packages` +of the tutorial. Most commonly, the ``__main__.py`` file is used to provide +a command-line interface for a package. Consider the following hypothetical +package, "bandclass": + +.. code-block:: text + + bandclass + ├── __init__.py + ├── __main__.py + └── student.py + +``__main__.py`` will be executed when the package itself is invoked +directly from the command line using the :option:`-m` flag. For example: + +.. code-block:: shell-session + + $ python3 -m bandclass + +This command will cause ``__main__.py`` to run. How you utilize this mechanism +will depend on the nature of the package you are writing, but in this +hypothetical case, it might make sense to allow the teacher to search for +students:: + + # bandclass/__main__.py + + import sys + from .student import search_students + + student_name = sys.argv[2] if len(sys.argv) >= 2 else '' + print(f'Found student: {search_students(student_name)}') + +Note that ``from .student import search_students`` is an example of a relative +import. This import style can be used when referencing modules within a +package. For more details, see :ref:`intra-package-references` in the +:ref:`tut-modules` section of the tutorial. + +Idiomatic Usage +^^^^^^^^^^^^^^^ + +The contents of ``__main__.py`` typically isn't fenced with +``if __name__ == '__main__'`` blocks. Instead, those files are kept short, +functions to execute from other modules. Those other modules can then be +easily unit-tested and are properly reusable. + +If used, an ``if __name__ == '__main__'`` block will still work as expected +for a ``__main__.py`` file within a package, because its ``__name__`` +attribute will include the package's path if imported:: + + >>> import asyncio.__main__ + >>> asyncio.__main__.__name__ + 'asyncio.__main__' + +This won't work for ``__main__.py`` files in the root directory of a .zip file +though. Hence, for consistency, minimal ``__main__.py`` like the :mod:`venv` +one mentioned above are preferred. + +.. seealso:: + + See :mod:`venv` for an example of a package with a minimal ``__main__.py`` + in the standard library. It doesn't contain a ``if __name__ == '__main__'`` + block. You can invoke it with ``python3 -m venv [directory]``. + + See :mod:`runpy` for more details on the :option:`-m` flag to the + interpreter executable. + + See :mod:`zipapp` for how to run applications packaged as *.zip* files. In + this case Python looks for a ``__main__.py`` file in the root directory of + the archive. + + + +``import __main__`` +------------------- + +Regardless of which module a Python program was started with, other modules +running within that same program can import the top-level environment's scope +(:term:`namespace`) by importing the ``__main__`` module. This doesn't import +a ``__main__.py`` file but rather whichever module that received the special +name ``'__main__'``. + +Here is an example module that consumes the ``__main__`` namespace:: + + # namely.py + + import __main__ + + def did_user_define_their_name(): + return 'my_name' in dir(__main__) + + def print_user_name(): + if not did_user_define_their_name(): + raise ValueError('Define the variable `my_name`!') + + if '__file__' in dir(__main__): + print(__main__.my_name, "found in file", __main__.__file__) + else: + print(__main__.my_name) + +Example usage of this module could be as follows:: + + # start.py + + import sys + + from namely import print_user_name + + # my_name = "Dinsdale" + + def main(): + try: + print_user_name() + except ValueError as ve: + return str(ve) + + if __name__ == "__main__": + sys.exit(main()) + +Now, if we started our program, the result would look like this: + +.. code-block:: shell-session + + $ python3 start.py + Define the variable `my_name`! + +The exit code of the program would be 1, indicating an error. Uncommenting the +line with ``my_name = "Dinsdale"`` fixes the program and now it exits with +status code 0, indicating success: + +.. code-block:: shell-session + + $ python3 start.py + Dinsdale found in file /path/to/start.py + +Note that importing ``__main__`` doesn't cause any issues with unintentionally +running top-level code meant for script use which is put in the +``if __name__ == "__main__"`` block of the ``start`` module. Why does this work? + +Python inserts an empty ``__main__`` module in :attr:`sys.modules` at +interpreter startup, and populates it by running top-level code. In our example +this is the ``start`` module which runs line by line and imports ``namely``. +In turn, ``namely`` imports ``__main__`` (which is really ``start``). That's an +import cycle! Fortunately, since the partially populated ``__main__`` +module is present in :attr:`sys.modules`, Python passes that to ``namely``. +See :ref:`Special considerations for __main__ ` in the +import system's reference for details on how this works. + +The Python REPL is another example of a "top-level environment", so anything +defined in the REPL becomes part of the ``__main__`` scope:: -A module can discover whether or not it is running in the main scope by -checking its own ``__name__``, which allows a common idiom for conditionally -executing code in a module when it is run as a script or with ``python --m`` but not when it is imported:: + >>> import namely + >>> namely.did_user_define_their_name() + False + >>> namely.print_user_name() + Traceback (most recent call last): + ... + ValueError: Define the variable `my_name`! + >>> my_name = 'Jabberwocky' + >>> namely.did_user_define_their_name() + True + >>> namely.print_user_name() + Jabberwocky - if __name__ == "__main__": - # execute only if run as a script - main() +Note that in this case the ``__main__`` scope doesn't contain a ``__file__`` +attribute as it's interactive. -For a package, the same effect can be achieved by including a -``__main__.py`` module, the contents of which will be executed when the -module is run with ``-m``. +The ``__main__`` scope is used in the implementation of :mod:`pdb` and +:mod:`rlcompleter`. diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index b2eb9eff914c69..d853d2afbe372f 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -148,7 +148,8 @@ ArgumentParser objects as keyword arguments. Each parameter has its own more detailed description below, but in short they are: - * prog_ - The name of the program (default: ``sys.argv[0]``) + * prog_ - The name of the program (default: + ``os.path.basename(sys.argv[0])``) * usage_ - The string describing the program usage (default: generated from arguments added to parser) @@ -853,6 +854,8 @@ is available in ``argparse`` and adds support for boolean actions such as >>> parser.parse_args(['--no-foo']) Namespace(foo=False) +.. versionadded:: 3.9 + The recommended way to create a custom action is to extend :class:`Action`, overriding the ``__call__`` method and optionally the ``__init__`` and ``format_usage`` methods. @@ -1102,7 +1105,7 @@ Anything with more interesting error-handling or resource management should be done downstream after the arguments are parsed. For example, JSON or YAML conversions have complex error cases that require -better reporting than can be given by the ``type`` keyword. An +better reporting than can be given by the ``type`` keyword. A :exc:`~json.JSONDecodeError` would not be well formatted and a :exc:`FileNotFound` exception would not be handled at all. diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index c7074c40f280c6..e29b5e88d71d41 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -1266,7 +1266,7 @@ Pattern matching the pattern matches the subject. ``body`` contains a list of nodes to execute if the pattern matches and - the result of evaluating the guard expression is truthy. + the result of evaluating the guard expression is true. .. doctest:: @@ -1621,7 +1621,7 @@ Function and class definitions A function definition. * ``name`` is a raw string of the function name. - * ``args`` is a :class:`arguments` node. + * ``args`` is an :class:`arguments` node. * ``body`` is the list of nodes inside the function. * ``decorator_list`` is the list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last). @@ -1795,7 +1795,7 @@ Function and class definitions * ``bases`` is a list of nodes for explicitly specified base classes. * ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'. Other keywords will be passed to the metaclass, as per `PEP-3115 - `_. + `_. * ``starargs`` and ``kwargs`` are each a single node, as in a function call. starargs will be expanded to join the list of base classes, and kwargs will be passed to the metaclass. @@ -1917,6 +1917,19 @@ and classes for traversing abstract syntax trees: ``await`` as variable names. The lowest supported version is ``(3, 4)``; the highest is ``sys.version_info[0:2]``. + If source contains a null character ('\0'), :exc:`ValueError` is raised. + + .. warning:: + Note that successfully parsing source code into an AST object doesn't + guarantee that the source code provided is valid Python code that can + be executed as the compilation step can raise further :exc:`SyntaxError` + exceptions. For instance, the source ``return 42`` generates a valid + AST node for a return statement, but it cannot be compiled alone (it needs + to be inside a function node). + + In particular, :func:`ast.parse` won't do any scoping checks, which the + compilation step does. + .. warning:: It is possible to crash the Python interpreter with a sufficiently large/complex string due to stack depth limitations diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index ca91efec260db2..b1700c996928bf 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -55,7 +55,7 @@ an event loop: .. deprecated:: 3.10 Deprecation warning is emitted if there is no running event loop. - If future Python releases this function will be an alias of + In future Python releases, this function will be an alias of :func:`get_running_loop`. .. function:: set_event_loop(loop) @@ -64,7 +64,7 @@ an event loop: .. function:: new_event_loop() - Create a new event loop object. + Create and return a new event loop object. Note that the behaviour of :func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop` functions can be altered by @@ -216,6 +216,10 @@ Scheduling callbacks A thread-safe variant of :meth:`call_soon`. Must be used to schedule callbacks *from another thread*. + Raises :exc:`RuntimeError` if called on a loop that's been closed. + This can happen on a secondary thread when the main application is + shutting down. + See the :ref:`concurrency and multithreading ` section of the documentation. @@ -445,7 +449,7 @@ Opening network connections and *local_addr* should be specified. * *local_addr*, if given, is a ``(local_host, local_port)`` tuple used - to bind the socket to locally. The *local_host* and *local_port* + to bind the socket locally. The *local_host* and *local_port* are looked up using ``getaddrinfo()``, similarly to *host* and *port*. * *ssl_handshake_timeout* is (for a TLS connection) the time in seconds @@ -523,7 +527,7 @@ Opening network connections Other arguments: * *local_addr*, if given, is a ``(local_host, local_port)`` tuple used - to bind the socket to locally. The *local_host* and *local_port* + to bind the socket locally. The *local_host* and *local_port* are looked up using :meth:`getaddrinfo`. * *remote_addr*, if given, is a ``(remote_host, remote_port)`` tuple used @@ -627,6 +631,11 @@ Creating network servers assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6). + * The *port* parameter can be set to specify which port the server should + listen on. If ``0`` or ``None`` (the default), a random unused port will + be selected (note that if *host* resolves to multiple network interfaces, + a different random port will be selected for each interface). + * *family* can be set to either :data:`socket.AF_INET` or :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set, the *family* will be determined from host name @@ -1238,9 +1247,10 @@ async/await code consider using the high-level .. note:: - The default asyncio event loop on **Windows** does not support - subprocesses. See :ref:`Subprocess Support on Windows - ` for details. + On Windows, the default event loop :class:`ProactorEventLoop` supports + subprocesses, whereas :class:`SelectorEventLoop` does not. See + :ref:`Subprocess Support on Windows ` for + details. .. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \ stdin=subprocess.PIPE, stdout=subprocess.PIPE, \ diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index ef496a23f5cd4c..3496387c178af7 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -54,6 +54,9 @@ Future Functions See also the :func:`create_task` function which is the preferred way for creating new Tasks. + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index 9dbd3ab46a3f68..8b67f4b8957ef6 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -683,7 +683,7 @@ factories passed to the :meth:`loop.create_datagram_endpoint` method. Subprocess Protocols -------------------- -Datagram Protocol instances should be constructed by protocol +Subprocess Protocol instances should be constructed by protocol factories passed to the :meth:`loop.subprocess_exec` and :meth:`loop.subprocess_shell` methods. diff --git a/Doc/library/asyncio-queue.rst b/Doc/library/asyncio-queue.rst index 289ad1b014c356..e6f26bb959869f 100644 --- a/Doc/library/asyncio-queue.rst +++ b/Doc/library/asyncio-queue.rst @@ -105,6 +105,13 @@ Queue Raises :exc:`ValueError` if called more times than there were items placed in the queue. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + Priority Queue ============== diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index ad3c7442ad56cd..95a8e4649beede 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -70,6 +70,14 @@ and work with streams: The *ssl_handshake_timeout* parameter. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + + .. coroutinefunction:: start_server(client_connected_cb, host=None, \ port=None, *, limit=None, \ family=socket.AF_UNSPEC, \ @@ -100,6 +108,13 @@ and work with streams: The *ssl_handshake_timeout* and *start_serving* parameters. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. rubric:: Unix Sockets @@ -124,6 +139,13 @@ and work with streams: The *path* parameter can now be a :term:`path-like object` + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. coroutinefunction:: start_unix_server(client_connected_cb, path=None, \ *, limit=None, sock=None, backlog=100, ssl=None, \ @@ -145,6 +167,13 @@ and work with streams: The *path* parameter can now be a :term:`path-like object`. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + StreamReader ============ @@ -366,8 +395,8 @@ TCP echo server using the :func:`asyncio.start_server` function:: server = await asyncio.start_server( handle_echo, '127.0.0.1', 8888) - addr = server.sockets[0].getsockname() - print(f'Serving on {addr}') + addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets) + print(f'Serving on {addrs}') async with server: await server.serve_forever() diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst index ef4d9bcc434c9f..fd1f9c99578794 100644 --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -75,6 +75,13 @@ Creating Subprocesses See the documentation of :meth:`loop.subprocess_exec` for other parameters. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. coroutinefunction:: create_subprocess_shell(cmd, stdin=None, \ stdout=None, stderr=None, limit=None, **kwds) @@ -99,6 +106,13 @@ Creating Subprocesses escape whitespace and special shell characters in strings that are going to be used to construct shell commands. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. note:: Subprocesses are available for Windows if a :class:`ProactorEventLoop` is diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst index d12630afc6a326..88e523af0b8088 100644 --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -63,6 +63,12 @@ Lock finally: lock.release() + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This class has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. coroutinemethod:: acquire() Acquire the lock. @@ -105,6 +111,12 @@ Event :meth:`clear` method. The :meth:`~Event.wait` method blocks until the flag is set to *true*. The flag is set to *false* initially. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This class has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. _asyncio_example_sync_event: Example:: @@ -177,6 +189,12 @@ Condition ``None``. In the latter case a new Lock object is created automatically. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This class has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + The preferred way to use a Condition is an :keyword:`async with` statement:: @@ -273,6 +291,12 @@ Semaphore internal counter (``1`` by default). If the given value is less than ``0`` a :exc:`ValueError` is raised. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This class has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + The preferred way to use a Semaphore is an :keyword:`async with` statement:: @@ -325,6 +349,13 @@ BoundedSemaphore a :exc:`ValueError` in :meth:`~Semaphore.release` if it increases the internal counter above the initial *value*. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This class has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + --------- diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 3f54ecb08efc1f..1175b0537c0511 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -274,6 +274,11 @@ Creating Tasks task = asyncio.ensure_future(coro()) ... + .. important:: + + Save a reference to the result of this function, to avoid + a task disappearing mid execution. + .. versionadded:: 3.7 .. versionchanged:: 3.8 @@ -297,6 +302,12 @@ Sleeping tasks to run. This can be used by long-running functions to avoid blocking the event loop for the full duration of the function call. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. _asyncio_example_sleep: Example of coroutine displaying the current date every second @@ -317,6 +328,14 @@ Sleeping asyncio.run(display_date()) + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + + Running Tasks Concurrently ========================== @@ -349,6 +368,12 @@ Running Tasks Concurrently cancellation of one submitted Task/Future to cause other Tasks/Futures to be cancelled. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. _asyncio_example_gather: Example:: @@ -358,32 +383,35 @@ Running Tasks Concurrently async def factorial(name, number): f = 1 for i in range(2, number + 1): - print(f"Task {name}: Compute factorial({i})...") + print(f"Task {name}: Compute factorial({number}), currently i={i}...") await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") + return f async def main(): # Schedule three calls *concurrently*: - await asyncio.gather( + L = await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), ) + print(L) asyncio.run(main()) # Expected output: # - # Task A: Compute factorial(2)... - # Task B: Compute factorial(2)... - # Task C: Compute factorial(2)... + # Task A: Compute factorial(2), currently i=2... + # Task B: Compute factorial(3), currently i=2... + # Task C: Compute factorial(4), currently i=2... # Task A: factorial(2) = 2 - # Task B: Compute factorial(3)... - # Task C: Compute factorial(3)... + # Task B: Compute factorial(3), currently i=3... + # Task C: Compute factorial(4), currently i=3... # Task B: factorial(3) = 6 - # Task C: Compute factorial(4)... + # Task C: Compute factorial(4), currently i=4... # Task C: factorial(4) = 24 + # [2, 6, 24] .. note:: If *return_exceptions* is False, cancelling gather() after it @@ -397,6 +425,12 @@ Running Tasks Concurrently If the *gather* itself is cancelled, the cancellation is propagated regardless of *return_exceptions*. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. deprecated:: 3.10 Deprecation warning is emitted if no positional arguments are provided or not all positional arguments are Future-like objects @@ -439,6 +473,12 @@ Shielding From Cancellation except CancelledError: res = None + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. deprecated:: 3.10 Deprecation warning is emitted if *aw* is not Future-like object and there is no running event loop. @@ -470,6 +510,12 @@ Timeouts If the wait is cancelled, the future *aw* is also cancelled. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. _asyncio_example_waitfor: Example:: @@ -497,6 +543,12 @@ Timeouts for *aw* to be cancelled. Previously, it raised :exc:`asyncio.TimeoutError` immediately. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + Waiting Primitives ================== @@ -553,6 +605,12 @@ Waiting Primitives ``wait()`` directly is deprecated as it leads to :ref:`confusing behavior `. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. _asyncio_example_wait_coroutine: .. note:: @@ -580,6 +638,13 @@ Waiting Primitives if task in done: # Everything will work as expected now. + .. deprecated-removed:: 3.8 3.10 + + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. deprecated-removed:: 3.8 3.11 Passing coroutine objects to ``wait()`` directly is @@ -596,12 +661,24 @@ Waiting Primitives Raises :exc:`asyncio.TimeoutError` if the timeout occurs before all Futures are done. + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + Example:: for coro in as_completed(aws): earliest_result = await coro # ... + .. deprecated-removed:: 3.8 3.10 + The ``loop`` parameter. This function has been implicitly getting the + current running loop since 3.7. See + :ref:`What's New in 3.10's Removed section ` + for more information. + .. deprecated:: 3.10 Deprecation warning is emitted if not all awaitable objects in the *aws* iterable are Future-like objects and there is no running event loop. @@ -694,7 +771,7 @@ Scheduling From Other Threads try: result = future.result(timeout) - except asyncio.TimeoutError: + except concurrent.futures.TimeoutError: print('The coroutine took too long, cancelling the task...') future.cancel() except Exception as exc: @@ -1008,7 +1085,7 @@ enforced. This decorator should not be used for :keyword:`async def` coroutines. - .. deprecated-removed:: 3.8 3.10 + .. deprecated-removed:: 3.8 3.11 Use :keyword:`async def` instead. diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst index c2c058e474cbdc..f7f038107d11fe 100644 --- a/Doc/library/atexit.rst +++ b/Doc/library/atexit.rst @@ -39,7 +39,7 @@ internal error is detected, or when :func:`os._exit` is called. If an exception is raised during execution of the exit handlers, a traceback is printed (unless :exc:`SystemExit` is raised) and the exception information is - saved. After all exit handlers have had a chance to run the last exception to + saved. After all exit handlers have had a chance to run, the last exception to be raised is re-raised. This function returns *func*, which makes it possible to use it as a @@ -48,11 +48,12 @@ internal error is detected, or when :func:`os._exit` is called. .. function:: unregister(func) - Remove *func* from the list of functions to be run at interpreter - shutdown. After calling :func:`unregister`, *func* is guaranteed not to be - called when the interpreter shuts down, even if it was registered more than - once. :func:`unregister` silently does nothing if *func* was not previously - registered. + Remove *func* from the list of functions to be run at interpreter shutdown. + :func:`unregister` silently does nothing if *func* was not previously + registered. If *func* has been registered more than once, every occurrence + of that function in the :mod:`atexit` call stack will be removed. Equality + comparisons (``==``) are used internally during unregistration, so function + references do not need to have matching identities. .. seealso:: @@ -73,7 +74,7 @@ automatically when the program terminates without relying on the application making an explicit call into this module at termination. :: try: - with open("counterfile") as infile: + with open('counterfile') as infile: _count = int(infile.read()) except FileNotFoundError: _count = 0 @@ -83,21 +84,22 @@ making an explicit call into this module at termination. :: _count = _count + n def savecounter(): - with open("counterfile", "w") as outfile: - outfile.write("%d" % _count) + with open('counterfile', 'w') as outfile: + outfile.write('%d' % _count) import atexit + atexit.register(savecounter) Positional and keyword arguments may also be passed to :func:`register` to be passed along to the registered function when it is called:: def goodbye(name, adjective): - print('Goodbye, %s, it was %s to meet you.' % (name, adjective)) + print('Goodbye %s, it was %s to meet you.' % (name, adjective)) import atexit - atexit.register(goodbye, 'Donny', 'nice') + atexit.register(goodbye, 'Donny', 'nice') # or: atexit.register(goodbye, adjective='nice', name='Donny') @@ -107,6 +109,6 @@ Usage as a :term:`decorator`:: @atexit.register def goodbye(): - print("You are now leaving the Python sector.") + print('You are now leaving the Python sector.') This only works with functions that can be called without arguments. diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index 2f24bb63912fb6..35fb7b69fa4925 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -2,7 +2,7 @@ =============================================================== .. module:: base64 - :synopsis: RFC 3548: Base16, Base32, Base64 Data Encodings; + :synopsis: RFC 4648: Base16, Base32, Base64 Data Encodings; Base85 and Ascii85 **Source code:** :source:`Lib/base64.py` @@ -16,10 +16,10 @@ This module provides functions for encoding binary data to printable ASCII characters and decoding such encodings back to binary data. It provides encoding and decoding functions for the encodings specified in -:rfc:`3548`, which defines the Base16, Base32, and Base64 algorithms, +:rfc:`4648`, which defines the Base16, Base32, and Base64 algorithms, and for the de-facto standard Ascii85 and Base85 encodings. -The :rfc:`3548` encodings are suitable for encoding binary data so that it can +The :rfc:`4648` encodings are suitable for encoding binary data so that it can be safely sent by email, used as parts of URLs, or included as part of an HTTP POST request. The encoding algorithm is not the same as the :program:`uuencode` program. @@ -28,7 +28,7 @@ There are two interfaces provided by this module. The modern interface supports encoding :term:`bytes-like objects ` to ASCII :class:`bytes`, and decoding :term:`bytes-like objects ` or strings containing ASCII to :class:`bytes`. Both base-64 alphabets -defined in :rfc:`3548` (normal, and URL- and filesystem-safe) are supported. +defined in :rfc:`4648` (normal, and URL- and filesystem-safe) are supported. The legacy interface does not support decoding from strings, but it does provide functions for encoding and decoding to and from :term:`file objects @@ -152,7 +152,7 @@ The modern interface provides: This version does not allow the digit 0 (zero) to the letter O (oh) and digit 1 (one) to either the letter I (eye) or letter L (el) mappings, all these characters are included in the Extended Hex Alphabet and are not - interchangable. + interchangeable. .. versionadded:: 3.10 @@ -287,6 +287,13 @@ An example usage of the module: >>> data b'data to be encoded' +.. _base64-security: + +Security Considerations +----------------------- + +A new security considerations section was added to :rfc:`4648` (section 12); it's +recommended to review the security section for any code deployed to production. .. seealso:: diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst index f6787ab120ed57..999892e95f4715 100644 --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -325,3 +325,8 @@ Writing and reading a bzip2-compressed file in binary mode: ... content = f.read() >>> content == data # Check equality to original object after round-trip True + +.. testcleanup:: + + import os + os.remove("myfile.bz2") diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst index 05d9cdf424073f..c151f04dfb8d01 100644 --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -73,7 +73,7 @@ When you write a new script, consider adding these lines:: cgitb.enable() This activates a special exception handler that will display detailed reports in -the Web browser if any errors occur. If you'd rather not show the guts of your +the web browser if any errors occur. If you'd rather not show the guts of your program to users of your script, you can have the reports saved to files instead, with code like this:: @@ -89,7 +89,7 @@ To get at submitted form data, use the :class:`FieldStorage` class. If the form contains non-ASCII characters, use the *encoding* keyword parameter set to the value of the encoding defined for the document. It is usually contained in the META tag in the HEAD section of the HTML document or by the -:mailheader:`Content-Type` header). This reads the form contents from the +:mailheader:`Content-Type` header. This reads the form contents from the standard input or the environment (depending on the value of various environment variables set according to the CGI standard). Since it may consume standard input, it should be instantiated only once. @@ -316,7 +316,7 @@ algorithms implemented in this module in other circumstances. .. function:: test() Robust test CGI script, usable as main program. Writes minimal HTTP headers and - formats all information provided to the script in HTML form. + formats all information provided to the script in HTML format. .. function:: print_environ() @@ -346,11 +346,11 @@ Caring about security .. index:: pair: CGI; security -There's one important rule: if you invoke an external program (via the -:func:`os.system` or :func:`os.popen` functions. or others with similar +There's one important rule: if you invoke an external program (via +:func:`os.system`, :func:`os.popen` or other functions with similar functionality), make very sure you don't pass arbitrary strings received from the client to the shell. This is a well-known security hole whereby clever -hackers anywhere on the Web can exploit a gullible CGI script to invoke +hackers anywhere on the web can exploit a gullible CGI script to invoke arbitrary shell commands. Even parts of the URL or field names cannot be trusted, since the request doesn't have to come from your form! @@ -424,7 +424,7 @@ above on installing your CGI script carefully can save you a lot of time. If you wonder whether you have understood the installation procedure correctly, try installing a copy of this module file (:file:`cgi.py`) as a CGI script. When invoked as a script, the file will dump its environment and the contents of the -form in HTML form. Give it the right mode etc, and send it a request. If it's +form in HTML format. Give it the right mode etc., and send it a request. If it's installed in the standard :file:`cgi-bin` directory, it should be possible to send it a request by entering a URL into your browser of the form: @@ -457,7 +457,7 @@ likely the traceback will end up in one of the HTTP server's log files, or be discarded altogether. Fortunately, once you have managed to get your script to execute *some* code, -you can easily send tracebacks to the Web browser using the :mod:`cgitb` module. +you can easily send tracebacks to the web browser using the :mod:`cgitb` module. If you haven't done so already, just add the lines:: import cgitb diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 0dcd88f9fd5b7f..ef71832bcef1d3 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -923,7 +923,7 @@ it's a device to determine the storage layout of the encoded bytes, and vanishes once the byte sequence has been decoded into a string; as a ``ZERO WIDTH NO-BREAK SPACE`` it's a normal character that will be decoded like any other. -There's another encoding that is able to encoding the full range of Unicode +There's another encoding that is able to encode the full range of Unicode characters: UTF-8. UTF-8 is an 8-bit encoding, which means there are no issues with byte order in UTF-8. Each byte in a UTF-8 byte sequence consists of two parts: marker bits (the most significant bits) and payload bits. The marker bits diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst index 2345e78a17e4f5..2c941b47748d36 100644 --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -14,7 +14,7 @@ .. testsetup:: * - from collections import * + from collections.abc import * import itertools __name__ = '' @@ -24,6 +24,89 @@ This module provides :term:`abstract base classes ` that can be used to test whether a class provides a particular interface; for example, whether it is hashable or whether it is a mapping. +An :func:`issubclass` or :func:`isinstance` test for an interface works in one +of three ways. + +1) A newly written class can inherit directly from one of the +abstract base classes. The class must supply the required abstract +methods. The remaining mixin methods come from inheritance and can be +overridden if desired. Other methods may be added as needed: + +.. testcode:: + + class C(Sequence): # Direct inheritance + def __init__(self): ... # Extra method not required by the ABC + def __getitem__(self, index): ... # Required abstract method + def __len__(self): ... # Required abstract method + def count(self, value): ... # Optionally override a mixin method + +.. doctest:: + + >>> issubclass(C, Sequence) + True + >>> isinstance(C(), Sequence) + True + +2) Existing classes and built-in classes can be registered as "virtual +subclasses" of the ABCs. Those classes should define the full API +including all of the abstract methods and all of the mixin methods. +This lets users rely on :func:`issubclass` or :func:`isinstance` tests +to determine whether the full interface is supported. The exception to +this rule is for methods that are automatically inferred from the rest +of the API: + +.. testcode:: + + class D: # No inheritance + def __init__(self): ... # Extra method not required by the ABC + def __getitem__(self, index): ... # Abstract method + def __len__(self): ... # Abstract method + def count(self, value): ... # Mixin method + def index(self, value): ... # Mixin method + + Sequence.register(D) # Register instead of inherit + +.. doctest:: + + >>> issubclass(D, Sequence) + True + >>> isinstance(D(), Sequence) + True + +In this example, class :class:`D` does not need to define +``__contains__``, ``__iter__``, and ``__reversed__`` because the +:ref:`in-operator `, the :term:`iteration ` +logic, and the :func:`reversed` function automatically fall back to +using ``__getitem__`` and ``__len__``. + +3) Some simple interfaces are directly recognizable by the presence of +the required methods (unless those methods have been set to +:const:`None`): + +.. testcode:: + + class E: + def __iter__(self): ... + def __next__(next): ... + +.. doctest:: + + >>> issubclass(E, Iterable) + True + >>> isinstance(E(), Iterable) + True + +Complex interfaces do not support this last technique because an +interface is more than just the presence of method names. Interfaces +specify semantics and relationships between methods that cannot be +inferred solely from the presence of specific method names. For +example, knowing that a class supplies ``__getitem__``, ``__len__``, and +``__iter__`` is insufficient for distinguishing a :class:`Sequence` from +a :class:`Mapping`. + +.. versionadded:: 3.9 + These abstract classes now support ``[]``. See :ref:`types-genericalias` + and :pep:`585`. .. _collections-abstract-base-classes: @@ -34,67 +117,86 @@ The collections module offers the following :term:`ABCs `: .. tabularcolumns:: |l|L|L|L| -========================== ====================== ======================= ==================================================== -ABC Inherits from Abstract Methods Mixin Methods -========================== ====================== ======================= ==================================================== -:class:`Container` ``__contains__`` -:class:`Hashable` ``__hash__`` -:class:`Iterable` ``__iter__`` -:class:`Iterator` :class:`Iterable` ``__next__`` ``__iter__`` -:class:`Reversible` :class:`Iterable` ``__reversed__`` -:class:`Generator` :class:`Iterator` ``send``, ``throw`` ``close``, ``__iter__``, ``__next__`` -:class:`Sized` ``__len__`` -:class:`Callable` ``__call__`` -:class:`Collection` :class:`Sized`, ``__contains__``, - :class:`Iterable`, ``__iter__``, - :class:`Container` ``__len__`` - -:class:`Sequence` :class:`Reversible`, ``__getitem__``, ``__contains__``, ``__iter__``, ``__reversed__``, - :class:`Collection` ``__len__`` ``index``, and ``count`` - -:class:`MutableSequence` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods and - ``__setitem__``, ``append``, ``reverse``, ``extend``, ``pop``, - ``__delitem__``, ``remove``, and ``__iadd__`` - ``__len__``, - ``insert`` - -:class:`ByteString` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods - ``__len__`` - -:class:`Set` :class:`Collection` ``__contains__``, ``__le__``, ``__lt__``, ``__eq__``, ``__ne__``, - ``__iter__``, ``__gt__``, ``__ge__``, ``__and__``, ``__or__``, - ``__len__`` ``__sub__``, ``__xor__``, and ``isdisjoint`` - -:class:`MutableSet` :class:`Set` ``__contains__``, Inherited :class:`Set` methods and - ``__iter__``, ``clear``, ``pop``, ``remove``, ``__ior__``, - ``__len__``, ``__iand__``, ``__ixor__``, and ``__isub__`` - ``add``, - ``discard`` - -:class:`Mapping` :class:`Collection` ``__getitem__``, ``__contains__``, ``keys``, ``items``, ``values``, - ``__iter__``, ``get``, ``__eq__``, and ``__ne__`` - ``__len__`` - -:class:`MutableMapping` :class:`Mapping` ``__getitem__``, Inherited :class:`Mapping` methods and - ``__setitem__``, ``pop``, ``popitem``, ``clear``, ``update``, - ``__delitem__``, and ``setdefault`` - ``__iter__``, - ``__len__`` - - -:class:`MappingView` :class:`Sized` ``__len__`` -:class:`ItemsView` :class:`MappingView`, ``__contains__``, - :class:`Set` ``__iter__`` -:class:`KeysView` :class:`MappingView`, ``__contains__``, - :class:`Set` ``__iter__`` -:class:`ValuesView` :class:`MappingView`, ``__contains__``, ``__iter__`` - :class:`Collection` -:class:`Awaitable` ``__await__`` -:class:`Coroutine` :class:`Awaitable` ``send``, ``throw`` ``close`` -:class:`AsyncIterable` ``__aiter__`` -:class:`AsyncIterator` :class:`AsyncIterable` ``__anext__`` ``__aiter__`` -:class:`AsyncGenerator` :class:`AsyncIterator` ``asend``, ``athrow`` ``aclose``, ``__aiter__``, ``__anext__`` -========================== ====================== ======================= ==================================================== +============================== ====================== ======================= ==================================================== +ABC Inherits from Abstract Methods Mixin Methods +============================== ====================== ======================= ==================================================== +:class:`Container` [1]_ ``__contains__`` +:class:`Hashable` [1]_ ``__hash__`` +:class:`Iterable` [1]_ [2]_ ``__iter__`` +:class:`Iterator` [1]_ :class:`Iterable` ``__next__`` ``__iter__`` +:class:`Reversible` [1]_ :class:`Iterable` ``__reversed__`` +:class:`Generator` [1]_ :class:`Iterator` ``send``, ``throw`` ``close``, ``__iter__``, ``__next__`` +:class:`Sized` [1]_ ``__len__`` +:class:`Callable` [1]_ ``__call__`` +:class:`Collection` [1]_ :class:`Sized`, ``__contains__``, + :class:`Iterable`, ``__iter__``, + :class:`Container` ``__len__`` + +:class:`Sequence` :class:`Reversible`, ``__getitem__``, ``__contains__``, ``__iter__``, ``__reversed__``, + :class:`Collection` ``__len__`` ``index``, and ``count`` + +:class:`MutableSequence` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods and + ``__setitem__``, ``append``, ``reverse``, ``extend``, ``pop``, + ``__delitem__``, ``remove``, and ``__iadd__`` + ``__len__``, + ``insert`` + +:class:`ByteString` :class:`Sequence` ``__getitem__``, Inherited :class:`Sequence` methods + ``__len__`` + +:class:`Set` :class:`Collection` ``__contains__``, ``__le__``, ``__lt__``, ``__eq__``, ``__ne__``, + ``__iter__``, ``__gt__``, ``__ge__``, ``__and__``, ``__or__``, + ``__len__`` ``__sub__``, ``__xor__``, and ``isdisjoint`` + +:class:`MutableSet` :class:`Set` ``__contains__``, Inherited :class:`Set` methods and + ``__iter__``, ``clear``, ``pop``, ``remove``, ``__ior__``, + ``__len__``, ``__iand__``, ``__ixor__``, and ``__isub__`` + ``add``, + ``discard`` + +:class:`Mapping` :class:`Collection` ``__getitem__``, ``__contains__``, ``keys``, ``items``, ``values``, + ``__iter__``, ``get``, ``__eq__``, and ``__ne__`` + ``__len__`` + +:class:`MutableMapping` :class:`Mapping` ``__getitem__``, Inherited :class:`Mapping` methods and + ``__setitem__``, ``pop``, ``popitem``, ``clear``, ``update``, + ``__delitem__``, and ``setdefault`` + ``__iter__``, + ``__len__`` + + +:class:`MappingView` :class:`Sized` ``__len__`` +:class:`ItemsView` :class:`MappingView`, ``__contains__``, + :class:`Set` ``__iter__`` +:class:`KeysView` :class:`MappingView`, ``__contains__``, + :class:`Set` ``__iter__`` +:class:`ValuesView` :class:`MappingView`, ``__contains__``, ``__iter__`` + :class:`Collection` +:class:`Awaitable` [1]_ ``__await__`` +:class:`Coroutine` [1]_ :class:`Awaitable` ``send``, ``throw`` ``close`` +:class:`AsyncIterable` [1]_ ``__aiter__`` +:class:`AsyncIterator` [1]_ :class:`AsyncIterable` ``__anext__`` ``__aiter__`` +:class:`AsyncGenerator` [1]_ :class:`AsyncIterator` ``asend``, ``athrow`` ``aclose``, ``__aiter__``, ``__anext__`` +============================== ====================== ======================= ==================================================== + + +.. rubric:: Footnotes + +.. [1] These ABCs override :meth:`object.__subclasshook__` to support + testing an interface by verifying the required methods are present + and have not been set to :const:`None`. This only works for simple + interfaces. More complex interfaces require registration or direct + subclassing. + +.. [2] Checking ``isinstance(obj, Iterable)`` detects classes that are + registered as :class:`Iterable` or that have an :meth:`__iter__` + method, but it does not detect classes that iterate with the + :meth:`__getitem__` method. The only reliable way to determine + whether an object is :term:`iterable` is to call ``iter(obj)``. + + +Collections Abstract Base Classes -- Detailed Descriptions +---------------------------------------------------------- .. class:: Container @@ -244,8 +346,10 @@ ABC Inherits from Abstract Methods Mixin .. versionadded:: 3.6 +Examples and Recipes +-------------------- -These ABCs allow us to ask classes or instances if they provide +ABCs allow us to ask classes or instances if they provide particular functionality, for example:: size = None diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 94166ec6c754a7..b8a717d883c093 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -343,7 +343,7 @@ All of those tests treat missing elements as having zero counts so that ``Counter(a=1) == Counter(a=1, b=0)`` returns true. .. versionadded:: 3.10 - Rich comparison operations we were added + Rich comparison operations were added. .. versionchanged:: 3.10 In equality tests, missing elements are treated as having zero counts. @@ -707,9 +707,9 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, :class:`defaultdict` objects ---------------------------- -.. class:: defaultdict([default_factory[, ...]]) +.. class:: defaultdict(default_factory=None, /, [...]) - Returns a new dictionary-like object. :class:`defaultdict` is a subclass of the + Return a new dictionary-like object. :class:`defaultdict` is a subclass of the built-in :class:`dict` class. It overrides one method and adds one writable instance variable. The remaining functionality is the same as for the :class:`dict` class and is not documented here. @@ -1120,14 +1120,16 @@ Some differences from :class:`dict` still remain: Move an existing *key* to either end of an ordered dictionary. The item is moved to the right end if *last* is true (the default) or to the beginning if *last* is false. Raises :exc:`KeyError` if the *key* does - not exist:: + not exist: + + .. doctest:: >>> d = OrderedDict.fromkeys('abcde') >>> d.move_to_end('b') - >>> ''.join(d.keys()) + >>> ''.join(d) 'acdeb' >>> d.move_to_end('b', last=False) - >>> ''.join(d.keys()) + >>> ''.join(d) 'bacde' .. versionadded:: 3.2 @@ -1171,28 +1173,101 @@ 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 :func:`functools.lru_cache`: - class LRU(OrderedDict): - 'Limit size, evicting the least recently looked-up key when full' +.. testcode:: - def __init__(self, maxsize=128, /, *args, **kwds): - self.maxsize = maxsize - super().__init__(*args, **kwds) + from time import time - def __getitem__(self, key): - value = super().__getitem__(key) - self.move_to_end(key) - return value + class TimeBoundedLRU: + "LRU Cache that invalidates and refreshes old entries." - def __setitem__(self, key, value): - if key in self: - self.move_to_end(key) - super().__setitem__(key, value) - if len(self) > self.maxsize: - oldest = next(iter(self)) - del self[oldest] + def __init__(self, func, maxsize=128, maxage=30): + self.cache = OrderedDict() # { args : (timestamp, result)} + self.func = func + self.maxsize = maxsize + self.maxage = maxage + + def __call__(self, *args): + if args in self.cache: + self.cache.move_to_end(args) + timestamp, result = self.cache[args] + if time() - timestamp <= self.maxage: + return result + result = self.func(*args) + self.cache[args] = time(), result + if len(self.cache) > self.maxsize: + self.cache.popitem(0) + return result + + +.. testcode:: + + class MultiHitLRUCache: + """ LRU cache that defers caching a result until + it has been requested multiple times. + + To avoid flushing the LRU cache with one-time requests, + we don't cache until a request has been made more than once. + + """ + + def __init__(self, func, maxsize=128, maxrequests=4096, cache_after=1): + self.requests = OrderedDict() # { uncached_key : request_count } + self.cache = OrderedDict() # { cached_key : function_result } + self.func = func + self.maxrequests = maxrequests # max number of uncached requests + self.maxsize = maxsize # max number of stored return values + self.cache_after = cache_after + + def __call__(self, *args): + if args in self.cache: + self.cache.move_to_end(args) + return self.cache[args] + result = self.func(*args) + self.requests[args] = self.requests.get(args, 0) + 1 + if self.requests[args] <= self.cache_after: + self.requests.move_to_end(args) + if len(self.requests) > self.maxrequests: + self.requests.popitem(0) + else: + self.requests.pop(args, None) + self.cache[args] = result + if len(self.cache) > self.maxsize: + self.cache.popitem(0) + return result +.. doctest:: + :hide: + + >>> def square(x): + ... return x * x + ... + >>> f = MultiHitLRUCache(square, maxsize=4, maxrequests=6) + >>> list(map(f, range(10))) # First requests, don't cache + [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] + >>> f(4) # Cache the second request + 16 + >>> f(6) # Cache the second request + 36 + >>> f(2) # The first request aged out, so don't cache + 4 + >>> f(6) # Cache hit + 36 + >>> f(4) # Cache hit and move to front + 16 + >>> list(f.cache.values()) + [36, 16] + >>> set(f.requests).isdisjoint(f.cache) + True + >>> list(map(f, [9, 8, 7])) # Cache these second requests + [81, 64, 49] + >>> list(map(f, [7, 9])) # Cache hits + [49, 81] + >>> list(f.cache.values()) + [16, 64, 49, 81] + >>> set(f.requests).isdisjoint(f.cache) + True :class:`UserDict` objects ------------------------- @@ -1209,7 +1284,7 @@ attribute. regular dictionary, which is accessible via the :attr:`data` attribute of :class:`UserDict` instances. If *initialdata* is provided, :attr:`data` is initialized with its contents; note that a reference to *initialdata* will not - be kept, allowing it be used for other purposes. + be kept, allowing it to be used for other purposes. In addition to supporting the methods and operations of mappings, :class:`UserDict` instances provide the following attribute: diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst index 5c6e68f9304753..de34664acb84ab 100644 --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -166,9 +166,10 @@ Public functions If *force* is true, modules are re-compiled even if the timestamps are up to date. - If *rx* is given, its search method is called on the complete path to each + If *rx* is given, its ``search`` method is called on the complete path to each file considered for compilation, and if it returns a true value, the file - is skipped. + is skipped. This can be used to exclude files matching a regular expression, + given as a :ref:`re.Pattern ` object. If *quiet* is ``False`` or ``0`` (the default), the filenames and other information are printed to standard out. Set to ``1``, only errors are @@ -242,9 +243,10 @@ Public functions cases where the source file does not exist at the time the byte-code file is executed. - If *rx* is given, its search method is passed the full path name to the + If *rx* is given, its ``search`` method is passed the full path name to the file being compiled, and if it returns a true value, the file is not - compiled and ``True`` is returned. + compiled and ``True`` is returned. This can be used to exclude files matching + a regular expression, given as a :ref:`re.Pattern ` object. If *quiet* is ``False`` or ``0`` (the default), the filenames and other information are printed to standard out. Set to ``1``, only errors are diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index d57f8ce23d12c4..70a17a23119c12 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -30,7 +30,7 @@ Executor Objects .. method:: submit(fn, /, *args, **kwargs) - Schedules the callable, *fn*, to be executed as ``fn(*args **kwargs)`` + Schedules the callable, *fn*, to be executed as ``fn(*args, **kwargs)`` and returns a :class:`Future` object representing the execution of the callable. :: @@ -350,7 +350,7 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. If the future is cancelled before completing then :exc:`.CancelledError` will be raised. - If the call raised, this method will raise the same exception. + If the call raised an exception, this method will raise the same exception. .. method:: exception(timeout=None) @@ -435,7 +435,8 @@ Module Functions .. function:: wait(fs, timeout=None, return_when=ALL_COMPLETED) Wait for the :class:`Future` instances (possibly created by different - :class:`Executor` instances) given by *fs* to complete. Returns a named + :class:`Executor` instances) given by *fs* to complete. Duplicate futures + given to *fs* are removed and will be returned only once. Returns a named 2-tuple of sets. The first set, named ``done``, contains the futures that completed (finished or cancelled futures) before the wait completed. The second set, named ``not_done``, contains the futures that did not complete diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index 646e8a317f52c3..1ebda53ecda0fb 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -46,6 +46,11 @@ can be customized by end users easily. import configparser +.. testcleanup:: + + import os + os.remove("example.ini") + Quick Start ----------- @@ -256,7 +261,8 @@ A configuration file consists of sections, each led by a ``[section]`` header, followed by key/value entries separated by a specific string (``=`` or ``:`` by default [1]_). By default, section names are case sensitive but keys are not [1]_. Leading and trailing whitespace is removed from keys and values. -Values can be omitted, in which case the key/value delimiter may also be left +Values can be omitted if the parser is configured to allow it [1]_, +in which case the key/value delimiter may also be left out. Values can also span multiple lines, as long as they are indented deeper than the first line of the value. Depending on the parser's mode, blank lines may be treated as parts of multiline values or ignored. @@ -1153,6 +1159,13 @@ ConfigParser Objects *space_around_delimiters* is true, delimiters between keys and values are surrounded by spaces. + .. note:: + + Comments in the original configuration file are not preserved when + writing the configuration back. + What is considered a comment, depends on the given values for + *comment_prefix* and *inline_comment_prefix*. + .. method:: remove_option(section, option) diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index b92f703509fcac..b6ec6b8c876bee 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -130,7 +130,9 @@ Functions and classes provided: either as decorators or with :keyword:`async with` statements:: import time + from contextlib import asynccontextmanager + @asynccontextmanager async def timeit(): now = time.monotonic() try: @@ -171,7 +173,7 @@ Functions and classes provided: from contextlib import closing from urllib.request import urlopen - with closing(urlopen('http://www.python.org')) as page: + with closing(urlopen('https://www.python.org')) as page: for line in page: print(line) @@ -267,8 +269,9 @@ Functions and classes provided: .. function:: suppress(*exceptions) Return a context manager that suppresses any of the specified exceptions - if they occur in the body of a with statement and then resumes execution - with the first statement following the end of the with statement. + if they occur in the body of a :keyword:`!with` statement and then + resumes execution with the first statement following the end of the + :keyword:`!with` statement. As with any other mechanism that completely suppresses exceptions, this context manager should be used only to cover very specific errors where @@ -312,10 +315,11 @@ Functions and classes provided: For example, the output of :func:`help` normally is sent to *sys.stdout*. You can capture that output in a string by redirecting the output to an - :class:`io.StringIO` object:: + :class:`io.StringIO` object. The replacement stream is returned from the + ``__enter__`` method and so is available as the target of the + :keyword:`with` statement:: - f = io.StringIO() - with redirect_stdout(f): + with redirect_stdout(io.StringIO()) as f: help(pow) s = f.getvalue() @@ -578,7 +582,7 @@ Functions and classes provided: The :meth:`close` method is not implemented, :meth:`aclose` must be used instead. - .. method:: enter_async_context(cm) + .. coroutinemethod:: enter_async_context(cm) Similar to :meth:`enter_context` but expects an asynchronous context manager. @@ -592,7 +596,7 @@ Functions and classes provided: Similar to :meth:`callback` but expects a coroutine function. - .. method:: aclose() + .. coroutinemethod:: aclose() Similar to :meth:`close` but properly handles awaitables. diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 14ac47f4c9eb16..be1dd0c9eb57e8 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -94,7 +94,7 @@ Context Variables # var.get() would raise a LookupError. -.. class:: contextvars.Token +.. class:: Token *Token* objects are returned by the :meth:`ContextVar.set` method. They can be passed to the :meth:`ContextVar.reset` method to revert diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst index 01ebf198d7c501..a8bc2fa55ea8c3 100644 --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -60,7 +60,7 @@ The :func:`deepcopy` function avoids these problems by: components copied. This module does not copy types like module, method, stack trace, stack frame, -file, socket, window, array, or any similar types. It does "copy" functions and +file, socket, window, or any similar types. It does "copy" functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the :mod:`pickle` module. diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index 7a72c26d5badeb..899ce0225ce7f3 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -94,8 +94,8 @@ The :mod:`csv` module defines the following functions: :class:`Dialect` class or one of the strings returned by the :func:`list_dialects` function. The other optional *fmtparams* keyword arguments can be given to override individual formatting parameters in the current - dialect. For full details about the dialect and formatting parameters, see - section :ref:`csv-fmt-params`. To make it + dialect. For full details about dialects and formatting parameters, see + the :ref:`csv-fmt-params` section. To make it as easy as possible to interface with modules which implement the DB API, the value :const:`None` is written as the empty string. While this isn't a reversible transformation, it makes it easier to dump SQL NULL data values to @@ -117,7 +117,7 @@ The :mod:`csv` module defines the following functions: Associate *dialect* with *name*. *name* must be a string. The dialect can be specified either by passing a sub-class of :class:`Dialect`, or by *fmtparams* keyword arguments, or both, with keyword arguments overriding - parameters of the dialect. For full details about the dialect and formatting + parameters of the dialect. For full details about dialects and formatting parameters, see section :ref:`csv-fmt-params`. @@ -225,9 +225,21 @@ The :mod:`csv` module defines the following classes: .. class:: Dialect - The :class:`Dialect` class is a container class relied on primarily for its - attributes, which are used to define the parameters for a specific - :class:`reader` or :class:`writer` instance. + The :class:`Dialect` class is a container class whose attributes contain + information for how to handle doublequotes, whitespace, delimiters, etc. + Due to the lack of a strict CSV specification, different applications + produce subtly different CSV data. :class:`Dialect` instances define how + :class:`reader` and :class:`writer` instances behave. + + All available :class:`Dialect` names are returned by :func:`list_dialects`, + and they can be registered with specific :class:`reader` and :class:`writer` + classes through their initializer (``__init__``) functions like this:: + + import csv + + with open('students.csv', 'w', newline='') as csvfile: + writer = csv.writer(csvfile, dialect='unix') + ^^^^^^^^^^^^^^ .. class:: excel() @@ -269,6 +281,20 @@ The :mod:`csv` module defines the following classes: Analyze the sample text (presumed to be in CSV format) and return :const:`True` if the first row appears to be a series of column headers. + Inspecting each column, one of two key criteria will be considered to + estimate if the sample contains a header: + + - the second through n-th rows contain numeric values + - the second through n-th rows contain strings where at least one value's + length differs from that of the putative header of that column. + + Twenty rows after the first row are sampled; if more than half of columns + + rows meet the criteria, :const:`True` is returned. + + .. note:: + + This method is a rough heuristic and may produce both false positives and + negatives. An example for :class:`Sniffer` use:: @@ -405,8 +431,8 @@ Reader objects (:class:`DictReader` instances and objects returned by the Return the next row of the reader's iterable object as a list (if the object was returned from :func:`reader`) or a dict (if it is a :class:`DictReader` - instance), parsed according to the current dialect. Usually you should call - this as ``next(reader)``. + instance), parsed according to the current :class:`Dialect`. Usually you + should call this as ``next(reader)``. Reader objects have the following public attributes: @@ -446,9 +472,9 @@ read CSV files (assuming they support complex numbers at all). .. method:: csvwriter.writerow(row) - Write the *row* parameter to the writer's file object, formatted according to - the current dialect. Return the return value of the call to the *write* method - of the underlying file object. + Write the *row* parameter to the writer's file object, formatted according + to the current :class:`Dialect`. Return the return value of the call to the + *write* method of the underlying file object. .. versionchanged:: 3.5 Added support of arbitrary iterables. diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index fd6422cc8c06c5..c10e54f153243f 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -20,7 +20,7 @@ ctypes tutorial Note: The code samples in this tutorial use :mod:`doctest` to make sure that they actually work. Since some code samples behave differently under Linux, -Windows, or Mac OS X, they contain doctest directives in comments. +Windows, or macOS, they contain doctest directives in comments. Note: Some code samples reference the ctypes :class:`c_int` type. On platforms where ``sizeof(long) == sizeof(int)`` it is an alias to :class:`c_long`. @@ -80,7 +80,7 @@ the library by creating an instance of CDLL by calling the constructor:: >>> -.. XXX Add section for Mac OS X. +.. XXX Add section for macOS. .. _ctypes-accessing-functions-from-loaded-dlls: @@ -1288,7 +1288,7 @@ Here are some examples:: 'libbz2.so.1.0' >>> -On OS X, :func:`find_library` tries several predefined naming schemes and paths +On macOS, :func:`find_library` tries several predefined naming schemes and paths to locate the library, and returns a full pathname if successful:: >>> from ctypes.util import find_library @@ -1320,7 +1320,7 @@ There are several ways to load shared libraries into the Python process. One way is to instantiate one of the following classes: -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return @@ -1342,7 +1342,7 @@ way is to instantiate one of the following classes: -- A tool to find DLL dependents. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1355,7 +1355,7 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) +.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 64540b3e963b52..6a9863cf56a6d3 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -17,7 +17,7 @@ adding generated :term:`special method`\s such as :meth:`__init__` and in :pep:`557`. The member variables to use in these generated methods are defined -using :pep:`526` type annotations. For example this code:: +using :pep:`526` type annotations. For example, this code:: from dataclasses import dataclass @@ -31,7 +31,7 @@ using :pep:`526` type annotations. For example this code:: def total_cost(self) -> float: return self.unit_price * self.quantity_on_hand -Will add, among other things, a :meth:`__init__` that looks like:: +will add, among other things, a :meth:`__init__` that looks like:: def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0): self.name = name @@ -52,7 +52,7 @@ Module contents :term:`special method`\s to classes, as described below. The :func:`dataclass` decorator examines the class to find - ``field``\s. A ``field`` is defined as class variable that has a + ``field``\s. A ``field`` is defined as a class variable that has a :term:`type annotation `. With two exceptions described below, nothing in :func:`dataclass` examines the type specified in the variable annotation. @@ -62,8 +62,8 @@ Module contents The :func:`dataclass` decorator will add various "dunder" methods to the class, described below. If any of the added methods already - exist on the class, the behavior depends on the parameter, as documented - below. The decorator returns the same class that is called on; no new + exist in the class, the behavior depends on the parameter, as documented + below. The decorator returns the same class that it is called on; no new class is created. If :func:`dataclass` is used just as a simple decorator with no parameters, @@ -202,10 +202,10 @@ Module contents def __init__(self, a: int, b: int = 0): :exc:`TypeError` will be raised if a field without a default value - follows a field with a default value. This is true either when this + follows a field with a default value. This is true whether this occurs in a single class, or as a result of class inheritance. -.. function:: field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING): +.. function:: field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING) For common and simple use cases, no other functionality is required. There are, however, some dataclass features that @@ -221,10 +221,9 @@ Module contents c.mylist += [1, 2, 3] As shown above, the :const:`MISSING` value is a sentinel object used to - detect if the ``default`` and ``default_factory`` parameters are - provided. This sentinel is used because ``None`` is a valid value - for ``default``. No code should directly use the :const:`MISSING` - value. + detect if some parameters are provided by the user. This sentinel is + used because ``None`` is a valid value for some parameters with + a distinct meaning. No code should directly use the :const:`MISSING` value. The parameters to :func:`field` are: @@ -308,7 +307,7 @@ Module contents - ``default``, ``default_factory``, ``init``, ``repr``, ``hash``, ``compare``, ``metadata``, and ``kw_only`` have the identical - meaning and values as they do in the :func:`field` declaration. + meaning and values as they do in the :func:`field` function. Other attributes may exist, but they are private and must not be inspected or relied on. @@ -320,12 +319,15 @@ Module contents Raises :exc:`TypeError` if not passed a dataclass or instance of one. Does not return pseudo-fields which are ``ClassVar`` or ``InitVar``. -.. function:: asdict(instance, *, dict_factory=dict) +.. function:: asdict(obj, *, dict_factory=dict) - Converts the dataclass ``instance`` to a dict (by using the + Converts the dataclass ``obj`` to a dict (by using the factory function ``dict_factory``). Each dataclass is converted to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, - lists, and tuples are recursed into. For example:: + lists, and tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. + + Example of using :func:`asdict` on nested dataclasses:: @dataclass class Point: @@ -342,21 +344,32 @@ Module contents c = C([Point(0, 0), Point(10, 4)]) assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + dict((field.name, getattr(obj, field.name)) for field in fields(obj)) -.. function:: astuple(instance, *, tuple_factory=tuple) + :func:`asdict` raises :exc:`TypeError` if ``obj`` is not a dataclass + instance. - Converts the dataclass ``instance`` to a tuple (by using the +.. function:: astuple(obj, *, tuple_factory=tuple) + + Converts the dataclass ``obj`` to a tuple (by using the factory function ``tuple_factory``). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and - tuples are recursed into. + tuples are recursed into. Other objects are copied with + :func:`copy.deepcopy`. Continuing from the previous example:: assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. + To create a shallow copy, the following workaround may be used:: + + tuple(getattr(obj, field.name) for field in dataclasses.fields(obj)) + + :func:`astuple` raises :exc:`TypeError` if ``obj`` is not a dataclass + instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False) @@ -393,10 +406,10 @@ Module contents def add_one(self): return self.x + 1 -.. function:: replace(instance, /, **changes) +.. function:: replace(obj, /, **changes) - Creates a new object of the same type of ``instance``, replacing - fields with values from ``changes``. If ``instance`` is not a Data + Creates a new object of the same type as ``obj``, replacing + fields with values from ``changes``. If ``obj`` is not a Data Class, raises :exc:`TypeError`. If values in ``changes`` do not specify fields, raises :exc:`TypeError`. @@ -421,7 +434,7 @@ Module contents ``replace()`` (or similarly named) method which handles instance copying. -.. function:: is_dataclass(class_or_instance) +.. function:: is_dataclass(obj) Return ``True`` if its parameter is a dataclass or an instance of one, otherwise return ``False``. @@ -491,6 +504,27 @@ depend on one or more other fields. For example:: def __post_init__(self): self.c = self.a + self.b +The :meth:`__init__` method generated by :func:`dataclass` does not call base +class :meth:`__init__` methods. If the base class has an :meth:`__init__` method +that has to be called, it is common to call this method in a +:meth:`__post_init__` method:: + + @dataclass + class Rectangle: + height: float + width: float + + @dataclass + class Square(Rectangle): + side: float + + def __post_init__(self): + super().__init__(self.side, self.side) + +Note, however, that in general the dataclass-generated :meth:`__init__` methods +don't need to be called, since the derived dataclass will take care of +initializing all fields of any base class that is a dataclass itself. + See the section below on init-only variables for ways to pass parameters to :meth:`__post_init__`. Also see the warning about how :func:`replace` handles ``init=False`` fields. diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index dae0dd7aa55898..217cdf222b89b7 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -27,6 +27,9 @@ on efficient attribute extraction for output formatting and manipulation. Module :mod:`time` Time access and conversions. + Module :mod:`zoneinfo` + Concrete time zones representing the IANA time zone database. + Package `dateutil `_ Third-party library with expanded time zone and parsing support. @@ -2174,14 +2177,13 @@ only EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). .. seealso:: - `dateutil.tz `_ + :mod:`zoneinfo` The :mod:`datetime` module has a basic :class:`timezone` class (for handling arbitrary fixed offsets from UTC) and its :attr:`timezone.utc` attribute (a UTC timezone instance). - *dateutil.tz* library brings the *IANA timezone database* - (also known as the Olson database) to Python, and its usage is - recommended. + ``zoneinfo`` brings the *IANA timezone database* (also known as the Olson + database) to Python, and its usage is recommended. `IANA timezone database `_ The Time Zone Database (often called tz, tzdata or zoneinfo) contains code @@ -2357,8 +2359,8 @@ requires, and these work on all platforms with a standard C implementation. | | decimal number. | | \(9) | +-----------+--------------------------------+------------------------+-------+ | ``%f`` | Microsecond as a decimal | 000000, 000001, ..., | \(5) | -| | number, zero-padded on the | 999999 | | -| | left. | | | +| | number, zero-padded to 6 | 999999 | | +| | digits. | | | +-----------+--------------------------------+------------------------+-------+ | ``%z`` | UTC offset in the form | (empty), +0000, | \(6) | | | ``±HHMM[SS[.ffffff]]`` (empty | -0400, +1030, | | @@ -2431,7 +2433,8 @@ incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`. The full set of format codes supported varies across platforms, because Python calls the platform C library's :func:`strftime` function, and platform variations are common. To see the full set of format codes supported on your -platform, consult the :manpage:`strftime(3)` documentation. +platform, consult the :manpage:`strftime(3)` documentation. There are also +differences between platforms in handling of unsupported format specifiers. .. versionadded:: 3.6 ``%G``, ``%u`` and ``%V`` were added. diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 57ae547b833cc0..ff01ae90f64257 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -216,7 +216,7 @@ supported. contains them all:: k = db.firstkey() - while k != None: + while k is not None: print(k) k = db.nextkey(k) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 0491a9d4a072bf..74820f9bdb5783 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -770,17 +770,20 @@ iterations of the loop. .. opcode:: MATCH_MAPPING - If TOS is an instance of :class:`collections.abc.Mapping`, push ``True`` onto - the stack. Otherwise, push ``False``. + If TOS is an instance of :class:`collections.abc.Mapping` (or, more technically: if + it has the :const:`Py_TPFLAGS_MAPPING` flag set in its + :c:member:`~PyTypeObject.tp_flags`), push ``True`` onto the stack. Otherwise, push + ``False``. .. versionadded:: 3.10 .. opcode:: MATCH_SEQUENCE - If TOS is an instance of :class:`collections.abc.Sequence` and is *not* an - instance of :class:`str`/:class:`bytes`/:class:`bytearray`, push ``True`` - onto the stack. Otherwise, push ``False``. + If TOS is an instance of :class:`collections.abc.Sequence` and is *not* an instance + of :class:`str`/:class:`bytes`/:class:`bytearray` (or, more technically: if it has + the :const:`Py_TPFLAGS_SEQUENCE` flag set in its :c:member:`~PyTypeObject.tp_flags`), + push ``True`` onto the stack. Otherwise, push ``False``. .. versionadded:: 3.10 @@ -1249,9 +1252,8 @@ All of the following opcodes use their arguments. .. opcode:: GEN_START (kind) - Pops TOS. If TOS was not ``None``, raises an exception. The ``kind`` - operand corresponds to the type of generator or coroutine and determines - the error message. The legal kinds are 0 for generator, 1 for coroutine, + Pops TOS. The ``kind`` operand corresponds to the type of generator or + coroutine. The legal kinds are 0 for generator, 1 for coroutine, and 2 for async generator. .. versionadded:: 3.10 diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index b5f9c2f08b1873..7d166bfb1fcc61 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -13,617 +13,1200 @@ **Source code:** :source:`Lib/enum.py` -.. sidebar:: Important +---------------- - This page contains the API reference information. For tutorial - information and discussion of more advanced topics, see +An enumeration is a set of symbolic names (members) bound to unique, +constant values. Within an enumeration, the members can be compared +by identity, and the enumeration itself can be iterated over. - * :ref:`Basic Tutorial ` - * :ref:`Advanced Tutorial ` - * :ref:`Enum Cookbook ` +.. note:: Case of Enum Members ----------------- + Because Enums are used to represent constants we recommend using + UPPER_CASE names for enum members, and will be using that style + in our examples. -An enumeration: -* is a set of symbolic names (members) bound to unique values -* can be iterated over to return its members in definition order -* uses :meth:`call` syntax to return members by value -* uses :meth:`index` syntax to return members by name +Module Contents +--------------- -Enumerations are created either by using the :keyword:`class` syntax, or by -using function-call syntax:: +This module defines four enumeration classes that can be used to define unique +sets of names and values: :class:`Enum`, :class:`IntEnum`, :class:`Flag`, and +:class:`IntFlag`. It also defines one decorator, :func:`unique`, and one +helper, :class:`auto`. - >>> from enum import Enum +.. class:: Enum - >>> # class syntax - >>> class Color(Enum): - ... RED = 1 - ... GREEN = 2 - ... BLUE = 3 + Base class for creating enumerated constants. See section + `Functional API`_ for an alternate construction syntax. - >>> # functional syntax - >>> Color = Enum('Color', ['RED', 'GREEN', 'BLUE']) +.. class:: IntEnum -Even though we can use the :keyword:`class` syntax to create Enums, Enums -are not normal Python classes. See -:ref:`How are Enums different? ` for more details. + Base class for creating enumerated constants that are also + subclasses of :class:`int`. -.. note:: Nomenclature +.. class:: IntFlag - - The class :class:`Color` is an *enumeration* (or *enum*) - - The attributes :attr:`Color.RED`, :attr:`Color.GREEN`, etc., are - *enumeration members* (or *enum members*) and are functionally constants. - - The enum members have *names* and *values* (the name of - :attr:`Color.RED` is ``RED``, the value of :attr:`Color.BLUE` is - ``3``, etc.) + Base class for creating enumerated constants that can be combined using + the bitwise operators without losing their :class:`IntFlag` membership. + :class:`IntFlag` members are also subclasses of :class:`int`. +.. class:: Flag -Module Contents ---------------- + Base class for creating enumerated constants that can be combined using + the bitwise operations without losing their :class:`Flag` membership. - :class:`EnumType` +.. function:: unique + :noindex: - The ``type`` for Enum and its subclasses. + Enum class decorator that ensures only one name is bound to any one value. - :class:`Enum` +.. class:: auto - Base class for creating enumerated constants. + Instances are replaced with an appropriate value for Enum members. By default, the initial value starts at 1. - :class:`IntEnum` +.. versionadded:: 3.6 ``Flag``, ``IntFlag``, ``auto`` - Base class for creating enumerated constants that are also - subclasses of :class:`int`. - :class:`StrEnum` +Creating an Enum +---------------- - Base class for creating enumerated constants that are also - subclasses of :class:`str`. +Enumerations are created using the :keyword:`class` syntax, which makes them +easy to read and write. An alternative creation method is described in +`Functional API`_. To define an enumeration, subclass :class:`Enum` as +follows:: - :class:`Flag` + >>> from enum import Enum + >>> class Color(Enum): + ... RED = 1 + ... GREEN = 2 + ... BLUE = 3 + ... - Base class for creating enumerated constants that can be combined using - the bitwise operations without losing their :class:`Flag` membership. +.. note:: Enum member values - :class:`IntFlag` + Member values can be anything: :class:`int`, :class:`str`, etc.. If + the exact value is unimportant you may use :class:`auto` instances and an + appropriate value will be chosen for you. Care must be taken if you mix + :class:`auto` with other values. - Base class for creating enumerated constants that can be combined using - the bitwise operators without losing their :class:`IntFlag` membership. - :class:`IntFlag` members are also subclasses of :class:`int`. +.. note:: Nomenclature - :class:`FlagBoundary` + - The class :class:`Color` is an *enumeration* (or *enum*) + - The attributes :attr:`Color.RED`, :attr:`Color.GREEN`, etc., are + *enumeration members* (or *enum members*) and are functionally constants. + - The enum members have *names* and *values* (the name of + :attr:`Color.RED` is ``RED``, the value of :attr:`Color.BLUE` is + ``3``, etc.) - An enumeration with the values ``STRICT``, ``CONFORM``, ``EJECT``, and - ``KEEP`` which allows for more fine-grained control over how invalid values - are dealt with in an enumeration. +.. note:: - :class:`auto` + Even though we use the :keyword:`class` syntax to create Enums, Enums + are not normal Python classes. See `How are Enums different?`_ for + more details. - Instances are replaced with an appropriate value for Enum members. - :class:`StrEnum` defaults to the lower-cased version of the member name, - while other Enums default to 1 and increase from there. +Enumeration members have human readable string representations:: - :func:`global_enum` + >>> print(Color.RED) + Color.RED - :class:`Enum` class decorator to apply the appropriate global `__repr__`, - and export its members into the global name space. +...while their ``repr`` has more information:: - :func:`property` + >>> print(repr(Color.RED)) + - Allows :class:`Enum` members to have attributes without conflicting with - other members' names. +The *type* of an enumeration member is the enumeration it belongs to:: - :func:`unique` + >>> type(Color.RED) + + >>> isinstance(Color.GREEN, Color) + True + >>> - Enum class decorator that ensures only one name is bound to any one value. +Enum members also have a property that contains just their item name:: + >>> print(Color.RED.name) + RED -.. versionadded:: 3.6 ``Flag``, ``IntFlag``, ``auto`` -.. versionadded:: 3.10 ``StrEnum`` +Enumerations support iteration, in definition order:: + >>> class Shake(Enum): + ... VANILLA = 7 + ... CHOCOLATE = 4 + ... COOKIES = 9 + ... MINT = 3 + ... + >>> for shake in Shake: + ... print(shake) + ... + Shake.VANILLA + Shake.CHOCOLATE + Shake.COOKIES + Shake.MINT -Data Types ----------- +Enumeration members are hashable, so they can be used in dictionaries and sets:: + >>> apples = {} + >>> apples[Color.RED] = 'red delicious' + >>> apples[Color.GREEN] = 'granny smith' + >>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'} + True -.. class:: EnumType - *EnumType* is the :term:`metaclass` for *enum* enumerations. It is possible - to subclass *EnumType* -- see :ref:`Subclassing EnumType ` - for details. +Programmatic access to enumeration members and their attributes +--------------------------------------------------------------- - .. method:: EnumType.__contains__(cls, member) +Sometimes it's useful to access members in enumerations programmatically (i.e. +situations where ``Color.RED`` won't do because the exact color is not known +at program-writing time). ``Enum`` allows such access:: - Returns ``True`` if member belongs to the ``cls``:: + >>> Color(1) + + >>> Color(3) + - >>> some_var = Color.RED - >>> some_var in Color - True +If you want to access enum members by *name*, use item access:: - .. note:: + >>> Color['RED'] + + >>> Color['GREEN'] + - In Python 3.12 it will be possible to check for member values and not - just members; until then, a ``TypeError`` will be raised if a - non-Enum-member is used in a containment check. +If you have an enum member and need its :attr:`name` or :attr:`value`:: - .. method:: EnumType.__dir__(cls) + >>> member = Color.RED + >>> member.name + 'RED' + >>> member.value + 1 - Returns ``['__class__', '__doc__', '__members__', '__module__']`` and the - names of the members in *cls*:: - >>> dir(Color) - ['BLUE', 'GREEN', 'RED', '__class__', '__doc__', '__members__', '__module__'] +Duplicating enum members and values +----------------------------------- - .. method:: EnumType.__getattr__(cls, name) +Having two enum members with the same name is invalid:: - Returns the Enum member in *cls* matching *name*, or raises an :exc:`AttributeError`:: + >>> class Shape(Enum): + ... SQUARE = 2 + ... SQUARE = 3 + ... + Traceback (most recent call last): + ... + TypeError: Attempted to reuse key: 'SQUARE' - >>> Color.GREEN - Color.GREEN +However, two enum members are allowed to have the same value. Given two members +A and B with the same value (and A defined first), B is an alias to A. By-value +lookup of the value of A and B will return A. By-name lookup of B will also +return A:: - .. method:: EnumType.__getitem__(cls, name) + >>> class Shape(Enum): + ... SQUARE = 2 + ... DIAMOND = 1 + ... CIRCLE = 3 + ... ALIAS_FOR_SQUARE = 2 + ... + >>> Shape.SQUARE + + >>> Shape.ALIAS_FOR_SQUARE + + >>> Shape(2) + - Returns the Enum member in *cls* matching *name*, or raises an :exc:`KeyError`:: +.. note:: - >>> Color['BLUE'] - Color.BLUE + Attempting to create a member with the same name as an already + defined attribute (another member, a method, etc.) or attempting to create + an attribute with the same name as a member is not allowed. - .. method:: EnumType.__iter__(cls) - Returns each member in *cls* in definition order:: +Ensuring unique enumeration values +---------------------------------- - >>> list(Color) - [Color.RED, Color.GREEN, Color.BLUE] +By default, enumerations allow multiple names as aliases for the same value. +When this behavior isn't desired, the following decorator can be used to +ensure each value is used only once in the enumeration: - .. method:: EnumType.__len__(cls) +.. decorator:: unique - Returns the number of member in *cls*:: +A :keyword:`class` decorator specifically for enumerations. It searches an +enumeration's :attr:`__members__` gathering any aliases it finds; if any are +found :exc:`ValueError` is raised with the details:: + + >>> from enum import Enum, unique + >>> @unique + ... class Mistake(Enum): + ... ONE = 1 + ... TWO = 2 + ... THREE = 3 + ... FOUR = 3 + ... + Traceback (most recent call last): + ... + ValueError: duplicate values found in : FOUR -> THREE + + +Using automatic values +---------------------- + +If the exact value is unimportant you can use :class:`auto`:: + + >>> from enum import Enum, auto + >>> class Color(Enum): + ... RED = auto() + ... BLUE = auto() + ... GREEN = auto() + ... + >>> list(Color) + [, , ] + +The values are chosen by :func:`_generate_next_value_`, which can be +overridden:: + + >>> class AutoName(Enum): + ... def _generate_next_value_(name, start, count, last_values): + ... return name + ... + >>> class Ordinal(AutoName): + ... NORTH = auto() + ... SOUTH = auto() + ... EAST = auto() + ... WEST = auto() + ... + >>> list(Ordinal) + [, , , ] - >>> len(Color) - 3 +.. note:: - .. method:: EnumType.__reversed__(cls) + The goal of the default :meth:`_generate_next_value_` method is to provide + the next :class:`int` in sequence with the last :class:`int` provided, but + the way it does this is an implementation detail and may change. - Returns each member in *cls* in reverse definition order:: +.. note:: - >>> list(reversed(Color)) - [Color.BLUE, Color.GREEN, Color.RED] + The :meth:`_generate_next_value_` method must be defined before any members. +Iteration +--------- -.. class:: Enum +Iterating over the members of an enum does not provide the aliases:: + + >>> list(Shape) + [, , ] + +The special attribute ``__members__`` is a read-only ordered mapping of names +to members. It includes all names defined in the enumeration, including the +aliases:: + + >>> for name, member in Shape.__members__.items(): + ... name, member + ... + ('SQUARE', ) + ('DIAMOND', ) + ('CIRCLE', ) + ('ALIAS_FOR_SQUARE', ) - *Enum* is the base class for all *enum* enumerations. +The ``__members__`` attribute can be used for detailed programmatic access to +the enumeration members. For example, finding all the aliases:: - .. attribute:: Enum.name + >>> [name for name, member in Shape.__members__.items() if member.name != name] + ['ALIAS_FOR_SQUARE'] - The name used to define the ``Enum`` member:: - >>> Color.BLUE.name - 'BLUE' +Comparisons +----------- - .. attribute:: Enum.value +Enumeration members are compared by identity:: - The value given to the ``Enum`` member:: + >>> Color.RED is Color.RED + True + >>> Color.RED is Color.BLUE + False + >>> Color.RED is not Color.BLUE + True - >>> Color.RED.value - 1 +Ordered comparisons between enumeration values are *not* supported. Enum +members are not integers (but see `IntEnum`_ below):: + + >>> Color.RED < Color.BLUE + Traceback (most recent call last): + File "", line 1, in + TypeError: '<' not supported between instances of 'Color' and 'Color' + +Equality comparisons are defined though:: + + >>> Color.BLUE == Color.RED + False + >>> Color.BLUE != Color.RED + True + >>> Color.BLUE == Color.BLUE + True - .. note:: Enum member values +Comparisons against non-enumeration values will always compare not equal +(again, :class:`IntEnum` was explicitly designed to behave differently, see +below):: - Member values can be anything: :class:`int`, :class:`str`, etc.. If - the exact value is unimportant you may use :class:`auto` instances and an - appropriate value will be chosen for you. Care must be taken if you mix - :class:`auto` with other values. + >>> Color.BLUE == 2 + False - .. attribute:: Enum._ignore_ - ``_ignore_`` is only used during creation and is removed from the - enumeration once that is complete. +Allowed members and attributes of enumerations +---------------------------------------------- - ``_ignore_`` is a list of names that will not become members, and whose - names will also be removed from the completed enumeration. See - :ref:`TimePeriod ` for an example. +The examples above use integers for enumeration values. Using integers is +short and handy (and provided by default by the `Functional API`_), but not +strictly enforced. In the vast majority of use-cases, one doesn't care what +the actual value of an enumeration is. But if the value *is* important, +enumerations can have arbitrary values. - .. method:: Enum.__call__(cls, value, names=None, \*, module=None, qualname=None, type=None, start=1, boundary=None) +Enumerations are Python classes, and can have methods and special methods as +usual. If we have this enumeration:: - This method is called in two different ways: + >>> class Mood(Enum): + ... FUNKY = 1 + ... HAPPY = 3 + ... + ... def describe(self): + ... # self is the member here + ... return self.name, self.value + ... + ... def __str__(self): + ... return 'my custom str! {0}'.format(self.value) + ... + ... @classmethod + ... def favorite_mood(cls): + ... # cls here is the enumeration + ... return cls.HAPPY + ... - * to look up an existing member: +Then:: - :cls: The enum class being called. - :value: The value to lookup. - - * to use the ``cls`` enum to create a new enum: - - :cls: The enum class being called. - :value: The name of the new Enum to create. - :names: The names/values of the members for the new Enum. - :module: The name of the module the new Enum is created in. - :qualname: The actual location in the module where this Enum can be found. - :type: A mix-in type for the new Enum. - :start: The first integer value for the Enum (used by :class:`auto`) - :boundary: How to handle out-of-range values from bit operations (:class:`Flag` only) - - .. method:: Enum.__dir__(self) - - Returns ``['__class__', '__doc__', '__module__', 'name', 'value']`` and - any public methods defined on *self.__class__*:: - - >>> from datetime import date - >>> class Weekday(Enum): - ... MONDAY = 1 - ... TUESDAY = 2 - ... WEDNESDAY = 3 - ... THURSDAY = 4 - ... FRIDAY = 5 - ... SATURDAY = 6 - ... SUNDAY = 7 - ... @classmethod - ... def today(cls): - ... print('today is %s' % cls(date.today.isoweekday).naem) - >>> dir(Weekday.SATURDAY) - ['__class__', '__doc__', '__module__', 'name', 'today', 'value'] - - .. method:: Enum._generate_next_value_(name, start, count, last_values) - - :name: The name of the member being defined (e.g. 'RED'). - :start: The start value for the Enum; the default is 1. - :count: The number of members currently defined, not including this one. - :last_values: A list of the previous values. - - A *staticmethod* that is used to determine the next value returned by - :class:`auto`:: - - >>> from enum import auto - >>> class PowersOfThree(Enum): - ... @staticmethod - ... def _generate_next_value_(name, start, count, last_values): - ... return (count + 1) * 3 - ... FIRST = auto() - ... SECOND = auto() - >>> PowersOfThree.SECOND.value - 6 - - .. method:: Enum._missing_(cls, value) - - A *classmethod* for looking up values not found in *cls*. By default it - does nothing, but can be overridden to implement custom search behavior:: - - >>> from enum import StrEnum - >>> class Build(StrEnum): - ... DEBUG = auto() - ... OPTIMIZED = auto() - ... @classmethod - ... def _missing_(cls, value): - ... value = value.lower() - ... for member in cls: - ... if member.value == value: - ... return member - ... return None - >>> Build.DEBUG.value - 'debug' - >>> Build('deBUG') - Build.DEBUG - - .. method:: Enum.__repr__(self) - - Returns the string used for *repr()* calls. By default, returns the - *Enum* name and the member name, but can be overridden:: - - >>> class OldStyle(Enum): - ... RETRO = auto() - ... OLD_SCHOOl = auto() - ... YESTERYEAR = auto() - ... def __repr__(self): - ... cls_name = self.__class__.__name__ - ... return f'<{cls_name}.{self.name}: {self.value}>' - >>> OldStyle.RETRO - - - .. method:: Enum.__str__(self) - - Returns the string used for *str()* calls. By default, returns the - member name, but can be overridden:: - - >>> class OldStyle(Enum): - ... RETRO = auto() - ... OLD_SCHOOl = auto() - ... YESTERYEAR = auto() - ... def __str__(self): - ... cls_name = self.__class__.__name__ - ... return f'{cls_name}.{self.name}' - >>> OldStyle.RETRO - OldStyle.RETRO + >>> Mood.favorite_mood() + + >>> Mood.HAPPY.describe() + ('HAPPY', 3) + >>> str(Mood.FUNKY) + 'my custom str! 1' + +The rules for what is allowed are as follows: names that start and end with +a single underscore are reserved by enum and cannot be used; all other +attributes defined within an enumeration will become members of this +enumeration, with the exception of special methods (:meth:`__str__`, +:meth:`__add__`, etc.), descriptors (methods are also descriptors), and +variable names listed in :attr:`_ignore_`. + +Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then +any value(s) given to the enum member will be passed into those methods. +See `Planet`_ for an example. + + +Restricted Enum subclassing +--------------------------- + +A new :class:`Enum` class must have one base Enum class, up to one concrete +data type, and as many :class:`object`-based mixin classes as needed. The +order of these base classes is:: + + class EnumName([mix-in, ...,] [data-type,] base-enum): + pass + +Also, subclassing an enumeration is allowed only if the enumeration does not define +any members. So this is forbidden:: + + >>> class MoreColor(Color): + ... PINK = 17 + ... + Traceback (most recent call last): + ... + TypeError: MoreColor: cannot extend enumeration 'Color' + +But this is allowed:: + + >>> class Foo(Enum): + ... def some_behavior(self): + ... pass + ... + >>> class Bar(Foo): + ... HAPPY = 1 + ... SAD = 2 + ... + +Allowing subclassing of enums that define members would lead to a violation of +some important invariants of types and instances. On the other hand, it makes +sense to allow sharing some common behavior between a group of enumerations. +(See `OrderedEnum`_ for an example.) + + +Pickling +-------- + +Enumerations can be pickled and unpickled:: + + >>> from test.test_enum import Fruit + >>> from pickle import dumps, loads + >>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO)) + True + +The usual restrictions for pickling apply: picklable enums must be defined in +the top level of a module, since unpickling requires them to be importable +from that module. .. note:: - Using :class:`auto` with :class:`Enum` results in integers of increasing value, - starting with ``1``. + With pickle protocol version 4 it is possible to easily pickle enums + nested in other classes. +It is possible to modify how Enum members are pickled/unpickled by defining +:meth:`__reduce_ex__` in the enumeration class. -.. class:: IntEnum - *IntEnum* is the same as *Enum*, but its members are also integers and can be - used anywhere that an integer can be used. If any integer operation is performed - with an *IntEnum* member, the resulting value loses its enumeration status. - - >>> from enum import IntEnum - >>> class Numbers(IntEnum): - ... ONE = 1 - ... TWO = 2 - ... THREE = 3 - >>> Numbers.THREE - Numbers.THREE - >>> Numbers.ONE + Numbers.TWO - 3 - >>> Numbers.THREE + 5 - 8 - >>> Numbers.THREE == 3 - True +Functional API +-------------- -.. note:: +The :class:`Enum` class is callable, providing the following functional API:: - Using :class:`auto` with :class:`IntEnum` results in integers of increasing value, - starting with ``1``. + >>> Animal = Enum('Animal', 'ANT BEE CAT DOG') + >>> Animal + + >>> Animal.ANT + + >>> Animal.ANT.value + 1 + >>> list(Animal) + [, , , ] +The semantics of this API resemble :class:`~collections.namedtuple`. The first +argument of the call to :class:`Enum` is the name of the enumeration. -.. class:: StrEnum +The second argument is the *source* of enumeration member names. It can be a +whitespace-separated string of names, a sequence of names, a sequence of +2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to +values. The last two options enable assigning arbitrary values to +enumerations; the others auto-assign increasing integers starting with 1 (use +the ``start`` parameter to specify a different starting value). A +new class derived from :class:`Enum` is returned. In other words, the above +assignment to :class:`Animal` is equivalent to:: - *StrEnum* is the same as *Enum*, but its members are also strings and can be used - in most of the same places that a string can be used. The result of any string - operation performed on or with a *StrEnum* member is not part of the enumeration. + >>> class Animal(Enum): + ... ANT = 1 + ... BEE = 2 + ... CAT = 3 + ... DOG = 4 + ... - .. note:: There are places in the stdlib that check for an exact :class:`str` - instead of a :class:`str` subclass (i.e. ``type(unknown) == str`` - instead of ``isinstance(str, unknown)``), and in those locations you - will need to use ``str(StrEnum.member)``. +The reason for defaulting to ``1`` as the starting number and not ``0`` is +that ``0`` is ``False`` in a boolean sense, but enum members all evaluate +to ``True``. +Pickling enums created with the functional API can be tricky as frame stack +implementation details are used to try and figure out which module the +enumeration is being created in (e.g. it will fail if you use a utility +function in separate module, and also may not work on IronPython or Jython). +The solution is to specify the module name explicitly as follows:: -.. note:: + >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__) - Using :class:`auto` with :class:`StrEnum` results in values of the member name, - lower-cased. +.. warning:: + If ``module`` is not supplied, and Enum cannot determine what it is, + the new Enum members will not be unpicklable; to keep errors closer to + the source, pickling will be disabled. -.. class:: Flag +The new pickle protocol 4 also, in some circumstances, relies on +:attr:`~definition.__qualname__` being set to the location where pickle will be able +to find the class. For example, if the class was made available in class +SomeData in the global scope:: - *Flag* members support the bitwise operators ``&`` (*AND*), ``|`` (*OR*), - ``^`` (*XOR*), and ``~`` (*INVERT*); the results of those operators are members - of the enumeration. + >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal') - .. method:: __contains__(self, value) +The complete signature is:: - Returns *True* if value is in self:: + Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=, start=1) - >>> from enum import Flag, auto - >>> class Color(Flag): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> purple = Color.RED | Color.BLUE - >>> white = Color.RED | Color.GREEN | Color.BLUE - >>> Color.GREEN in purple - False - >>> Color.GREEN in white - True - >>> purple in white - True - >>> white in purple - False +:value: What the new Enum class will record as its name. - .. method:: __iter__(self): +:names: The Enum members. This can be a whitespace or comma separated string + (values will start at 1 unless otherwise specified):: - Returns all contained members:: + 'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE' - >>> list(Color.RED) - [Color.RED] - >>> list(purple) - [Color.RED, Color.BLUE] + or an iterator of names:: - .. method:: __len__(self): + ['RED', 'GREEN', 'BLUE'] - Returns number of members in flag:: + or an iterator of (name, value) pairs:: - >>> len(Color.GREEN) - 1 - >>> len(white) - 3 + [('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)] - .. method:: __bool__(self): + or a mapping:: - Returns *True* if any members in flag, *False* otherwise:: + {'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42} - >>> bool(Color.GREEN) - True - >>> bool(white) - True - >>> black = Color(0) - >>> bool(black) - False +:module: name of module where new Enum class can be found. - .. method:: __or__(self, other) +:qualname: where in module new Enum class can be found. - Returns current flag binary or'ed with other:: +:type: type to mix in to new Enum class. - >>> Color.RED | Color.GREEN - Color.RED|Color.GREEN +:start: number to start counting at if only names are passed in. - .. method:: __and__(self, other) +.. versionchanged:: 3.5 + The *start* parameter was added. - Returns current flag binary and'ed with other:: - >>> purple & white - Color.RED|Color.BLUE - >>> purple & Color.GREEN - 0x0 +Derived Enumerations +-------------------- - .. method:: __xor__(self, other) +IntEnum +^^^^^^^ - Returns current flag binary xor'ed with other:: +The first variation of :class:`Enum` that is provided is also a subclass of +:class:`int`. Members of an :class:`IntEnum` can be compared to integers; +by extension, integer enumerations of different types can also be compared +to each other:: - >>> purple ^ white - Color.GREEN - >>> purple ^ Color.GREEN - Color.RED|Color.GREEN|Color.BLUE + >>> from enum import IntEnum + >>> class Shape(IntEnum): + ... CIRCLE = 1 + ... SQUARE = 2 + ... + >>> class Request(IntEnum): + ... POST = 1 + ... GET = 2 + ... + >>> Shape == 1 + False + >>> Shape.CIRCLE == 1 + True + >>> Shape.CIRCLE == Request.POST + True - .. method:: __invert__(self): +However, they still can't be compared to standard :class:`Enum` enumerations:: - Returns all the flags in *type(self)* that are not in self:: + >>> class Shape(IntEnum): + ... CIRCLE = 1 + ... SQUARE = 2 + ... + >>> class Color(Enum): + ... RED = 1 + ... GREEN = 2 + ... + >>> Shape.CIRCLE == Color.RED + False - >>> ~white - 0x0 - >>> ~purple - Color.GREEN - >>> ~Color.RED - Color.GREEN|Color.BLUE +:class:`IntEnum` values behave like integers in other ways you'd expect:: -.. note:: + >>> int(Shape.CIRCLE) + 1 + >>> ['a', 'b', 'c'][Shape.CIRCLE] + 'b' + >>> [i for i in range(Shape.SQUARE)] + [0, 1] - Using :class:`auto` with :class:`Flag` results in integers that are powers - of two, starting with ``1``. +IntFlag +^^^^^^^ -.. class:: IntFlag +The next variation of :class:`Enum` provided, :class:`IntFlag`, is also based +on :class:`int`. The difference being :class:`IntFlag` members can be combined +using the bitwise operators (&, \|, ^, ~) and the result is still an +:class:`IntFlag` member. However, as the name implies, :class:`IntFlag` +members also subclass :class:`int` and can be used wherever an :class:`int` is +used. Any operation on an :class:`IntFlag` member besides the bit-wise +operations will lose the :class:`IntFlag` membership. - *IntFlag* is the same as *Flag*, but its members are also integers and can be - used anywhere that an integer can be used. +.. versionadded:: 3.6 - >>> from enum import IntFlag, auto - >>> class Color(IntFlag): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> Color.RED & 2 - 0x0 - >>> Color.RED | 2 - Color.RED|Color.GREEN +Sample :class:`IntFlag` class:: - If any integer operation is performed with an *IntFlag* member, the result is - not an *IntFlag*:: + >>> from enum import IntFlag + >>> class Perm(IntFlag): + ... R = 4 + ... W = 2 + ... X = 1 + ... + >>> Perm.R | Perm.W + + >>> Perm.R + Perm.W + 6 + >>> RW = Perm.R | Perm.W + >>> Perm.R in RW + True + +It is also possible to name the combinations:: + + >>> class Perm(IntFlag): + ... R = 4 + ... W = 2 + ... X = 1 + ... RWX = 7 + >>> Perm.RWX + + >>> ~Perm.RWX + + +Another important difference between :class:`IntFlag` and :class:`Enum` is that +if no flags are set (the value is 0), its boolean evaluation is :data:`False`:: + + >>> Perm.R & Perm.X + + >>> bool(Perm.R & Perm.X) + False + +Because :class:`IntFlag` members are also subclasses of :class:`int` they can +be combined with them:: + + >>> Perm.X | 8 + + + +Flag +^^^^ + +The last variation is :class:`Flag`. Like :class:`IntFlag`, :class:`Flag` +members can be combined using the bitwise operators (&, \|, ^, ~). Unlike +:class:`IntFlag`, they cannot be combined with, nor compared against, any +other :class:`Flag` enumeration, nor :class:`int`. While it is possible to +specify the values directly it is recommended to use :class:`auto` as the +value and let :class:`Flag` select an appropriate value. + +.. versionadded:: 3.6 + +Like :class:`IntFlag`, if a combination of :class:`Flag` members results in no +flags being set, the boolean evaluation is :data:`False`:: + + >>> from enum import Flag, auto + >>> class Color(Flag): + ... RED = auto() + ... BLUE = auto() + ... GREEN = auto() + ... + >>> Color.RED & Color.GREEN + + >>> bool(Color.RED & Color.GREEN) + False + +Individual flags should have values that are powers of two (1, 2, 4, 8, ...), +while combinations of flags won't:: + + >>> class Color(Flag): + ... RED = auto() + ... BLUE = auto() + ... GREEN = auto() + ... WHITE = RED | BLUE | GREEN + ... + >>> Color.WHITE + + +Giving a name to the "no flags set" condition does not change its boolean +value:: + + >>> class Color(Flag): + ... BLACK = 0 + ... RED = auto() + ... BLUE = auto() + ... GREEN = auto() + ... + >>> Color.BLACK + + >>> bool(Color.BLACK) + False + +.. note:: - >>> Color.RED + 2 - 3 + For the majority of new code, :class:`Enum` and :class:`Flag` are strongly + recommended, since :class:`IntEnum` and :class:`IntFlag` break some + semantic promises of an enumeration (by being comparable to integers, and + thus by transitivity to other unrelated enumerations). :class:`IntEnum` + and :class:`IntFlag` should be used only in cases where :class:`Enum` and + :class:`Flag` will not do; for example, when integer constants are replaced + with enumerations, or for interoperability with other systems. + + +Others +^^^^^^ + +While :class:`IntEnum` is part of the :mod:`enum` module, it would be very +simple to implement independently:: + + class IntEnum(int, Enum): + pass + +This demonstrates how similar derived enumerations can be defined; for example +a :class:`StrEnum` that mixes in :class:`str` instead of :class:`int`. + +Some rules: + +1. When subclassing :class:`Enum`, mix-in types must appear before + :class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum` + example above. +2. While :class:`Enum` can have members of any type, once you mix in an + additional type, all the members must have values of that type, e.g. + :class:`int` above. This restriction does not apply to mix-ins which only + add methods and don't specify another type. +3. When another data type is mixed in, the :attr:`value` attribute is *not the + same* as the enum member itself, although it is equivalent and will compare + equal. +4. %-style formatting: `%s` and `%r` call the :class:`Enum` class's + :meth:`__str__` and :meth:`__repr__` respectively; other codes (such as + `%i` or `%h` for IntEnum) treat the enum member as its mixed-in type. +5. :ref:`Formatted string literals `, :meth:`str.format`, + and :func:`format` will use the mixed-in type's :meth:`__format__` + unless :meth:`__str__` or :meth:`__format__` is overridden in the subclass, + in which case the overridden methods or :class:`Enum` methods will be used. + Use the !s and !r format codes to force usage of the :class:`Enum` class's + :meth:`__str__` and :meth:`__repr__` methods. + +When to use :meth:`__new__` vs. :meth:`__init__` +------------------------------------------------ + +:meth:`__new__` must be used whenever you want to customize the actual value of +the :class:`Enum` member. Any other modifications may go in either +:meth:`__new__` or :meth:`__init__`, with :meth:`__init__` being preferred. + +For example, if you want to pass several items to the constructor, but only +want one of them to be the value:: + + >>> class Coordinate(bytes, Enum): + ... """ + ... Coordinate with binary codes that can be indexed by the int code. + ... """ + ... def __new__(cls, value, label, unit): + ... obj = bytes.__new__(cls, [value]) + ... obj._value_ = value + ... obj.label = label + ... obj.unit = unit + ... return obj + ... PX = (0, 'P.X', 'km') + ... PY = (1, 'P.Y', 'km') + ... VX = (2, 'V.X', 'km/s') + ... VY = (3, 'V.Y', 'km/s') + ... + + >>> print(Coordinate['PY']) + Coordinate.PY + + >>> print(Coordinate(3)) + Coordinate.VY + +Interesting examples +-------------------- + +While :class:`Enum`, :class:`IntEnum`, :class:`IntFlag`, and :class:`Flag` are +expected to cover the majority of use-cases, they cannot cover them all. Here +are recipes for some different types of enumerations that can be used directly, +or as examples for creating one's own. + + +Omitting values +^^^^^^^^^^^^^^^ + +In many use-cases one doesn't care what the actual value of an enumeration +is. There are several ways to define this type of simple enumeration: + +- use instances of :class:`auto` for the value +- use instances of :class:`object` as the value +- use a descriptive string as the value +- use a tuple as the value and a custom :meth:`__new__` to replace the + tuple with an :class:`int` value + +Using any of these methods signifies to the user that these values are not +important, and also enables one to add, remove, or reorder members without +having to renumber the remaining members. + +Whichever method you choose, you should provide a :meth:`repr` that also hides +the (unimportant) value:: + + >>> class NoValue(Enum): + ... def __repr__(self): + ... return '<%s.%s>' % (self.__class__.__name__, self.name) + ... + + +Using :class:`auto` +""""""""""""""""""" + +Using :class:`auto` would look like:: + + >>> class Color(NoValue): + ... RED = auto() + ... BLUE = auto() + ... GREEN = auto() + ... + >>> Color.GREEN + + + +Using :class:`object` +""""""""""""""""""""" + +Using :class:`object` would look like:: + + >>> class Color(NoValue): + ... RED = object() + ... GREEN = object() + ... BLUE = object() + ... + >>> Color.GREEN + + + +Using a descriptive string +"""""""""""""""""""""""""" + +Using a string as the value would look like:: + + >>> class Color(NoValue): + ... RED = 'stop' + ... GREEN = 'go' + ... BLUE = 'too fast!' + ... + >>> Color.GREEN + + >>> Color.GREEN.value + 'go' + + +Using a custom :meth:`__new__` +"""""""""""""""""""""""""""""" + +Using an auto-numbering :meth:`__new__` would look like:: + + >>> class AutoNumber(NoValue): + ... def __new__(cls): + ... value = len(cls.__members__) + 1 + ... obj = object.__new__(cls) + ... obj._value_ = value + ... return obj + ... + >>> class Color(AutoNumber): + ... RED = () + ... GREEN = () + ... BLUE = () + ... + >>> Color.GREEN + + >>> Color.GREEN.value + 2 + +To make a more general purpose ``AutoNumber``, add ``*args`` to the signature:: + + >>> class AutoNumber(NoValue): + ... def __new__(cls, *args): # this is the only change from above + ... value = len(cls.__members__) + 1 + ... obj = object.__new__(cls) + ... obj._value_ = value + ... return obj + ... + +Then when you inherit from ``AutoNumber`` you can write your own ``__init__`` +to handle any extra arguments:: + + >>> class Swatch(AutoNumber): + ... def __init__(self, pantone='unknown'): + ... self.pantone = pantone + ... AUBURN = '3497' + ... SEA_GREEN = '1246' + ... BLEACHED_CORAL = () # New color, no Pantone code yet! + ... + >>> Swatch.SEA_GREEN + + >>> Swatch.SEA_GREEN.pantone + '1246' + >>> Swatch.BLEACHED_CORAL.pantone + 'unknown' - If a *Flag* operation is performed with an *IntFlag* member and: +.. note:: - * the result is a valid *IntFlag*: an *IntFlag* is returned - * the result is not a valid *IntFlag*: the result depends on the *FlagBoundary* setting + The :meth:`__new__` method, if defined, is used during creation of the Enum + members; it is then replaced by Enum's :meth:`__new__` which is used after + class creation for lookup of existing members. + + +OrderedEnum +^^^^^^^^^^^ + +An ordered enumeration that is not based on :class:`IntEnum` and so maintains +the normal :class:`Enum` invariants (such as not being comparable to other +enumerations):: + + >>> class OrderedEnum(Enum): + ... def __ge__(self, other): + ... if self.__class__ is other.__class__: + ... return self.value >= other.value + ... return NotImplemented + ... def __gt__(self, other): + ... if self.__class__ is other.__class__: + ... return self.value > other.value + ... return NotImplemented + ... def __le__(self, other): + ... if self.__class__ is other.__class__: + ... return self.value <= other.value + ... return NotImplemented + ... def __lt__(self, other): + ... if self.__class__ is other.__class__: + ... return self.value < other.value + ... return NotImplemented + ... + >>> class Grade(OrderedEnum): + ... A = 5 + ... B = 4 + ... C = 3 + ... D = 2 + ... F = 1 + ... + >>> Grade.C < Grade.A + True + + +DuplicateFreeEnum +^^^^^^^^^^^^^^^^^ + +Raises an error if a duplicate member name is found instead of creating an +alias:: + + >>> class DuplicateFreeEnum(Enum): + ... def __init__(self, *args): + ... cls = self.__class__ + ... if any(self.value == e.value for e in cls): + ... a = self.name + ... e = cls(self.value).name + ... raise ValueError( + ... "aliases not allowed in DuplicateFreeEnum: %r --> %r" + ... % (a, e)) + ... + >>> class Color(DuplicateFreeEnum): + ... RED = 1 + ... GREEN = 2 + ... BLUE = 3 + ... GRENE = 2 + ... + Traceback (most recent call last): + ... + ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN' .. note:: - Using :class:`auto` with :class:`IntFlag` results in integers that are powers - of two, starting with ``1``. + This is a useful example for subclassing Enum to add or change other + behaviors as well as disallowing aliases. If the only desired change is + disallowing aliases, the :func:`unique` decorator can be used instead. -.. class:: FlagBoundary - *FlagBoundary* controls how out-of-range values are handled in *Flag* and its - subclasses. +Planet +^^^^^^ - .. attribute:: STRICT +If :meth:`__new__` or :meth:`__init__` is defined the value of the enum member +will be passed to those methods:: + + >>> class Planet(Enum): + ... MERCURY = (3.303e+23, 2.4397e6) + ... VENUS = (4.869e+24, 6.0518e6) + ... EARTH = (5.976e+24, 6.37814e6) + ... MARS = (6.421e+23, 3.3972e6) + ... JUPITER = (1.9e+27, 7.1492e7) + ... SATURN = (5.688e+26, 6.0268e7) + ... URANUS = (8.686e+25, 2.5559e7) + ... NEPTUNE = (1.024e+26, 2.4746e7) + ... def __init__(self, mass, radius): + ... self.mass = mass # in kilograms + ... self.radius = radius # in meters + ... @property + ... def surface_gravity(self): + ... # universal gravitational constant (m3 kg-1 s-2) + ... G = 6.67300E-11 + ... return G * self.mass / (self.radius * self.radius) + ... + >>> Planet.EARTH.value + (5.976e+24, 6378140.0) + >>> Planet.EARTH.surface_gravity + 9.802652743337129 + + +TimePeriod +^^^^^^^^^^ + +An example to show the :attr:`_ignore_` attribute in use:: + + >>> from datetime import timedelta + >>> class Period(timedelta, Enum): + ... "different lengths of time" + ... _ignore_ = 'Period i' + ... Period = vars() + ... for i in range(367): + ... Period['day_%d' % i] = i + ... + >>> list(Period)[:2] + [, ] + >>> list(Period)[-2:] + [, ] + + +How are Enums different? +------------------------ + +Enums have a custom metaclass that affects many aspects of both derived Enum +classes and their instances (members). + + +Enum Classes +^^^^^^^^^^^^ + +The :class:`EnumMeta` metaclass is responsible for providing the +:meth:`__contains__`, :meth:`__dir__`, :meth:`__iter__` and other methods that +allow one to do things with an :class:`Enum` class that fail on a typical +class, such as `list(Color)` or `some_enum_var in Color`. :class:`EnumMeta` is +responsible for ensuring that various other methods on the final :class:`Enum` +class are correct (such as :meth:`__new__`, :meth:`__getnewargs__`, +:meth:`__str__` and :meth:`__repr__`). + + +Enum Members (aka instances) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most interesting thing about Enum members is that they are singletons. +:class:`EnumMeta` creates them all while it is creating the :class:`Enum` +class itself, and then puts a custom :meth:`__new__` in place to ensure +that no new ones are ever instantiated by returning only the existing +member instances. + + +Finer Points +^^^^^^^^^^^^ + +Supported ``__dunder__`` names +"""""""""""""""""""""""""""""" + +:attr:`__members__` is a read-only ordered mapping of ``member_name``:``member`` +items. It is only available on the class. + +:meth:`__new__`, if specified, must create and return the enum members; it is +also a very good idea to set the member's :attr:`_value_` appropriately. Once +all the members are created it is no longer used. + + +Supported ``_sunder_`` names +"""""""""""""""""""""""""""" + +- ``_name_`` -- name of the member +- ``_value_`` -- value of the member; can be set / modified in ``__new__`` + +- ``_missing_`` -- a lookup function used when a value is not found; may be + overridden +- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, + that will not be transformed into members, and will be removed from the final + class +- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent + (class attribute, removed during class creation) +- ``_generate_next_value_`` -- used by the `Functional API`_ and by + :class:`auto` to get an appropriate value for an enum member; may be + overridden + +.. versionadded:: 3.6 ``_missing_``, ``_order_``, ``_generate_next_value_`` +.. versionadded:: 3.7 ``_ignore_`` + +To help keep Python 2 / Python 3 code in sync an :attr:`_order_` attribute can +be provided. It will be checked against the actual order of the enumeration +and raise an error if the two do not match:: + + >>> class Color(Enum): + ... _order_ = 'RED GREEN BLUE' + ... RED = 1 + ... BLUE = 3 + ... GREEN = 2 + ... + Traceback (most recent call last): + ... + TypeError: member order does not match _order_ - Out-of-range values cause a :exc:`ValueError` to be raised. This is the - default for :class:`Flag`:: +.. note:: - >>> from enum import Flag, STRICT - >>> class StrictFlag(Flag, boundary=STRICT): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> StrictFlag(2**2 + 2**4) - Traceback (most recent call last): - ... - ValueError: StrictFlag: invalid value: 20 - given 0b0 10100 - allowed 0b0 00111 + In Python 2 code the :attr:`_order_` attribute is necessary as definition + order is lost before it can be recorded. - .. attribute:: CONFORM - Out-of-range values have invalid values removed, leaving a valid *Flag* - value:: +_Private__names +""""""""""""""" - >>> from enum import Flag, CONFORM - >>> class ConformFlag(Flag, boundary=CONFORM): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> ConformFlag(2**2 + 2**4) - ConformFlag.BLUE +:ref:`Private names ` will be normal attributes in Python +3.11 instead of either an error or a member (depending on if the name ends with +an underscore). Using these names in 3.10 will issue a :exc:`DeprecationWarning`. - .. attribute:: EJECT - Out-of-range values lose their *Flag* membership and revert to :class:`int`. - This is the default for :class:`IntFlag`:: +``Enum`` member type +"""""""""""""""""""" - >>> from enum import Flag, EJECT - >>> class EjectFlag(Flag, boundary=EJECT): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> EjectFlag(2**2 + 2**4) - 20 +:class:`Enum` members are instances of their :class:`Enum` class, and are +normally accessed as ``EnumClass.member``. Under certain circumstances they +can also be accessed as ``EnumClass.member.member``, but you should never do +this as that lookup may fail or, worse, return something besides the +:class:`Enum` member you are looking for (this is another good reason to use +all-uppercase names for members):: - .. attribute:: KEEP + >>> class FieldTypes(Enum): + ... name = 0 + ... value = 1 + ... size = 2 + ... + >>> FieldTypes.value.size + + >>> FieldTypes.size.value + 2 - Out-of-range values are kept, and the *Flag* membership is kept. This is - used for some stdlib flags: +.. note:: - >>> from enum import Flag, KEEP - >>> class KeepFlag(Flag, boundary=KEEP): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> KeepFlag(2**2 + 2**4) - KeepFlag.BLUE|0x10 + This behavior is deprecated and will be removed in 3.11. +.. versionchanged:: 3.5 -Utilites and Decorators ------------------------ -.. class:: auto +Boolean value of ``Enum`` classes and members +""""""""""""""""""""""""""""""""""""""""""""" - *auto* can be used in place of a value. If used, the *Enum* machinery will - call an *Enum*'s :meth:`_generate_next_value_` to get an appropriate value. - For *Enum* and *IntEnum* that appropriate value will be the last value plus - one; for *Flag* and *IntFlag* it will be the first power-of-two greater - than the last value; for *StrEnum* it will be the lower-cased version of the - member's name. +:class:`Enum` members that are mixed with non-:class:`Enum` types (such as +:class:`int`, :class:`str`, etc.) are evaluated according to the mixed-in +type's rules; otherwise, all members evaluate as :data:`True`. To make your +own Enum's boolean evaluation depend on the member's value add the following to +your class:: - ``_generate_next_value_`` can be overridden to customize the values used by - *auto*. + def __bool__(self): + return bool(self.value) -.. decorator:: global_enum +:class:`Enum` classes always evaluate as :data:`True`. - A :keyword:`class` decorator specifically for enumerations. It replaces the - :meth:`__repr__` method with one that shows *module_name*.*member_name*. It - also injects the members, and their aliases, into the the global namespace - they were defined in. +``Enum`` classes with methods +""""""""""""""""""""""""""""" -.. decorator:: property +If you give your :class:`Enum` subclass extra methods, like the `Planet`_ +class above, those methods will show up in a :func:`dir` of the member, +but not of the class:: - A decorator similar to the built-in *property*, but specifically for - enumerations. It allows member attributes to have the same names as members - themselves. + >>> dir(Planet) + ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__'] + >>> dir(Planet.EARTH) + ['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value'] - .. note:: the *property* and the member must be defined in separate classes; - for example, the *value* and *name* attributes are defined in the - *Enum* class, and *Enum* subclasses can define members with the - names ``value`` and ``name``. -.. decorator:: unique +Combining members of ``Flag`` +""""""""""""""""""""""""""""" + +If a combination of Flag members is not named, the :func:`repr` will include +all named flags and all named combinations of flags that are in the value:: + + >>> class Color(Flag): + ... RED = auto() + ... GREEN = auto() + ... BLUE = auto() + ... MAGENTA = RED | BLUE + ... YELLOW = RED | GREEN + ... CYAN = GREEN | BLUE + ... + >>> Color(3) # named combination + + >>> Color(7) # not named combination + + +.. note:: + + In 3.11 unnamed combinations of flags will only produce the canonical flag + members (aka single-value flags). So ``Color(7)`` will produce something + like ````. - A :keyword:`class` decorator specifically for enumerations. It searches an - enumeration's :attr:`__members__`, gathering any aliases it finds; if any are - found :exc:`ValueError` is raised with the details:: - - >>> from enum import Enum, unique - >>> @unique - ... class Mistake(Enum): - ... ONE = 1 - ... TWO = 2 - ... THREE = 3 - ... FOUR = 3 - ... - Traceback (most recent call last): - ... - ValueError: duplicate values found in : FOUR -> THREE diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index c83daae302c19d..f8a692e8127913 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -34,6 +34,10 @@ class or one of its subclasses, and not from :exc:`BaseException`. More information on defining exceptions is available in the Python Tutorial under :ref:`tut-userexceptions`. + +Exception context +----------------- + When raising (or re-raising) an exception in an :keyword:`except` or :keyword:`finally` clause :attr:`__context__` is automatically set to the last exception caught; if the @@ -67,6 +71,25 @@ exceptions so that the final line of the traceback always shows the last exception that was raised. +Inheriting from built-in exceptions +----------------------------------- + +User code can create subclasses that inherit from an exception type. +It's recommended to only subclass one exception type at a time to avoid +any possible conflicts between how the bases handle the ``args`` +attribute, as well as due to possible memory layout incompatibilities. + +.. impl-detail:: + + Most built-in exceptions are implemented in C for efficiency, see: + :source:`Objects/exceptions.c`. Some have custom memory layouts + which makes it impossible to create a subclass that inherits from + multiple exception types. The memory layout of a type is an implementation + detail and might change between Python versions, leading to new + conflicts in the future. Therefore, it's recommended to avoid + subclassing multiple exception types altogether. + + Base classes ------------ @@ -96,7 +119,7 @@ The following exceptions are used mostly as base classes for other exceptions. instance of ``OtherException`` while preserving the traceback. Once raised, the current frame is pushed onto the traceback of the ``OtherException``, as would have happened to the traceback of the - original ``SomeException`` had we allowed it to propagate to the caller. + original ``SomeException`` had we allowed it to propagate to the caller. :: try: ... @@ -409,14 +432,16 @@ The following exceptions are the exceptions that are usually raised. .. versionadded:: 3.5 -.. exception:: SyntaxError +.. exception:: SyntaxError(message, details) Raised when the parser encounters a syntax error. This may occur in an - :keyword:`import` statement, in a call to the built-in functions :func:`exec` + :keyword:`import` statement, in a call to the built-in functions + :func:`compile`, :func:`exec`, or :func:`eval`, or when reading the initial script or standard input (also interactively). The :func:`str` of the exception instance returns only the error message. + Details is a tuple whose members are also available as separate attributes. .. attribute:: filename @@ -446,6 +471,11 @@ The following exceptions are the exceptions that are usually raised. The column in the end line where the error occurred finishes. This is 1-indexed: the first character in the line has an ``offset`` of 1. + For errors in f-string fields, the message is prefixed by "f-string: " + and the offsets are offsets in a text constructed from the replacement + expression. For example, compiling f'Bad {a b} field' results in this + args attribute: ('f-string: ...', ('', 1, 2, '(a b)\n', 1, 5)). + .. versionchanged:: 3.10 Added the :attr:`end_lineno` and :attr:`end_offset` attributes. @@ -683,8 +713,10 @@ depending on the system error code. .. exception:: NotADirectoryError - Raised when a directory operation (such as :func:`os.listdir`) is requested - on something which is not a directory. + Raised when a directory operation (such as :func:`os.listdir`) is requested on + something which is not a directory. On most POSIX platforms, it may also be + raised if an operation attempts to open or traverse a non-directory file as if + it were a directory. Corresponds to :c:data:`errno` ``ENOTDIR``. .. exception:: PermissionError @@ -739,6 +771,8 @@ The following exceptions are used as warning categories; see the (:pep:`565`). Enabling the :ref:`Python Development Mode ` shows this warning. + The deprecation policy is described in :pep:`387`. + .. exception:: PendingDeprecationWarning @@ -753,6 +787,8 @@ The following exceptions are used as warning categories; see the Ignored by the default warning filters. Enabling the :ref:`Python Development Mode ` shows this warning. + The deprecation policy is described in :pep:`387`. + .. exception:: SyntaxWarning diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst index 59274c1dd7ec35..be0912376bd8ef 100644 --- a/Doc/library/faulthandler.rst +++ b/Doc/library/faulthandler.rst @@ -76,6 +76,10 @@ Fault handler state .. versionchanged:: 3.6 On Windows, a handler for Windows exception is also installed. + .. versionchanged:: 3.10 + The dump now mentions if a garbage collector collection is running + if *all_threads* is true. + .. function:: disable() Disable the fault handler: uninstall the signal handlers installed by diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst index c60603b30a6d7d..83e9e14ddcacd8 100644 --- a/Doc/library/filecmp.rst +++ b/Doc/library/filecmp.rst @@ -22,8 +22,11 @@ The :mod:`filecmp` module defines the following functions: Compare the files named *f1* and *f2*, returning ``True`` if they seem equal, ``False`` otherwise. - If *shallow* is true, files with identical :func:`os.stat` signatures are - taken to be equal. Otherwise, the contents of the files are compared. + If *shallow* is true and the :func:`os.stat` signatures (file type, size, and + modification time) of both files are identical, the files are taken to be + equal. + + Otherwise, the files are treated as different if their sizes or contents differ. Note that no external programs are called from this function, giving it portability and efficiency. diff --git a/Doc/library/fileinput.rst b/Doc/library/fileinput.rst index 819640045cadf7..19cf7c67754f6e 100644 --- a/Doc/library/fileinput.rst +++ b/Doc/library/fileinput.rst @@ -50,8 +50,8 @@ You can control how files are opened by providing an opening hook via the *openhook* parameter to :func:`fileinput.input` or :class:`FileInput()`. The hook must be a function that takes two arguments, *filename* and *mode*, and returns an accordingly opened file-like object. If *encoding* and/or *errors* -are specified, they will be passed to the hook as aditional keyword arguments. -This module provides a :func:`hook_encoded` to support compressed files. +are specified, they will be passed to the hook as additional keyword arguments. +This module provides a :func:`hook_compressed` to support compressed files. The following function is the primary interface of this module: @@ -205,7 +205,7 @@ The two following opening hooks are provided by this module: modules. If the filename extension is not ``'.gz'`` or ``'.bz2'``, the file is opened normally (ie, using :func:`open` without any decompression). - The *encoding* and *errors* values are passed to to :class:`io.TextIOWrapper` + The *encoding* and *errors* values are passed to :class:`io.TextIOWrapper` for compressed files and open for normal files. Usage example: ``fi = fileinput.FileInput(openhook=fileinput.hook_compressed, encoding="utf-8")`` diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index f4d4cdf9ada9d9..2f94ac499285db 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -17,7 +17,7 @@ This module defines the class :class:`FTP` and a few related items. The this to write Python programs that perform a variety of automated FTP jobs, such as mirroring other FTP servers. It is also used by the module :mod:`urllib.request` to handle URLs that use FTP. For more information on FTP -(File Transfer Protocol), see Internet :rfc:`959`. +(File Transfer Protocol), see internet :rfc:`959`. The default encoding is UTF-8, following :rfc:`2640`. @@ -28,6 +28,7 @@ Here's a sample session using the :mod:`ftplib` module:: >>> ftp.login() # user anonymous, passwd anonymous@ '230 Login successful.' >>> ftp.cwd('debian') # change into "debian" directory + '250 Directory successfully changed.' >>> ftp.retrlines('LIST') # list directory contents -rw-rw-r-- 1 1176 1176 1063 Jun 15 10:18 README ... @@ -39,6 +40,7 @@ Here's a sample session using the :mod:`ftplib` module:: >>> ftp.retrbinary('RETR README', fp.write) '226 Transfer complete.' >>> ftp.quit() + '221 Goodbye.' The module defines the following items: diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 7d8a669f9e16d4..9a9c87e32013c8 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -66,9 +66,6 @@ are always available. They are listed here in alphabetical order. Return an :term:`asynchronous iterator` for an :term:`asynchronous iterable`. Equivalent to calling ``x.__aiter__()``. - ``aiter(x)`` itself has an ``__aiter__()`` method that returns ``x``, - so ``aiter(aiter(x))`` is the same as ``aiter(x)``. - Note: Unlike :func:`iter`, :func:`aiter` has no 2-argument variant. .. versionadded:: 3.10 @@ -116,7 +113,7 @@ are always available. They are listed here in alphabetical order. As :func:`repr`, return a string containing a printable representation of an object, but escape the non-ASCII characters in the string returned by - :func:`repr` using ``\x``, ``\u`` or ``\U`` escapes. This generates a string + :func:`repr` using ``\x``, ``\u``, or ``\U`` escapes. This generates a string similar to that returned by :func:`repr` in Python 2. @@ -132,7 +129,7 @@ are always available. They are listed here in alphabetical order. >>> bin(-10) '-0b1010' - If prefix "0b" is desired or not, you can use either of the following ways. + If the prefix "0b" is desired or not, you can use either of the following ways. >>> format(14, '#b'), format(14, 'b') ('0b1110', '1110') @@ -146,7 +143,7 @@ are always available. They are listed here in alphabetical order. Return a Boolean value, i.e. one of ``True`` or ``False``. *x* is converted using the standard :ref:`truth testing procedure `. If *x* is false - or omitted, this returns ``False``; otherwise it returns ``True``. The + or omitted, this returns ``False``; otherwise, it returns ``True``. The :class:`bool` class is a subclass of :class:`int` (see :ref:`typesnumeric`). It cannot be subclassed further. Its only instances are ``False`` and ``True`` (see :ref:`bltin-boolean-values`). @@ -206,7 +203,7 @@ are always available. They are listed here in alphabetical order. .. class:: bytes([source[, encoding[, errors]]]) :noindex: - Return a new "bytes" object, which is an immutable sequence of integers in + Return a new "bytes" object which is an immutable sequence of integers in the range ``0 <= x < 256``. :class:`bytes` is an immutable version of :class:`bytearray` -- it has the same non-mutating methods and the same indexing and slicing behavior. @@ -245,7 +242,7 @@ are always available. They are listed here in alphabetical order. Transform a method into a class method. - A class method receives the class as implicit first argument, just like an + A class method receives the class as an implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom:: @@ -342,7 +339,7 @@ are always available. They are listed here in alphabetical order. object due to stack depth limitations in Python's AST compiler. .. versionchanged:: 3.2 - Allowed use of Windows and Mac newlines. Also input in ``'exec'`` mode + Allowed use of Windows and Mac newlines. Also, input in ``'exec'`` mode does not have to end in a newline anymore. Added the *optimize* parameter. .. versionchanged:: 3.5 @@ -420,7 +417,7 @@ are always available. They are listed here in alphabetical order. If the object does not provide :meth:`__dir__`, the function tries its best to gather information from the object's :attr:`~object.__dict__` attribute, if defined, and - from its type object. The resulting list is not necessarily complete, and may + from its type object. The resulting list is not necessarily complete and may be inaccurate when the object has a custom :func:`__getattr__`. The default :func:`dir` mechanism behaves differently with different types of @@ -466,7 +463,7 @@ are always available. They are listed here in alphabetical order. .. function:: divmod(a, b) - Take two (non complex) numbers as arguments and return a pair of numbers + Take two (non-complex) numbers as arguments and return a pair of numbers consisting of their quotient and remainder when using integer division. With mixed operand types, the rules for binary arithmetic operators apply. For integers, the result is the same as ``(a // b, a % b)``. For floating point @@ -528,13 +525,13 @@ are always available. They are listed here in alphabetical order. 2 This function can also be used to execute arbitrary code objects (such as - those created by :func:`compile`). In this case pass a code object instead + those created by :func:`compile`). In this case, pass a code object instead of a string. If the code object has been compiled with ``'exec'`` as the *mode* argument, :func:`eval`\'s return value will be ``None``. Hints: dynamic execution of statements is supported by the :func:`exec` function. The :func:`globals` and :func:`locals` functions - returns the current global and local dictionary, respectively, which may be + return the current global and local dictionary, respectively, which may be useful to pass around for use by :func:`eval` or :func:`exec`. If the given source is a string, then leading and trailing spaces and tabs @@ -557,7 +554,7 @@ are always available. They are listed here in alphabetical order. a suite of Python statements which is then executed (unless a syntax error occurs). [#]_ If it is a code object, it is simply executed. In all cases, the code that's executed is expected to be valid as file input (see the - section "File input" in the Reference Manual). Be aware that the + section :ref:`file-input` in the Reference Manual). Be aware that the :keyword:`nonlocal`, :keyword:`yield`, and :keyword:`return` statements may not be used outside of function definitions even within the context of code passed to the @@ -569,7 +566,7 @@ are always available. They are listed here in alphabetical order. will be used for both the global and the local variables. If *globals* and *locals* are given, they are used for the global and local variables, respectively. If provided, *locals* can be any mapping object. Remember - that at module level, globals and locals are the same dictionary. If exec + that at the module level, globals and locals are the same dictionary. If exec gets two separate objects as *globals* and *locals*, the code will be executed as if it were embedded in a class definition. @@ -627,7 +624,7 @@ are always available. They are listed here in alphabetical order. preceded by a sign, and optionally embedded in whitespace. The optional sign may be ``'+'`` or ``'-'``; a ``'+'`` sign has no effect on the value produced. The argument may also be a string representing a NaN - (not-a-number), or a positive or negative infinity. More precisely, the + (not-a-number), or positive or negative infinity. More precisely, the input must conform to the following grammar after leading and trailing whitespace characters are removed: @@ -640,7 +637,7 @@ are always available. They are listed here in alphabetical order. Here ``floatnumber`` is the form of a Python floating-point literal, described in :ref:`floating`. Case is not significant, so, for example, - "inf", "Inf", "INFINITY" and "iNfINity" are all acceptable spellings for + "inf", "Inf", "INFINITY", and "iNfINity" are all acceptable spellings for positive infinity. Otherwise, if the argument is an integer or a floating point number, a @@ -687,7 +684,7 @@ are always available. They are listed here in alphabetical order. Convert a *value* to a "formatted" representation, as controlled by *format_spec*. The interpretation of *format_spec* will depend on the type - of the *value* argument, however there is a standard formatting syntax that + of the *value* argument; however, there is a standard formatting syntax that is used by most built-in types: :ref:`formatspec`. The default *format_spec* is an empty string which usually gives the same @@ -736,9 +733,9 @@ are always available. They are listed here in alphabetical order. .. function:: globals() - Return a dictionary representing the current global symbol table. This is always - the dictionary of the current module (inside a function or method, this is the - module where it is defined, not the module from which it is called). + Return the dictionary implementing the current module namespace. For code within + functions, this is set when the function is defined and remains the same + regardless of where the function is called. .. function:: hasattr(object, name) @@ -771,7 +768,7 @@ are always available. They are listed here in alphabetical order. topic, and a help page is printed on the console. If the argument is any other kind of object, a help page on the object is generated. - Note that if a slash(/) appears in the parameter list of a function, when + Note that if a slash(/) appears in the parameter list of a function when invoking :func:`help`, it means that the parameters prior to the slash are positional-only. For more info, see :ref:`the FAQ entry on positional-only parameters `. @@ -898,7 +895,7 @@ are always available. They are listed here in alphabetical order. .. function:: isinstance(object, classinfo) Return ``True`` if the *object* argument is an instance of the *classinfo* - argument, or of a (direct, indirect or :term:`virtual `) subclass thereof. If *object* is not an object of the given type, the function always returns ``False``. If *classinfo* is a tuple of type objects (or recursively, other such @@ -913,12 +910,12 @@ are always available. They are listed here in alphabetical order. .. function:: issubclass(class, classinfo) - Return ``True`` if *class* is a subclass (direct, indirect or :term:`virtual + Return ``True`` if *class* is a subclass (direct, indirect, or :term:`virtual `) of *classinfo*. A class is considered a subclass of itself. *classinfo* may be a tuple of class - objects or a :ref:`types-union`, in which case every entry in *classinfo* - will be checked. In any other - case, a :exc:`TypeError` exception is raised. + objects or a :ref:`types-union`, in which case return ``True`` if *class* is a + subclass of any entry in *classinfo*. In any other case, a :exc:`TypeError` + exception is raised. .. versionchanged:: 3.10 *classinfo* can be a :ref:`types-union`. @@ -929,8 +926,8 @@ are always available. They are listed here in alphabetical order. Return an :term:`iterator` object. The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, *object* must be a collection object which supports the - iteration protocol (the :meth:`__iter__` method), or it must support the - sequence protocol (the :meth:`__getitem__` method with integer arguments + :term:`iterable` protocol (the :meth:`__iter__` method), or it must support + the sequence protocol (the :meth:`__getitem__` method with integer arguments starting at ``0``). If it does not support either of those protocols, :exc:`TypeError` is raised. If the second argument, *sentinel*, is given, then *object* must be a callable object. The iterator created in this case @@ -1022,7 +1019,7 @@ are always available. They are listed here in alphabetical order. .. _func-memoryview: -.. class:: memoryview(obj) +.. class:: memoryview(object) :noindex: Return a "memory view" object created from the given argument. See @@ -1060,7 +1057,7 @@ are always available. They are listed here in alphabetical order. .. function:: next(iterator[, default]) - Retrieve the next item from the *iterator* by calling its + Retrieve the next item from the :term:`iterator` by calling its :meth:`~iterator.__next__` method. If *default* is given, it is returned if the iterator is exhausted, otherwise :exc:`StopIteration` is raised. @@ -1068,7 +1065,7 @@ are always available. They are listed here in alphabetical order. .. class:: object() Return a new featureless object. :class:`object` is a base for all classes. - It has the methods that are common to all instances of Python classes. This + It has methods that are common to all instances of Python classes. This function does not accept any arguments. .. note:: @@ -1089,7 +1086,7 @@ are always available. They are listed here in alphabetical order. >>> oct(-56) '-0o70' - If you want to convert an integer number to octal string either with prefix + If you want to convert an integer number to an octal string either with the prefix "0o" or not, you can use either of the following ways. >>> '%#o' % 10, '%o' % 10 @@ -1113,16 +1110,16 @@ are always available. They are listed here in alphabetical order. *file* is a :term:`path-like object` giving the pathname (absolute or relative to the current working directory) of the file to be opened or an integer file descriptor of the file to be wrapped. (If a file descriptor is - given, it is closed when the returned I/O object is closed, unless *closefd* + given, it is closed when the returned I/O object is closed unless *closefd* is set to ``False``.) *mode* is an optional string that specifies the mode in which the file is opened. It defaults to ``'r'`` which means open for reading in text mode. Other common values are ``'w'`` for writing (truncating the file if it - already exists), ``'x'`` for exclusive creation and ``'a'`` for appending + already exists), ``'x'`` for exclusive creation, and ``'a'`` for appending (which on *some* Unix systems, means that *all* writes append to the end of the file regardless of the current seek position). In text mode, if - *encoding* is not specified the encoding used is platform dependent: + *encoding* is not specified the encoding used is platform-dependent: ``locale.getpreferredencoding(False)`` is called to get the current locale encoding. (For reading and writing raw bytes use binary mode and leave *encoding* unspecified.) The available modes are: @@ -1138,13 +1135,13 @@ are always available. They are listed here in alphabetical order. ``'r'`` open for reading (default) ``'w'`` open for writing, truncating the file first ``'x'`` open for exclusive creation, failing if the file already exists - ``'a'`` open for writing, appending to the end of the file if it exists + ``'a'`` open for writing, appending to the end of file if it exists ``'b'`` binary mode ``'t'`` text mode (default) ``'+'`` open for updating (reading and writing) ========= =============================================================== - The default mode is ``'r'`` (open for reading text, synonym of ``'rt'``). + The default mode is ``'r'`` (open for reading text, a synonym of ``'rt'``). Modes ``'w+'`` and ``'w+b'`` open and truncate the file. Modes ``'r+'`` and ``'r+b'`` open the file with no truncation. @@ -1158,7 +1155,7 @@ are always available. They are listed here in alphabetical order. There is an additional mode character permitted, ``'U'``, which no longer has any effect, and is considered deprecated. It previously enabled - :term:`universal newlines` in text mode, which became the default behaviour + :term:`universal newlines` in text mode, which became the default behavior in Python 3.0. Refer to the documentation of the :ref:`newline ` parameter for further details. @@ -1208,9 +1205,9 @@ are always available. They are listed here in alphabetical order. * ``'replace'`` causes a replacement marker (such as ``'?'``) to be inserted where there is malformed data. - * ``'surrogateescape'`` will represent any incorrect bytes as code - points in the Unicode Private Use Area ranging from U+DC80 to - U+DCFF. These private code points will then be turned back into + * ``'surrogateescape'`` will represent any incorrect bytes as low + surrogate code units ranging from U+DC80 to U+DCFF. + These surrogate code units will then be turned back into the same bytes when the ``surrogateescape`` error handler is used when writing data. This is useful for processing files in an unknown encoding. @@ -1250,8 +1247,8 @@ are always available. They are listed here in alphabetical order. If *closefd* is ``False`` and a file descriptor rather than a filename was given, the underlying file descriptor will be kept open when the file is - closed. If a filename is given *closefd* must be ``True`` (the default) - otherwise an error will be raised. + closed. If a filename is given *closefd* must be ``True`` (the default); + otherwise, an error will be raised. 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 @@ -1295,7 +1292,7 @@ are always available. They are listed here in alphabetical order. single: text mode module: sys - See also the file handling modules, such as, :mod:`fileinput`, :mod:`io` + See also the file handling modules, such as :mod:`fileinput`, :mod:`io` (where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`, and :mod:`shutil`. @@ -1356,8 +1353,11 @@ are always available. They are listed here in alphabetical order. coercion rules for binary arithmetic operators apply. For :class:`int` operands, the result has the same type as the operands (after coercion) unless the second argument is negative; in that case, all arguments are - converted to float and a float result is delivered. For example, ``10**2`` - returns ``100``, but ``10**-2`` returns ``0.01``. + converted to float and a float result is delivered. For example, ``pow(10, 2)`` + returns ``100``, but ``pow(10, -2)`` returns ``0.01``. For a negative base of + type :class:`int` or :class:`float` and a non-integral exponent, a complex + result is delivered. For example, ``pow(-9, 0.5)`` returns a value close + to ``3j``. For :class:`int` operands *base* and *exp*, if *mod* is present, *mod* must also be of integer type and *mod* must be nonzero. If *mod* is present and @@ -1385,7 +1385,7 @@ are always available. They are listed here in alphabetical order. .. function:: print(*objects, sep=' ', end='\\n', file=sys.stdout, flush=False) Print *objects* to the text stream *file*, separated by *sep* and followed - by *end*. *sep*, *end*, *file* and *flush*, if present, must be given as keyword + by *end*. *sep*, *end*, *file*, and *flush*, if present, must be given as keyword arguments. All non-keyword arguments are converted to strings like :func:`str` does and @@ -1399,7 +1399,7 @@ are always available. They are listed here in alphabetical order. arguments are converted to text strings, :func:`print` cannot be used with binary mode file objects. For these, use ``file.write(...)`` instead. - Whether output is buffered is usually determined by *file*, but if the + Whether the output is buffered is usually determined by *file*, but if the *flush* keyword argument is true, the stream is forcibly flushed. .. versionchanged:: 3.3 @@ -1432,7 +1432,7 @@ are always available. They are listed here in alphabetical order. x = property(getx, setx, delx, "I'm the 'x' property.") If *c* is an instance of *C*, ``c.x`` will invoke the getter, - ``c.x = value`` will invoke the setter and ``del c.x`` the deleter. + ``c.x = value`` will invoke the setter, and ``del c.x`` the deleter. 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 @@ -1497,7 +1497,7 @@ are always available. They are listed here in alphabetical order. Return a string containing a printable representation of an object. For many types, this function makes an attempt to return a string that would yield an - object with the same value when passed to :func:`eval`, otherwise the + object with the same value when passed to :func:`eval`; otherwise, the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this @@ -1525,7 +1525,7 @@ are always available. They are listed here in alphabetical order. ``2``). Any integer value is valid for *ndigits* (positive, zero, or negative). The return value is an integer if *ndigits* is omitted or ``None``. - Otherwise the return value has the same type as *number*. + Otherwise, the return value has the same type as *number*. For a general Python object ``number``, ``round`` delegates to ``number.__round__``. @@ -1555,7 +1555,7 @@ are always available. They are listed here in alphabetical order. .. function:: setattr(object, name, value) This is the counterpart of :func:`getattr`. The arguments are an object, a - string and an arbitrary value. The string may name an existing attribute or a + string, and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it. For example, ``setattr(x, 'foobar', 123)`` is equivalent to ``x.foobar = 123``. @@ -1574,15 +1574,15 @@ are always available. They are listed here in alphabetical order. Return a :term:`slice` object representing the set of indices specified by ``range(start, stop, step)``. The *start* and *step* arguments default to ``None``. Slice objects have read-only data attributes :attr:`~slice.start`, - :attr:`~slice.stop` and :attr:`~slice.step` which merely return the argument + :attr:`~slice.stop`, and :attr:`~slice.step` which merely return the argument values (or their default). They have no other explicit functionality; - however they are used by NumPy and other third party packages. + however, they are used by NumPy and other third-party packages. Slice objects are also generated when extended indexing syntax is used. For example: ``a[start:stop:step]`` or ``a[start:stop, i]``. See :func:`itertools.islice` for an alternate version that returns an iterator. -.. function:: sorted(iterable, *, key=None, reverse=False) +.. function:: sorted(iterable, /, *, key=None, reverse=False) Return a new sorted list from the items in *iterable*. @@ -1603,6 +1603,15 @@ are always available. They are listed here in alphabetical order. compare equal --- this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade). + The sort algorithm uses only ``<`` comparisons between items. While + defining an :meth:`~object.__lt__` method will suffice for sorting, + :PEP:`8` recommends that all six :ref:`rich comparisons + ` be implemented. This will help avoid bugs when using + the same data with other ordering tools such as :func:`max` that rely + on a different underlying method. Implementing all six comparisons + also helps avoid confusion for mixed type comparisons which can call + reflected the :meth:`~object.__gt__` method. + For sorting examples and a brief sorting tutorial, see :ref:`sortinghowto`. .. decorator:: staticmethod @@ -1623,7 +1632,7 @@ are always available. They are listed here in alphabetical order. an instance (such as ``C().f()``). Moreover, they can be called as regular functions (such as ``f()``). - Static methods in Python are similar to those found in Java or C++. Also see + 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 constructors. @@ -1923,7 +1932,7 @@ are always available. They are listed here in alphabetical order. and *locals* to determine how to interpret the name in a package context. The *fromlist* gives the names of objects or submodules that should be imported from the module given by *name*. The standard implementation does - not use its *locals* argument at all, and uses its *globals* only to + not use its *locals* argument at all and uses its *globals* only to determine the package context of the :keyword:`import` statement. *level* specifies whether to use absolute or relative imports. ``0`` (the diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index e981bcdf6f2573..c78818bfab1a51 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -154,15 +154,22 @@ The :mod:`functools` module defines the following functions: @lru_cache def count_vowels(sentence): - sentence = sentence.casefold() - return sum(sentence.count(vowel) for vowel in 'aeiou') + return sum(sentence.count(vowel) for vowel in 'AEIOUaeiou') If *maxsize* is set to ``None``, the LRU feature is disabled and the cache can grow without bound. If *typed* is set to true, function arguments of different types will be - cached separately. For example, ``f(3)`` and ``f(3.0)`` will be treated - as distinct calls with distinct results. + cached separately. If *typed* is false, the implementation will usually + regard them as equivalent calls and only cache a single result. (Some + types such as *str* and *int* may be cached separately even when *typed* + is false.) + + Note, type specificity applies only to the function's immediate arguments + rather than their contents. The scalar arguments, ``Decimal(42)`` and + ``Fraction(42)`` are be treated as distinct calls with distinct results. + In contrast, the tuple arguments ``('answer', Decimal(42))`` and + ``('answer', Fraction(42))`` are treated as equivalent. The wrapped function is instrumented with a :func:`cache_parameters` function that returns a new :class:`dict` showing the values for *maxsize* @@ -172,8 +179,7 @@ The :mod:`functools` module defines the following functions: To help measure the effectiveness of the cache and tune the *maxsize* parameter, the wrapped function is instrumented with a :func:`cache_info` function that returns a :term:`named tuple` showing *hits*, *misses*, - *maxsize* and *currsize*. In a multi-threaded environment, the hits - and misses are approximate. + *maxsize* and *currsize*. The decorator also provides a :func:`cache_clear` function for clearing or invalidating the cache. @@ -182,6 +188,9 @@ The :mod:`functools` module defines the following functions: :attr:`__wrapped__` attribute. This is useful for introspection, for bypassing the cache, or for rewrapping the function with a different cache. + The cache keeps references to the arguments and return values until they age + out of the cache or until the cache is cleared. + An `LRU (least recently used) cache `_ works best when the most recent calls are the best predictors of upcoming @@ -199,7 +208,7 @@ The :mod:`functools` module defines the following functions: @lru_cache(maxsize=32) def get_pep(num): 'Retrieve text of a Python Enhancement Proposal' - resource = 'http://www.python.org/dev/peps/pep-%04d/' % num + resource = 'https://www.python.org/dev/peps/pep-%04d/' % num try: with urllib.request.urlopen(resource) as s: return s.read() @@ -399,8 +408,8 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic function, decorate it with the ``@singledispatch`` - decorator. Note that the dispatch happens on the type of the first argument, - create your function accordingly:: + decorator. When defining a function using ``@singledispatch``, note that the + dispatch happens on the type of the first argument:: >>> from functools import singledispatch >>> @singledispatch @@ -410,9 +419,9 @@ The :mod:`functools` module defines the following functions: ... print(arg) To add overloaded implementations to the function, use the :func:`register` - attribute of the generic function. It is a decorator. For functions - annotated with types, the decorator will infer the type of the first - argument automatically:: + attribute of the generic function, which can be used as a decorator. For + functions annotated with types, the decorator will infer the type of the + first argument automatically:: >>> @fun.register ... def _(arg: int, verbose=False): @@ -438,17 +447,17 @@ The :mod:`functools` module defines the following functions: ... - To enable registering lambdas and pre-existing functions, the - :func:`register` attribute can be used in a functional form:: + To enable registering :term:`lambdas` and pre-existing functions, + the :func:`register` attribute can also be used in a functional form:: >>> def nothing(arg, verbose=False): ... print("Nothing.") ... >>> fun.register(type(None), nothing) - The :func:`register` attribute returns the undecorated function which - enables decorator stacking, pickling, as well as creating unit tests for - each variant independently:: + The :func:`register` attribute returns the undecorated function. This + enables decorator stacking, :mod:`pickling`, and the creation + of unit tests for each variant independently:: >>> @fun.register(float) ... @fun.register(Decimal) @@ -483,11 +492,12 @@ The :mod:`functools` module defines the following functions: Where there is no registered implementation for a specific type, its method resolution order is used to find a more generic implementation. The original function decorated with ``@singledispatch`` is registered - for the base ``object`` type, which means it is used if no better + for the base :class:`object` type, which means it is used if no better implementation is found. - If an implementation registered to :term:`abstract base class`, virtual - subclasses will be dispatched to that implementation:: + If an implementation is registered to an :term:`abstract base class`, + virtual subclasses of the base class will be dispatched to that + implementation:: >>> from collections.abc import Mapping >>> @fun.register @@ -500,7 +510,7 @@ The :mod:`functools` module defines the following functions: >>> fun({"a": "b"}) a => b - To check which implementation will the generic function choose for + To check which implementation the generic function will choose for a given type, use the ``dispatch()`` attribute:: >>> fun.dispatch(float) @@ -523,7 +533,7 @@ The :mod:`functools` module defines the following functions: .. versionadded:: 3.4 .. versionchanged:: 3.7 - The :func:`register` attribute supports using type annotations. + The :func:`register` attribute now supports using type annotations. .. class:: singledispatchmethod(func) @@ -532,8 +542,9 @@ The :mod:`functools` module defines the following functions: dispatch>` :term:`generic function`. To define a generic method, decorate it with the ``@singledispatchmethod`` - decorator. Note that the dispatch happens on the type of the first non-self - or non-cls argument, create your function accordingly:: + decorator. When defining a function using ``@singledispatchmethod``, note + that the dispatch happens on the type of the first non-*self* or non-*cls* + argument:: class Negator: @singledispatchmethod @@ -549,9 +560,10 @@ The :mod:`functools` module defines the following functions: return not arg ``@singledispatchmethod`` supports nesting with other decorators such as - ``@classmethod``. Note that to allow for ``dispatcher.register``, - ``singledispatchmethod`` must be the *outer most* decorator. Here is the - ``Negator`` class with the ``neg`` methods being class bound:: + :func:`@classmethod`. Note that to allow for + ``dispatcher.register``, ``singledispatchmethod`` must be the *outer most* + decorator. Here is the ``Negator`` class with the ``neg`` methods bound to + the class, rather than an instance of the class:: class Negator: @singledispatchmethod @@ -569,8 +581,9 @@ The :mod:`functools` module defines the following functions: def _(cls, arg: bool): return not arg - The same pattern can be used for other similar decorators: ``staticmethod``, - ``abstractmethod``, and others. + The same pattern can be used for other similar decorators: + :func:`@staticmethod`, + :func:`@abstractmethod`, and others. .. versionadded:: 3.8 diff --git a/Doc/library/graphlib.rst b/Doc/library/graphlib.rst index 0faca2186b268c..2bc80da4ead2a2 100644 --- a/Doc/library/graphlib.rst +++ b/Doc/library/graphlib.rst @@ -154,9 +154,10 @@ .. method:: static_order() - Returns an iterable of nodes in a topological order. Using this method - does not require to call :meth:`TopologicalSorter.prepare` or - :meth:`TopologicalSorter.done`. This method is equivalent to:: + Returns an iterator object which will iterate over nodes in a topological + order. When using this method, :meth:`~TopologicalSorter.prepare` and + :meth:`~TopologicalSorter.done` should not be called. This method is + equivalent to:: def static_order(self): self.prepare() @@ -206,4 +207,4 @@ The :mod:`graphlib` module defines the following exception classes: The detected cycle can be accessed via the second element in the :attr:`~CycleError.args` attribute of the exception instance and consists in a list of nodes, such that each node is, in the graph, an immediate predecessor of the next node in the list. In the reported list, - the first and the last node will be the same, to make it clear that it is cyclic. \ No newline at end of file + the first and the last node will be the same, to make it clear that it is cyclic. diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index d77a2e5912d5e6..53320d9cb0d6c3 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -23,7 +23,7 @@ This module implements a common interface to many different secure hash and message digest algorithms. Included are the FIPS secure hash algorithms SHA1, SHA224, SHA256, SHA384, and SHA512 (defined in FIPS 180-2) as well as RSA's MD5 -algorithm (defined in Internet :rfc:`1321`). The terms "secure hash" and +algorithm (defined in internet :rfc:`1321`). The terms "secure hash" and "message digest" are interchangeable. Older algorithms were called message digests. The modern term is secure hash. @@ -80,6 +80,8 @@ library that Python uses on your platform. On most platforms the .. versionadded:: 3.6 :func:`blake2b` and :func:`blake2s` were added. +.. _hashlib-usedforsecurity: + .. versionchanged:: 3.9 All hashlib constructors take a keyword-only argument *usedforsecurity* with default value ``True``. A false value allows the use of insecure and @@ -118,10 +120,10 @@ More condensed: Using :func:`new` with an algorithm provided by OpenSSL: - >>> h = hashlib.new('sha512_256') + >>> h = hashlib.new('sha256') >>> h.update(b"Nobody inspects the spammish repetition") >>> h.hexdigest() - '19197dc4d03829df858011c6c87600f994a858103bbc19005f20987aa19a97e2' + '031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406' Hashlib provides the following constant attributes: @@ -374,10 +376,10 @@ Constructor functions also accept the following tree hashing parameters: * *depth*: maximal depth of tree (1 to 255, 255 if unlimited, 1 in sequential mode). -* *leaf_size*: maximal byte length of leaf (0 to 2**32-1, 0 if unlimited or in +* *leaf_size*: maximal byte length of leaf (0 to ``2**32-1``, 0 if unlimited or in sequential mode). -* *node_offset*: node offset (0 to 2**64-1 for BLAKE2b, 0 to 2**48-1 for +* *node_offset*: node offset (0 to ``2**64-1`` for BLAKE2b, 0 to ``2**48-1`` for BLAKE2s, 0 for the first, leftmost, leaf, or in sequential mode). * *node_depth*: node depth (0 to 255, 0 for leaves, or in sequential mode). @@ -498,7 +500,7 @@ Keyed hashing Keyed hashing can be used for authentication as a faster and simpler replacement for `Hash-based message authentication code -`_ (HMAC). +`_ (HMAC). BLAKE2 can be securely used in prefix-MAC mode thanks to the indifferentiability property inherited from BLAKE. diff --git a/Doc/library/html.entities.rst b/Doc/library/html.entities.rst index 067e1b1e5adb3e..7d836fe7380245 100644 --- a/Doc/library/html.entities.rst +++ b/Doc/library/html.entities.rst @@ -44,4 +44,4 @@ This module defines four dictionaries, :data:`html5`, .. rubric:: Footnotes -.. [#] See https://www.w3.org/TR/html5/syntax.html#named-character-references +.. [#] See https://html.spec.whatwg.org/multipage/syntax.html#named-character-references diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 7b1aa80a01797c..3d59665be4f254 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -20,7 +20,7 @@ Both the regular Netscape cookie protocol and the protocol defined by :rfc:`2965` are handled. RFC 2965 handling is switched off by default. :rfc:`2109` cookies are parsed as Netscape cookies and subsequently treated either as Netscape or RFC 2965 cookies according to the 'policy' in effect. -Note that the great majority of cookies on the Internet are Netscape cookies. +Note that the great majority of cookies on the internet are Netscape cookies. :mod:`http.cookiejar` attempts to follow the de-facto Netscape cookie protocol (which differs substantially from that set out in the original Netscape specification), including taking note of the ``max-age`` and ``port`` cookie-attributes @@ -122,7 +122,7 @@ The following classes are provided: :mod:`http.cookiejar` and :mod:`http.cookies` modules do not depend on each other. - https://curl.haxx.se/rfc/cookie_spec.html + https://curl.se/rfc/cookie_spec.html The specification of the original Netscape cookie protocol. Though this is still the dominant protocol, the 'Netscape cookie protocol' implemented by all the major browsers (and :mod:`http.cookiejar`) only bears a passing resemblance to diff --git a/Doc/library/http.rst b/Doc/library/http.rst index 1569d504c7f92a..2466c84476c6c1 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -35,7 +35,7 @@ associated messages through the :class:`http.HTTPStatus` enum: >>> from http import HTTPStatus >>> HTTPStatus.OK - HTTPStatus.OK + >>> HTTPStatus.OK == 200 True >>> HTTPStatus.OK.value @@ -45,7 +45,7 @@ associated messages through the :class:`http.HTTPStatus` enum: >>> HTTPStatus.OK.description 'Request fulfilled, document follows' >>> list(HTTPStatus) - [HTTPStatus.CONTINUE, HTTPStatus.SWITCHING_PROTOCOLS, ...] + [, , ...] .. _http-status-codes: diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 729d7e37137a81..c3cee079526b2e 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -14,7 +14,7 @@ -------------- -This module defines classes for implementing HTTP servers (Web servers). +This module defines classes for implementing HTTP servers. .. warning:: @@ -197,7 +197,7 @@ provides three different variants: request header it responds back with a ``100 Continue`` followed by ``200 OK`` headers. This method can be overridden to raise an error if the server does not - want the client to continue. For e.g. server can chose to send ``417 + want the client to continue. For e.g. server can choose to send ``417 Expectation Failed`` as a response header and ``return False``. .. versionadded:: 3.2 @@ -320,9 +320,16 @@ provides three different variants: .. class:: SimpleHTTPRequestHandler(request, client_address, server, directory=None) - This class serves files from the current directory and below, directly + This class serves files from the directory *directory* and below, + or the current directory if *directory* is not provided, directly mapping the directory structure to HTTP requests. + .. versionadded:: 3.7 + The *directory* parameter. + + .. versionchanged:: 3.9 + The *directory* parameter accepts a :term:`path-like object`. + A lot of the work, such as parsing the request, is done by the base class :class:`BaseHTTPRequestHandler`. This class implements the :func:`do_GET` and :func:`do_HEAD` functions. @@ -345,13 +352,6 @@ provides three different variants: This dictionary is no longer filled with the default system mappings, but only contains overrides. - .. attribute:: directory - - If not specified, the directory to serve is the current working directory. - - .. versionchanged:: 3.9 - Accepts a :term:`path-like object`. - The :class:`SimpleHTTPRequestHandler` class defines the following methods: .. method:: do_HEAD() diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index 3c302115b5f408..d740973af9124e 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -518,7 +518,7 @@ and not restarting the Shell thereafter. This is especially useful after adding imports at the top of a file. This also increases possible attribute completions. -Completion boxes intially exclude names beginning with '_' or, for +Completion boxes initially exclude names beginning with '_' or, for modules, not included in '__all__'. The hidden names can be accessed by typing '_' after '.', either before or after the box is opened. @@ -613,6 +613,12 @@ keywords, builtin class and function names, names following ``class`` and ``def``, strings, and comments. For any text window, these are the cursor (when present), found text (when possible), and selected text. +IDLE also highlights the :ref:`soft keywords ` :keyword:`match`, +:keyword:`case `, and :keyword:`_ ` in +pattern-matching statements. However, this highlighting is not perfect and +will be incorrect in some rare cases, including some ``_``-s in ``case`` +patterns. + Text coloring is done in the background, so uncolorized text is occasionally visible. To change the color scheme, use the Configure IDLE dialog Highlighting tab. The marking of debugger breakpoint lines in the editor and @@ -863,7 +869,7 @@ Running without a subprocess By default, IDLE executes user code in a separate subprocess via a socket, which uses the internal loopback interface. This connection is not -externally visible and no data is sent to or received from the Internet. +externally visible and no data is sent to or received from the internet. If firewall software complains anyway, you can ignore it. If the attempt to make the socket connection fails, Idle will notify you. diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index 9bedee5af28f69..99bcfeb2d1b55d 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -8,12 +8,10 @@ :synopsis: The implementation of the importlib metadata. .. versionadded:: 3.8 +.. versionchanged:: 3.10 + ``importlib.metadata`` is no longer provisional. -**Source code:** :source:`Lib/importlib/metadata.py` - -.. note:: - This functionality is provisional and may deviate from the usual - version semantics of the standard library. +**Source code:** :source:`Lib/importlib/metadata/__init__.py` ``importlib.metadata`` is a library that provides for access to installed package metadata. Built in part on Python's import system, this library @@ -257,7 +255,7 @@ function:: Package distributions --------------------- -A convience method to resolve the distribution or +A convenience method to resolve the distribution or distributions (in the case of a namespace package) for top-level Python packages or modules:: diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 50297e0d73e7c8..3576941efa46d9 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -491,7 +491,7 @@ ABC hierarchy:: .. class:: ResourceReader - *Superseded by TraversableReader* + *Superseded by TraversableResources* An :term:`abstract base class` to provide the ability to read *resources*. @@ -622,7 +622,7 @@ ABC hierarchy:: .. method:: is_package(fullname) - An abstract method to return a true value if the module is a package, a + An optional method to return a true value if the module is a package, a false value otherwise. :exc:`ImportError` is raised if the :term:`loader` cannot find the module. @@ -815,8 +815,48 @@ ABC hierarchy:: .. versionadded:: 3.9 + .. abstractmethod:: name() -.. class:: TraversableReader + The base name of this object without any parent references. + + .. abstractmethod:: iterdir() + + Yield Traversable objects in self. + + .. abstractmethod:: is_dir() + + Return True if self is a directory. + + .. abstractmethod:: is_file() + + Return True if self is a file. + + .. abstractmethod:: joinpath(child) + + Return Traversable child in self. + + .. abstractmethod:: __truediv__(child) + + Return Traversable child in self. + + .. abstractmethod:: open(mode='r', *args, **kwargs) + + *mode* may be 'r' or 'rb' to open as text or binary. Return a handle + suitable for reading (same as :attr:`pathlib.Path.open`). + + When opening as text, accepts encoding parameters such as those + accepted by :attr:`io.TextIOWrapper`. + + .. method:: read_bytes() + + Read contents of self as bytes. + + .. method:: read_text(encoding=None) + + Read contents of self as text. + + +.. class:: TraversableResources An abstract base class for resource readers capable of serving the ``files`` interface. Subclasses ResourceReader and provides diff --git a/Doc/library/index.rst b/Doc/library/index.rst index 1a9e52ec5ccfba..db8f0d9bdfb8fb 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -75,3 +75,4 @@ the `Python Package Index `_. unix.rst superseded.rst undoc.rst + security_warnings.rst diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index b9e8be1234e259..ed33cbb8a61ab2 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -834,10 +834,10 @@ function. >>> str(param.replace(default=Parameter.empty, annotation='spam')) "foo:'spam'" - .. versionchanged:: 3.4 - In Python 3.3 Parameter objects were allowed to have ``name`` set - to ``None`` if their ``kind`` was set to ``POSITIONAL_ONLY``. - This is no longer permitted. + .. versionchanged:: 3.4 + In Python 3.3 Parameter objects were allowed to have ``name`` set + to ``None`` if their ``kind`` was set to ``POSITIONAL_ONLY``. + This is no longer permitted. .. class:: BoundArguments diff --git a/Doc/library/internet.rst b/Doc/library/internet.rst index b8950bb6cb8c2d..e745dd1243512e 100644 --- a/Doc/library/internet.rst +++ b/Doc/library/internet.rst @@ -11,7 +11,7 @@ Internet Protocols and Support .. index:: module: socket -The modules described in this chapter implement Internet protocols and support +The modules described in this chapter implement internet protocols and support for related technology. They are all implemented in Python. Most of these modules require the presence of the system-dependent module :mod:`socket`, which is currently supported on most popular platforms. Here is an overview: diff --git a/Doc/library/intro.rst b/Doc/library/intro.rst index 8567e4d1d08920..5bb33b9c10cc03 100644 --- a/Doc/library/intro.rst +++ b/Doc/library/intro.rst @@ -58,5 +58,5 @@ Notes on availability operating system. * If not separately noted, all functions that claim "Availability: Unix" are - supported on Mac OS X, which builds on a Unix core. + supported on macOS, which builds on a Unix core. diff --git a/Doc/library/io.rst b/Doc/library/io.rst index f9ffc19fac489d..de88c572f3662e 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -131,7 +131,7 @@ explicitly when opening text files. If you want to use UTF-8, pass ``encoding="utf-8"``. To use the current locale encoding, ``encoding="locale"`` is supported in Python 3.10. -When you need to run existing code on Windows that attempts to opens +When you need to run existing code on Windows that attempts to open UTF-8 files using the default locale encoding, you can enable the UTF-8 mode. See :ref:`UTF-8 mode on Windows `. @@ -391,6 +391,9 @@ I/O Base Classes to control the number of lines read: no more lines will be read if the total size (in bytes/characters) of all lines so far exceeds *hint*. + *hint* values of ``0`` or less, as well as ``None``, are treated as no + hint. + Note that it's already possible to iterate on file objects using ``for line in file: ...`` without calling ``file.readlines()``. diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 1c2263b128a8fe..9c2dff55703273 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -41,7 +41,7 @@ IP addresses, networks and interfaces: Return an :class:`IPv4Address` or :class:`IPv6Address` object depending on the IP address passed as argument. Either IPv4 or IPv6 addresses may be - supplied; integers less than 2**32 will be considered to be IPv4 by default. + supplied; integers less than ``2**32`` will be considered to be IPv4 by default. A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or IPv6 address. @@ -56,7 +56,7 @@ IP addresses, networks and interfaces: Return an :class:`IPv4Network` or :class:`IPv6Network` object depending on the IP address passed as argument. *address* is a string or integer representing the IP network. Either IPv4 or IPv6 networks may be supplied; - integers less than 2**32 will be considered to be IPv4 by default. *strict* + integers less than ``2**32`` will be considered to be IPv4 by default. *strict* is passed to :class:`IPv4Network` or :class:`IPv6Network` constructor. A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or IPv6 address, or if the network has host bits set. @@ -70,7 +70,7 @@ IP addresses, networks and interfaces: Return an :class:`IPv4Interface` or :class:`IPv6Interface` object depending on the IP address passed as argument. *address* is a string or integer representing the IP address. Either IPv4 or IPv6 addresses may be supplied; - integers less than 2**32 will be considered to be IPv4 by default. A + integers less than ``2**32`` will be considered to be IPv4 by default. A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or IPv6 address. @@ -132,6 +132,11 @@ write code that handles both IP versions correctly. Address objects are The above change was also included in Python 3.9 starting with version 3.9.5. + .. versionchanged:: 3.8.12 + + The above change was also included in Python 3.8 starting with + version 3.8.12. + .. attribute:: version The appropriate version number: ``4`` for IPv4, ``6`` for IPv6. @@ -677,7 +682,7 @@ dictionaries. Note that currently expanded netmasks are not supported. That means ``2001:db00::0/24`` is a valid argument while ``2001:db00::0/ffff:ff00::`` - not. + is not. 2. An integer that fits into 128 bits. This is equivalent to a single-address network, with the network address being *address* and diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index fd77f99a88f577..61d8b869711fa4 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -492,6 +492,8 @@ loops that truncate the stream. next(b, None) return zip(a, b) + .. versionadded:: 3.10 + .. function:: permutations(iterable, r=None) @@ -812,11 +814,27 @@ which incur interpreter overhead. return starmap(func, repeat(args, times)) def grouper(iterable, n, fillvalue=None): - "Collect data into fixed-length chunks or blocks" - # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx" + "Collect data into non-overlapping fixed-length chunks or blocks" + # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx args = [iter(iterable)] * n return zip_longest(*args, fillvalue=fillvalue) + def triplewise(iterable): + "Return overlapping triplets from an iterable" + # triplewise('ABCDEFG') -> ABC BCD CDE DEF EFG + for (a, _), (b, c) in pairwise(pairwise(iterable)): + yield a, b, c + + def sliding_window(iterable, n): + # sliding_window('ABCDEFG', 4) -> ABCD BCDE CDEF DEFG + it = iter(iterable) + window = collections.deque(islice(it, n), maxlen=n) + if len(window) == n: + yield tuple(window) + for x in it: + window.append(x) + yield tuple(window) + def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" # Recipe credited to George Sakkis @@ -837,6 +855,35 @@ which incur interpreter overhead. t1, t2 = tee(iterable) return filterfalse(pred, t1), filter(pred, t2) + def before_and_after(predicate, it): + """ Variant of takewhile() that allows complete + access to the remainder of the iterator. + + >>> it = iter('ABCdEfGhI') + >>> all_upper, remainder = before_and_after(str.isupper, it) + >>> ''.join(all_upper) + 'ABC' + >>> ''.join(remainder) # takewhile() would lose the 'd' + 'dEfGhI' + + Note that the first iterator must be fully + consumed before the second iterator can + generate valid results. + """ + it = iter(it) + transition = [] + def true_iterator(): + for elem in it: + if predicate(elem): + yield elem + else: + transition.append(elem) + return + def remainder_iterator(): + yield from transition + yield from it + return true_iterator(), remainder_iterator() + def powerset(iterable): "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" s = list(iterable) @@ -948,4 +995,3 @@ which incur interpreter overhead. c, n = c*(n-r)//n, n-1 result.append(pool[-1-n]) return tuple(result) - diff --git a/Doc/library/json.rst b/Doc/library/json.rst index c8184da80fe43e..1810e04cc83495 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -11,9 +11,9 @@ -------------- -`JSON (JavaScript Object Notation) `_, specified by +`JSON (JavaScript Object Notation) `_, specified by :rfc:`7159` (which obsoletes :rfc:`4627`) and by -`ECMA-404 `_, +`ECMA-404 `_, is a lightweight data interchange format inspired by `JavaScript `_ object literal syntax (although it is not a strict subset of JavaScript [#rfc-errata]_ ). @@ -159,7 +159,7 @@ Basic Usage If *check_circular* is false (default: ``True``), then the circular reference check for container types will be skipped and a circular reference - will result in an :exc:`OverflowError` (or worse). + will result in an :exc:`RecursionError` (or worse). If *allow_nan* is false (default: ``True``), then it will be a :exc:`ValueError` to serialize out of range :class:`float` values (``nan``, @@ -432,7 +432,7 @@ Encoders and Decoders If *check_circular* is true (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an :exc:`OverflowError`). + prevent an infinite recursion (which would cause an :exc:`RecursionError`). Otherwise, no such check takes place. If *allow_nan* is true (the default), then ``NaN``, ``Infinity``, and @@ -544,7 +544,7 @@ Standard Compliance and Interoperability ---------------------------------------- The JSON format is specified by :rfc:`7159` and by -`ECMA-404 `_. +`ECMA-404 `_. This section details this module's level of compliance with the RFC. For simplicity, :class:`JSONEncoder` and :class:`JSONDecoder` subclasses, and parameters other than those explicitly mentioned, are not considered. diff --git a/Doc/library/keyword.rst b/Doc/library/keyword.rst index 5cae79f5dc9dbc..c3b4699cb05af6 100644 --- a/Doc/library/keyword.rst +++ b/Doc/library/keyword.rst @@ -9,7 +9,7 @@ -------------- This module allows a Python program to determine if a string is a -:ref:`keyword `. +:ref:`keyword ` or :ref:`soft keyword `. .. function:: iskeyword(s) @@ -26,14 +26,14 @@ This module allows a Python program to determine if a string is a .. function:: issoftkeyword(s) - Return ``True`` if *s* is a Python soft :ref:`keyword `. + Return ``True`` if *s* is a Python :ref:`soft keyword `. .. versionadded:: 3.9 .. data:: softkwlist - Sequence containing all the soft :ref:`keywords ` defined for the + Sequence containing all the :ref:`soft keywords ` defined for the interpreter. If any soft keywords are defined to only be active when particular :mod:`__future__` statements are in effect, these will be included as well. diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index f833bcdd1fcf5b..a1b8dc755ba6b0 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -152,6 +152,8 @@ in :mod:`logging` itself) and defining handlers which are declared either in send it to the socket as a sequence of bytes preceded by a four-byte length string packed in binary using ``struct.pack('>L', n)``. + .. _logging-eval-security: + .. note:: Because portions of the configuration are passed through @@ -166,7 +168,7 @@ in :mod:`logging` itself) and defining handlers which are declared either in :func:`listen` socket and sending a configuration which runs whatever code the attacker wants to have executed in the victim's process. This is especially easy to do if the default port is used, but not hard even if a - different port is used). To avoid the risk of this happening, use the + different port is used. To avoid the risk of this happening, use the ``verify`` argument to :func:`listen` to prevent unrecognised configurations from being applied. @@ -189,6 +191,20 @@ in :mod:`logging` itself) and defining handlers which are declared either in :func:`listen`. +Security considerations +^^^^^^^^^^^^^^^^^^^^^^^ + +The logging configuration functionality tries to offer convenience, and in part this +is done by offering the ability to convert text in configuration files into Python +objects used in logging configuration - for example, as described in +:ref:`logging-config-dict-userdef`. However, these same mechanisms (importing +callables from user-defined modules and calling them with parameters from the +configuration) could be used to invoke any code you like, and for this reason you +should treat configuration files from untrusted sources with *extreme caution* and +satisfy yourself that nothing bad can happen if you load them, before actually loading +them. + + .. _logging-config-dictschema: Configuration dictionary schema diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 059ab3d3a34448..a5b181ee612d5f 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -117,6 +117,9 @@ sends logging output to a disk file. It inherits the output functionality from Outputs the record to the file. + Note that if the file was closed due to logging shutdown at exit and the file + mode is 'w', the record will not be emitted (see :issue:`42378`). + .. _null-handler: @@ -231,6 +234,19 @@ need to override. return the same output every time for a given input, otherwise the rollover behaviour may not work as expected. + It's also worth noting that care should be taken when using a namer to + preserve certain attributes in the filename which are used during rotation. + For example, :class:`RotatingFileHandler` expects to have a set of log files + whose names contain successive integers, so that rotation works as expected, + and :class:`TimedRotatingFileHandler` deletes old log files (based on the + ``backupCount`` parameter passed to the handler's initializer) by determining + the oldest files to delete. For this to happen, the filenames should be + sortable using the date/time portion of the filename, and a namer needs to + respect this. (If a namer is wanted that doesn't respect this scheme, it will + need to be used in a subclass of :class:`TimedRotatingFileHandler` which + overrides the :meth:`~TimedRotatingFileHandler.getFilesToDelete` method to + fit in with the custom naming scheme.) + .. versionadded:: 3.3 @@ -440,6 +456,10 @@ timed intervals. Outputs the record to the file, catering for rollover as described above. + .. method:: getFilesToDelete() + + Returns a list of filenames which should be deleted as part of rollover. These + are the absolute paths of the oldest backup log files written by the handler. .. _socket-handler: @@ -927,7 +947,7 @@ HTTPHandler ^^^^^^^^^^^ The :class:`HTTPHandler` class, located in the :mod:`logging.handlers` module, -supports sending logging messages to a Web server, using either ``GET`` or +supports sending logging messages to a web server, using either ``GET`` or ``POST`` semantics. @@ -957,17 +977,17 @@ supports sending logging messages to a Web server, using either ``GET`` or .. method:: emit(record) - Sends the record to the Web server as a URL-encoded dictionary. The + Sends the record to the web server as a URL-encoded dictionary. The :meth:`mapLogRecord` method is used to convert the record to the dictionary to be sent. - .. note:: Since preparing a record for sending it to a Web server is not + .. note:: Since preparing a record for sending it to a web server is not the same as a generic formatting operation, using :meth:`~logging.Handler.setFormatter` to specify a :class:`~logging.Formatter` for a :class:`HTTPHandler` has no effect. Instead of calling :meth:`~logging.Handler.format`, this handler calls :meth:`mapLogRecord` and then :func:`urllib.parse.urlencode` to encode the - dictionary in a form suitable for sending to a Web server. + dictionary in a form suitable for sending to a web server. .. _queue-handler: @@ -984,7 +1004,7 @@ supports sending logging messages to a queue, such as those implemented in the Along with the :class:`QueueListener` class, :class:`QueueHandler` can be used to let handlers do their work on a separate thread from the one which does the -logging. This is important in Web applications and also other service +logging. This is important in web applications and also other service applications where threads servicing clients need to respond as quickly as possible, while any potentially slow operations (such as sending an email via :class:`SMTPHandler`) are done on a separate thread. @@ -1046,7 +1066,7 @@ because it works hand-in-hand with :class:`QueueHandler`. Along with the :class:`QueueHandler` class, :class:`QueueListener` can be used to let handlers do their work on a separate thread from the one which does the -logging. This is important in Web applications and also other service +logging. This is important in web applications and also other service applications where threads servicing clients need to respond as quickly as possible, while any potentially slow operations (such as sending an email via :class:`SMTPHandler`) are done on a separate thread. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 70a703dde18a03..74b1f69caec5c2 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -80,6 +80,15 @@ is the module's name in the Python package namespace. If this evaluates to false, logging messages are not passed to the handlers of ancestor loggers. + Spelling it out with an example: If the propagate attribute of the logger named + ``A.B.C`` evaluates to true, any event logged to ``A.B.C`` via a method call such as + ``logging.getLogger('A.B.C').error(...)`` will [subject to passing that logger's + level and filter settings] be passed in turn to any handlers attached to loggers + named ``A.B``, ``A`` and the root logger, after first being passed to any handlers + attached to ``A.B.C``. If any logger in the chain ``A.B.C``, ``A.B``, ``A`` has its + ``propagate`` attribute set to false, then that is the last logger whose handlers + are offered the event to handle, and propagation stops at that point. + The constructor sets this attribute to ``True``. .. note:: If you attach a handler to a logger *and* one or more of its @@ -203,7 +212,7 @@ is the module's name in the Python package namespace. attributes can then be used as you like. For example, they could be incorporated into logged messages. For example:: - FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' + FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s' logging.basicConfig(format=FORMAT) d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} logger = logging.getLogger('tcpserver') @@ -900,6 +909,10 @@ interchangeably. :meth:`~Logger.setLevel` and :meth:`~Logger.hasHandlers` methods were added to :class:`LoggerAdapter`. These methods delegate to the underlying logger. +.. versionchanged:: 3.6 + Attribute :attr:`manager` and method :meth:`_log` were added, which + delegate to the underlying logger and allow adapters to be nested. + Thread Safety ------------- @@ -996,7 +1009,7 @@ functions. be used as you like. For example, they could be incorporated into logged messages. For example:: - FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' + FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s' logging.basicConfig(format=FORMAT) d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} logging.warning('Protocol problem: %s', 'connection reset', extra=d) @@ -1352,7 +1365,7 @@ with the :mod:`warnings` module. The proposal which described this feature for inclusion in the Python standard library. - `Original Python logging package `_ + `Original Python logging package `_ This is the original source for the :mod:`logging` package. The version of the package available from this site is suitable for use with Python 1.5.2, 2.1.x and 2.2.x, which do not include the :mod:`logging` package in the standard diff --git a/Doc/library/mailcap.rst b/Doc/library/mailcap.rst index bf9639bdaca50a..7749b7dd45ef44 100644 --- a/Doc/library/mailcap.rst +++ b/Doc/library/mailcap.rst @@ -9,16 +9,16 @@ -------------- Mailcap files are used to configure how MIME-aware applications such as mail -readers and Web browsers react to files with different MIME types. (The name +readers and web browsers react to files with different MIME types. (The name "mailcap" is derived from the phrase "mail capability".) For example, a mailcap file might contain a line like ``video/mpeg; xmpeg %s``. Then, if the user -encounters an email message or Web document with the MIME type +encounters an email message or web document with the MIME type :mimetype:`video/mpeg`, ``%s`` will be replaced by a filename (usually one belonging to a temporary file) and the :program:`xmpeg` program can be automatically started to view the file. The mailcap format is documented in :rfc:`1524`, "A User Agent Configuration -Mechanism For Multimedia Mail Format Information", but is not an Internet +Mechanism For Multimedia Mail Format Information", but is not an internet standard. However, mailcap files are supported on most Unix systems. diff --git a/Doc/library/marshal.rst b/Doc/library/marshal.rst index d65afc20041133..24f9dc1689da4a 100644 --- a/Doc/library/marshal.rst +++ b/Doc/library/marshal.rst @@ -66,6 +66,8 @@ The module defines these functions: The *version* argument indicates the data format that ``dump`` should use (see below). + .. audit-event:: marshal.dumps value,version marshal.dump + .. function:: load(file) @@ -74,11 +76,18 @@ The module defines these functions: format), raise :exc:`EOFError`, :exc:`ValueError` or :exc:`TypeError`. The file must be a readable :term:`binary file`. + .. audit-event:: marshal.load "" marshal.load + .. note:: If an object containing an unsupported type was marshalled with :func:`dump`, :func:`load` will substitute ``None`` for the unmarshallable type. + .. versionchanged:: 3.10 + + This call used to raise a ``code.__new__`` audit event for each code object. Now + it raises a single ``marshal.load`` event for the entire load operation. + .. function:: dumps(value[, version]) @@ -89,6 +98,8 @@ The module defines these functions: The *version* argument indicates the data format that ``dumps`` should use (see below). + .. audit-event:: marshal.dumps value,version marshal.dump + .. function:: loads(bytes) @@ -96,6 +107,13 @@ The module defines these functions: :exc:`EOFError`, :exc:`ValueError` or :exc:`TypeError`. Extra bytes in the input are ignored. + .. audit-event:: marshal.loads bytes marshal.load + + .. versionchanged:: 3.10 + + This call used to raise a ``code.__new__`` audit event for each code object. Now + it raises a single ``marshal.loads`` event for the entire load operation. + In addition, the following constants are defined: diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index d9825b47c71333..da174753361b2f 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -102,7 +102,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length To ensure validity of the created memory mapping the file specified by the descriptor *fileno* is internally automatically synchronized - with physical backing store on Mac OS X and OpenVMS. + with physical backing store on macOS and OpenVMS. This example shows a simple way of using :class:`~mmap.mmap`:: diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index ae4f7bf3b9621d..e81dd7e648f7fe 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -783,7 +783,7 @@ For an example of the usage of queues for interprocess communication see multithreading/multiprocessing semantics, this number is not reliable. Note that this may raise :exc:`NotImplementedError` on Unix platforms like - Mac OS X where ``sem_getvalue()`` is not implemented. + macOS where ``sem_getvalue()`` is not implemented. .. method:: empty() @@ -951,7 +951,8 @@ Miscellaneous use. The number of usable CPUs can be obtained with ``len(os.sched_getaffinity(0))`` - May raise :exc:`NotImplementedError`. + When the number of CPUs cannot be determined a :exc:`NotImplementedError` + is raised. .. seealso:: :func:`os.cpu_count` @@ -1029,7 +1030,13 @@ Miscellaneous The return value can be ``'fork'``, ``'spawn'``, ``'forkserver'`` or ``None``. ``'fork'`` is the default on Unix, while ``'spawn'`` is - the default on Windows. + the default on Windows and macOS. + +.. versionchanged:: 3.8 + + On macOS, the *spawn* start method is now the default. The *fork* start + method should be considered unsafe as it can lead to crashes of the + subprocess. See :issue:`33725`. .. versionadded:: 3.4 @@ -1187,6 +1194,7 @@ For example: >>> arr2 array('i', [0, 1, 2, 3, 4, 0, 0, 0, 0, 0]) +.. _multiprocessing-recv-pickle-security: .. warning:: @@ -1233,7 +1241,7 @@ object -- see :ref:`multiprocessing-managers`. first argument is named *block*, as is consistent with :meth:`Lock.acquire`. .. note:: - On Mac OS X, this is indistinguishable from :class:`Semaphore` because + On macOS, this is indistinguishable from :class:`Semaphore` because ``sem_getvalue()`` is not implemented on that platform. .. class:: Condition([lock]) @@ -1372,7 +1380,7 @@ object -- see :ref:`multiprocessing-managers`. .. note:: - On Mac OS X, ``sem_timedwait`` is unsupported, so calling ``acquire()`` with + On macOS, ``sem_timedwait`` is unsupported, so calling ``acquire()`` with a timeout will emulate that function's behavior using a sleeping loop. .. note:: @@ -2242,8 +2250,9 @@ with the :class:`Pool` class. .. method:: starmap(func, iterable[, chunksize]) - Like :meth:`map` except that the elements of the *iterable* are expected - to be iterables that are unpacked as arguments. + Like :meth:`~multiprocessing.pool.Pool.map` except that the + elements of the *iterable* are expected to be iterables that are + unpacked as arguments. Hence an *iterable* of ``[(1,2), (3, 4)]`` results in ``[func(1,2), func(3,4)]``. @@ -2627,12 +2636,13 @@ handler type) for messages from different processes to get mixed up. inherited. .. currentmodule:: multiprocessing -.. function:: log_to_stderr() +.. function:: log_to_stderr(level=None) This function performs a call to :func:`get_logger` but in addition to returning the logger created by get_logger, it adds a handler which sends output to :data:`sys.stderr` using format ``'[%(levelname)s/%(processName)s] %(message)s'``. + You can modify ``levelname`` of the logger by passing a ``level`` argument. Below is an example session with logging turned on:: diff --git a/Doc/library/multiprocessing.shared_memory.rst b/Doc/library/multiprocessing.shared_memory.rst index cba576a29e2e2b..2ba42b7e579a77 100644 --- a/Doc/library/multiprocessing.shared_memory.rst +++ b/Doc/library/multiprocessing.shared_memory.rst @@ -342,3 +342,30 @@ behind it: >>> c.shm.close() >>> c.shm.unlink() +The following examples demonstrates that ``ShareableList`` +(and underlying ``SharedMemory``) objects +can be pickled and unpickled if needed. +Note, that it will still be the same shared object. +This happens, because the deserialized object has +the same unique name and is just attached to an existing +object with the same name (if the object is still alive): + + >>> import pickle + >>> from multiprocessing import shared_memory + >>> sl = shared_memory.ShareableList(range(10)) + >>> list(sl) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + >>> deserialized_sl = pickle.loads(pickle.dumps(sl)) + >>> list(deserialized_sl) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + >>> sl[0] = -1 + >>> deserialized_sl[1] = -2 + >>> list(sl) + [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9] + >>> list(deserialized_sl) + [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9] + + >>> sl.shm.close() + >>> sl.shm.unlink() diff --git a/Doc/library/netdata.rst b/Doc/library/netdata.rst index 491501665e3d71..e76280f2fe3f4c 100644 --- a/Doc/library/netdata.rst +++ b/Doc/library/netdata.rst @@ -6,7 +6,7 @@ Internet Data Handling ********************** This chapter describes modules which support handling data formats commonly used -on the Internet. +on the internet. .. toctree:: diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index 1b594952ead724..b77845ed0dee92 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -10,7 +10,7 @@ The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric :term:`abstract base classes ` which progressively define -more operations. None of the types defined in this module can be instantiated. +more operations. None of the types defined in this module are intended to be instantiated. .. class:: Number @@ -27,8 +27,8 @@ The numeric tower Subclasses of this type describe complex numbers and include the operations that work on the built-in :class:`complex` type. These are: conversions to :class:`complex` and :class:`bool`, :attr:`.real`, :attr:`.imag`, ``+``, - ``-``, ``*``, ``/``, :func:`abs`, :meth:`conjugate`, ``==``, and ``!=``. All - except ``-`` and ``!=`` are abstract. + ``-``, ``*``, ``/``, ``**``, :func:`abs`, :meth:`conjugate`, ``==``, and + ``!=``. All except ``-`` and ``!=`` are abstract. .. attribute:: real @@ -76,8 +76,9 @@ The numeric tower Subtypes :class:`Rational` and adds a conversion to :class:`int`. Provides defaults for :func:`float`, :attr:`~Rational.numerator`, and - :attr:`~Rational.denominator`. Adds abstract methods for ``**`` and - bit-string operations: ``<<``, ``>>``, ``&``, ``^``, ``|``, ``~``. + :attr:`~Rational.denominator`. Adds abstract methods for :func:`pow` with + modulus and bit-string operations: ``<<``, ``>>``, ``&``, ``^``, ``|``, + ``~``. Notes for type implementors diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index d06d9ce8c9e3d7..6b15a113f54506 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -340,6 +340,14 @@ the :mod:`glob` module.) that contains symbolic links. On Windows, it converts forward slashes to backward slashes. To normalize case, use :func:`normcase`. + .. note:: + On POSIX systems, in accordance with `IEEE Std 1003.1 2013 Edition; 4.13 + Pathname Resolution `_, + if a pathname begins with exactly two slashes, the first component + following the leading characters may be interpreted in an implementation-defined + manner, although more than two leading characters shall be treated as a + single character. + .. versionchanged:: 3.6 Accepts a :term:`path-like object`. @@ -462,12 +470,16 @@ the :mod:`glob` module.) On Windows, splits a pathname into drive/UNC sharepoint and relative path. If the path contains a drive letter, drive will contain everything - up to and including the colon. - e.g. ``splitdrive("c:/dir")`` returns ``("c:", "/dir")`` + up to and including the colon:: + + >>> splitdrive("c:/dir") + ("c:", "/dir") If the path contains a UNC path, drive will contain the host name - and share, up to but not including the fourth separator. - e.g. ``splitdrive("//host/computer/dir")`` returns ``("//host/computer", "/dir")`` + and share, up to but not including the fourth separator:: + + >>> splitdrive("//host/computer/dir") + ("//host/computer", "/dir") .. versionchanged:: 3.6 Accepts a :term:`path-like object`. @@ -476,9 +488,29 @@ the :mod:`glob` module.) .. function:: splitext(path) Split the pathname *path* into a pair ``(root, ext)`` such that ``root + ext == - path``, and *ext* is empty or begins with a period and contains at most one - period. Leading periods on the basename are ignored; ``splitext('.cshrc')`` - returns ``('.cshrc', '')``. + path``, and the extension, *ext*, is empty or begins with a period and contains at + most one period. + + If the path contains no extension, *ext* will be ``''``:: + + >>> splitext('bar') + ('bar', '') + + If the path contains an extension, then *ext* will be set to this extension, + including the leading period. Note that previous periods will be ignored:: + + >>> splitext('foo.bar.exe') + ('foo.bar', '.exe') + >>> splitext('/foo/bar.exe') + ('/foo/bar', '.exe') + + Leading periods of the last component of the path are considered to + be part of the root:: + + >>> splitext('.cshrc') + ('.cshrc', '') + >>> splitext('/foo/....jpg') + ('/foo/....jpg', '') .. versionchanged:: 3.6 Accepts a :term:`path-like object`. diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 6f9f3219481c2b..629a32f1b63e7d 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -170,9 +170,10 @@ process and user. .. data:: environ - A :term:`mapping` object representing the string environment. For example, - ``environ['HOME']`` is the pathname of your home directory (on some platforms), - and is equivalent to ``getenv("HOME")`` in C. + A :term:`mapping` object where keys and values are strings that represent + the process environment. For example, ``environ['HOME']`` is the pathname + of your home directory (on some platforms), and is equivalent to + ``getenv("HOME")`` in C. This mapping is captured the first time the :mod:`os` module is imported, typically during Python startup as part of processing :file:`site.py`. Changes @@ -194,7 +195,7 @@ process and user. .. note:: - On some platforms, including FreeBSD and Mac OS X, setting ``environ`` may + On some platforms, including FreeBSD and macOS, setting ``environ`` may cause memory leaks. Refer to the system documentation for :c:func:`putenv`. @@ -209,10 +210,10 @@ process and user. .. data:: environb - Bytes version of :data:`environ`: a :term:`mapping` object representing the - environment as byte strings. :data:`environ` and :data:`environb` are - synchronized (modify :data:`environb` updates :data:`environ`, and vice - versa). + Bytes version of :data:`environ`: a :term:`mapping` object where both keys + and values are :class:`bytes` objects representing the process environment. + :data:`environ` and :data:`environb` are synchronized (modifying + :data:`environb` updates :data:`environ`, and vice versa). :data:`environb` is only available if :data:`supports_bytes_environ` is ``True``. @@ -369,7 +370,7 @@ process and user. .. note:: - On Mac OS X, :func:`getgroups` behavior differs somewhat from + On macOS, :func:`getgroups` behavior differs somewhat from other Unix platforms. If the Python interpreter was built with a deployment target of :const:`10.5` or earlier, :func:`getgroups` returns the list of effective group ids associated with the current user process; @@ -516,7 +517,7 @@ process and user. .. note:: - On some platforms, including FreeBSD and Mac OS X, setting ``environ`` may + On some platforms, including FreeBSD and macOS, setting ``environ`` may cause memory leaks. Refer to the system documentation for :c:func:`putenv`. .. audit-event:: os.putenv key,value os.putenv @@ -554,7 +555,7 @@ process and user. .. availability:: Unix. - .. note:: On Mac OS X, the length of *groups* may not exceed the + .. note:: On macOS, the length of *groups* may not exceed the system-defined maximum number of effective group ids, typically 16. See the documentation for :func:`getgroups` for cases where it may not return the same group list set by calling setgroups(). @@ -1379,11 +1380,11 @@ or `the MSDN `_ on Windo On Linux, if *offset* is given as ``None``, the bytes are read from the current position of *in_fd* and the position of *in_fd* is updated. - The second case may be used on Mac OS X and FreeBSD where *headers* and + The second case may be used on macOS and FreeBSD where *headers* and *trailers* are arbitrary sequences of buffers that are written before and after the data from *in_fd* is written. It returns the same as the first case. - On Mac OS X and FreeBSD, a value of ``0`` for *count* specifies to send until + On macOS and FreeBSD, a value of ``0`` for *count* specifies to send until the end of *in_fd* is reached. All platforms support sockets as *out_fd* file descriptor, and some platforms @@ -2789,7 +2790,7 @@ features: String that uniquely identifies the type of the filesystem that contains the file. - On Mac OS systems, the following attributes may also be available: + On macOS systems, the following attributes may also be available: .. attribute:: st_rsize @@ -4211,12 +4212,12 @@ written in Python, such as a mail server's external command delivery program. the Standard C function :c:func:`system`, and has the same limitations. Changes to :data:`sys.stdin`, etc. are not reflected in the environment of the executed command. If *command* generates any output, it will be sent to - the interpreter standard output stream. + the interpreter standard output stream. The C standard does not + specify the meaning of the return value of the C function, so the return + value of the Python function is system-dependent. On Unix, the return value is the exit status of the process encoded in the - format specified for :func:`wait`. Note that POSIX does not specify the - meaning of the return value of the C :c:func:`system` function, so the return - value of the Python function is system-dependent. + format specified for :func:`wait`. On Windows, the return value is that returned by the system shell after running *command*. The shell is given by the Windows environment variable @@ -4243,20 +4244,20 @@ written in Python, such as a mail server's external command delivery program. Returns the current global process times. The return value is an object with five attributes: - * :attr:`user` - user time - * :attr:`system` - system time - * :attr:`children_user` - user time of all child processes - * :attr:`children_system` - system time of all child processes - * :attr:`elapsed` - elapsed real time since a fixed point in the past + * :attr:`!user` - user time + * :attr:`!system` - system time + * :attr:`!children_user` - user time of all child processes + * :attr:`!children_system` - system time of all child processes + * :attr:`!elapsed` - elapsed real time since a fixed point in the past For backwards compatibility, this object also behaves like a five-tuple - containing :attr:`user`, :attr:`system`, :attr:`children_user`, - :attr:`children_system`, and :attr:`elapsed` in that order. + containing :attr:`!user`, :attr:`!system`, :attr:`!children_user`, + :attr:`!children_system`, and :attr:`!elapsed` in that order. See the Unix manual page :manpage:`times(2)` and :manpage:`times(3)` manual page on Unix or `the GetProcessTimes MSDN `_ - on Windows. On Windows, only :attr:`user` and :attr:`system` are known; the other attributes are zero. + on Windows. On Windows, only :attr:`!user` and :attr:`!system` are known; the other attributes are zero. .. availability:: Unix, Windows. @@ -4635,7 +4636,7 @@ operating system. .. function:: sched_setparam(pid, param) - Set a scheduling parameters for the process with PID *pid*. A *pid* of 0 means + Set the scheduling parameters for the process with PID *pid*. A *pid* of 0 means the calling process. *param* is a :class:`sched_param` instance. diff --git a/Doc/library/othergui.rst b/Doc/library/othergui.rst deleted file mode 100644 index 48c1f2754111aa..00000000000000 --- a/Doc/library/othergui.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. _other-gui-packages: - -Other Graphical User Interface Packages -======================================= - -Major cross-platform (Windows, Mac OS X, Unix-like) GUI toolkits are -available for Python: - -.. seealso:: - - `PyGObject `_ - PyGObject provides introspection bindings for C libraries using - `GObject `_. One of - these libraries is the `GTK+ 3 `_ widget set. - GTK+ comes with many more widgets than Tkinter provides. An online - `Python GTK+ 3 Tutorial `_ - is available. - - `PyGTK `_ - PyGTK provides bindings for an older version - of the library, GTK+ 2. It provides an object oriented interface that - is slightly higher level than the C one. There are also bindings to - `GNOME `_. An online `tutorial - `_ is available. - - `PyQt `_ - PyQt is a :program:`sip`\ -wrapped binding to the Qt toolkit. Qt is an - extensive C++ GUI application development framework that is - available for Unix, Windows and Mac OS X. :program:`sip` is a tool - for generating bindings for C++ libraries as Python classes, and - is specifically designed for Python. - - `PySide2 `_ - Also known as the Qt for Python project, PySide2 is a newer binding to the - Qt toolkit. It is provided by The Qt Company and aims to provide a - complete port of PySide to Qt 5. Compared to PyQt, its licensing scheme is - friendlier to non-open source applications. - - `wxPython `_ - wxPython is a cross-platform GUI toolkit for Python that is built around - the popular `wxWidgets `_ (formerly wxWindows) - C++ toolkit. It provides a native look and feel for applications on - Windows, Mac OS X, and Unix systems by using each platform's native - widgets where ever possible, (GTK+ on Unix-like systems). In addition to - an extensive set of widgets, wxPython provides classes for online - documentation and context sensitive help, printing, HTML viewing, - low-level device context drawing, drag and drop, system clipboard access, - an XML-based resource format and more, including an ever growing library - of user-contributed modules. - -PyGTK, PyQt, PySide2, and wxPython, all have a modern look and feel and more -widgets than Tkinter. In addition, there are many other GUI toolkits for -Python, both cross-platform, and platform-specific. See the `GUI Programming -`_ page in the Python Wiki for a -much more complete list, and also for links to documents where the -different GUI toolkits are compared. - diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index ed1e9712c0e3de..13e1a1993692d4 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -67,14 +67,13 @@ useful than quitting the debugger upon program's exit. before the first line of the module. -The typical usage to break into the debugger from a running program is to -insert :: +The typical usage to break into the debugger is to insert:: import pdb; pdb.set_trace() -at the location you want to break into the debugger. You can then step through -the code following this statement, and continue running without the debugger -using the :pdbcmd:`continue` command. +at the location you want to break into the debugger, and then run the program. +You can then step through the code following this statement, and continue +running without the debugger using the :pdbcmd:`continue` command. .. versionadded:: 3.7 The built-in :func:`breakpoint()`, when called with defaults, can be used diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index be86e568c180ba..a0eece6c4d8aa0 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -42,7 +42,7 @@ Cross Platform .. note:: - On Mac OS X (and perhaps other platforms), executable files may be + On macOS (and perhaps other platforms), executable files may be universal files containing multiple architectures. To get at the "64-bitness" of the current interpreter, it is more @@ -225,13 +225,13 @@ Windows Platform .. versionadded:: 3.8 -Mac OS Platform ---------------- +macOS Platform +-------------- .. function:: mac_ver(release='', versioninfo=('','',''), machine='') - Get Mac OS version information and return it as tuple ``(release, versioninfo, + Get macOS version information and return it as tuple ``(release, versioninfo, machine)`` with *versioninfo* being a tuple ``(version, dev_stage, non_release_version)``. diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst index ce6d4a85bf5e9d..5ded9661f08014 100644 --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -133,7 +133,7 @@ The following classes are available: encoded data, which contains UID (see PList manual). It has one attribute, :attr:`data`, which can be used to retrieve the int value - of the UID. :attr:`data` must be in the range `0 <= data < 2**64`. + of the UID. :attr:`data` must be in the range ``0 <= data < 2**64``. .. versionadded:: 3.8 diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index f45c66fd9f46fb..8f374503725ad1 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -42,24 +42,36 @@ The :mod:`pprint` module defines one class: compact=False, sort_dicts=True, underscore_numbers=False) Construct a :class:`PrettyPrinter` instance. This constructor understands - several keyword parameters. An output stream may be set using the *stream* - keyword; the only method used on the stream object is the file protocol's - :meth:`write` method. If not specified, the :class:`PrettyPrinter` adopts - ``sys.stdout``. The - amount of indentation added for each recursive level is specified by *indent*; - the default is one. Other values can cause output to look a little odd, but can - make nesting easier to spot. The number of levels which may be printed is - controlled by *depth*; if the data structure being printed is too deep, the next - contained level is replaced by ``...``. By default, there is no constraint on - the depth of the objects being formatted. The desired output width is - constrained using the *width* parameter; the default is 80 characters. If a - structure cannot be formatted within the constrained width, a best effort will - be made. If *compact* is false (the default) each item of a long sequence - will be formatted on a separate line. If *compact* is true, as many items - as will fit within the *width* will be formatted on each output line. If - *sort_dicts* is true (the default), dictionaries will be formatted with their - keys sorted, otherwise they will display in insertion order. If - *underscore_numbers* is true, integers will be formatted with the + several keyword parameters. + + *stream* (default ``sys.stdout``) is a :term:`file-like object` to + which the output will be written by calling its :meth:`write` method. + + Other values configure the manner in which nesting of complex data + structures is displayed. + + *indent* (default 1) specifies the amount of indentation added for + each nesting level. + + *depth* controls the number of nesting levels which may be printed; if + the data structure being printed is too deep, the next contained level + is replaced by ``...``. By default, there is no constraint on the + depth of the objects being formatted. + + *width* (default 80) specifies the desired maximum number of characters per + line in the output. If a structure cannot be formatted within the width + constraint, a best effort will be made. + + *compact* impacts the way that long sequences (lists, tuples, sets, etc) + are formatted. If *compact* is false (the default) then each item of a + sequence will be formatted on a separate line. If *compact* is true, as + many items as will fit within the *width* will be formatted on each output + line. + + If *sort_dicts* is true (the default), dictionaries will be formatted with + their keys sorted, otherwise they will display in insertion order. + + If *underscore_numbers* is true, integers will be formatted with the ``_`` character for a thousands separator, otherwise underscores are not displayed (the default). diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index 774d46d0e96247..cf324a57e79fdf 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -622,7 +622,7 @@ procedure can be used to obtain a better constant for a given platform (see The method executes the number of Python calls given by the argument, directly and again under the profiler, measuring the time for both. It then computes the hidden overhead per profiler event, and returns that as a float. For example, -on a 1.8Ghz Intel Core i5 running Mac OS X, and using Python's time.process_time() as +on a 1.8Ghz Intel Core i5 running macOS, and using Python's time.process_time() as the timer, the magical number is about 4.04e-6. The object of this exercise is to get a fairly consistent result. If your diff --git a/Doc/library/pty.rst b/Doc/library/pty.rst index 73d4f102fd4d8e..7f4da41e93802d 100644 --- a/Doc/library/pty.rst +++ b/Doc/library/pty.rst @@ -2,8 +2,8 @@ ======================================== .. module:: pty - :platform: Linux - :synopsis: Pseudo-Terminal Handling for Linux. + :platform: Unix + :synopsis: Pseudo-Terminal Handling for Unix. .. moduleauthor:: Steen Lumholt .. sectionauthor:: Moshe Zadka @@ -16,9 +16,9 @@ The :mod:`pty` module defines operations for handling the pseudo-terminal concept: starting another process and being able to write to and read from its controlling terminal programmatically. -Because pseudo-terminal handling is highly platform dependent, there is code to -do it only for Linux. (The Linux code is supposed to work on other platforms, -but hasn't been tested yet.) +Pseudo-terminal handling is highly platform dependent. This code is mainly +tested on Linux, FreeBSD, and macOS (it is supposed to work on other POSIX +platforms but it's not been thoroughly tested). The :mod:`pty` module defines the following functions: @@ -47,10 +47,14 @@ The :mod:`pty` module defines the following functions: spawned behind the pty will eventually terminate, and when it does *spawn* will return. + A loop copies STDIN of the current process to the child and data received + from the child to STDOUT of the current process. It is not signaled to the + child if STDIN of the current process closes down. + The functions *master_read* and *stdin_read* are passed a file descriptor which they should read from, and they should always return a byte string. In order to force spawn to return before the child process exits an - :exc:`OSError` should be thrown. + empty byte array should be returned to signal end of file. The default implementation for both functions will read and return up to 1024 bytes each time the function is called. The *master_read* callback is passed @@ -65,10 +69,6 @@ The :mod:`pty` module defines the following functions: process will quit without any input, *spawn* will then loop forever. If *master_read* signals EOF the same behavior results (on linux at least). - If both callbacks signal EOF then *spawn* will probably never return, unless - *select* throws an error on your platform when passed three empty lists. This - is a bug, documented in `issue 26228 `_. - Return the exit status value from :func:`os.waitpid` on the child process. :func:`waitstatus_to_exitcode` can be used to convert the exit status into diff --git a/Doc/library/pydoc.rst b/Doc/library/pydoc.rst index f956b9d2176187..94daf4a58f9c24 100644 --- a/Doc/library/pydoc.rst +++ b/Doc/library/pydoc.rst @@ -18,7 +18,7 @@ The :mod:`pydoc` module automatically generates documentation from Python modules. The documentation can be presented as pages of text on the console, -served to a Web browser, or saved to HTML files. +served to a web browser, or saved to HTML files. For modules, classes, functions and methods, the displayed documentation is derived from the docstring (i.e. the :attr:`__doc__` attribute) of the object, @@ -65,9 +65,9 @@ manner similar to the Unix :program:`man` command. The synopsis line of a module is the first line of its documentation string. You can also use :program:`pydoc` to start an HTTP server on the local machine -that will serve documentation to visiting Web browsers. :program:`pydoc -p 1234` +that will serve documentation to visiting web browsers. :program:`pydoc -p 1234` will start a HTTP server on port 1234, allowing you to browse the -documentation at ``http://localhost:1234/`` in your preferred Web browser. +documentation at ``http://localhost:1234/`` in your preferred web browser. Specifying ``0`` as the port number will select an arbitrary unused port. :program:`pydoc -n ` will start the server listening at the given diff --git a/Doc/library/random.rst b/Doc/library/random.rst index e924127d8b828d..b9c33af59c8fa7 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -512,7 +512,7 @@ between the effects of a drug versus a placebo:: Simulation of arrival times and service deliveries for a multiserver queue:: - from heapq import heappush, heappop + from heapq import heapify, heapreplace from random import expovariate, gauss from statistics import mean, quantiles @@ -524,14 +524,15 @@ Simulation of arrival times and service deliveries for a multiserver queue:: waits = [] arrival_time = 0.0 servers = [0.0] * num_servers # time when each server becomes available - for i in range(100_000): + heapify(servers) + for i in range(1_000_000): arrival_time += expovariate(1.0 / average_arrival_interval) - next_server_available = heappop(servers) + next_server_available = servers[0] wait = max(0.0, next_server_available - arrival_time) waits.append(wait) - service_duration = gauss(average_service_time, stdev_service_time) + service_duration = max(0.0, gauss(average_service_time, stdev_service_time)) service_completed = arrival_time + wait + service_duration - heappush(servers, service_completed) + heapreplace(servers, service_completed) print(f'Mean wait: {mean(waits):.1f} Max wait: {max(waits):.1f}') print('Quartiles:', [round(q, 1) for q in quantiles(waits)]) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 9abbd8ba73616e..b12ce4b9744f94 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -824,10 +824,20 @@ form. .. function:: findall(pattern, string, flags=0) Return all non-overlapping matches of *pattern* in *string*, as a list of - strings. The *string* is scanned left-to-right, and matches are returned in - the order found. If one or more groups are present in the pattern, return a - list of groups; this will be a list of tuples if the pattern has more than - one group. Empty matches are included in the result. + strings or tuples. The *string* is scanned left-to-right, and matches + are returned in the order found. Empty matches are included in the result. + + The result depends on the number of capturing groups in the pattern. + If there are no groups, return a list of strings matching the whole + pattern. If there is exactly one group, return a list of strings + matching that group. If multiple groups are present, return a list + of tuples of strings matching the groups. Non-capturing groups do not + affect the form of the result. + + >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') + ['foot', 'fell', 'fastest'] + >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') + [('width', '20'), ('height', '10')] .. versionchanged:: 3.7 Non-empty matches can now start just after a previous empty match. @@ -931,8 +941,8 @@ form. This is useful if you want to match an arbitrary literal string that may have regular expression metacharacters in it. For example:: - >>> print(re.escape('http://www.python.org')) - http://www\.python\.org + >>> print(re.escape('https://www.python.org')) + https://www\.python\.org >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:" >>> print('[%s]+' % re.escape(legal_chars)) @@ -1562,7 +1572,7 @@ find all of the adverbs in some text, they might use :func:`findall` in the following manner:: >>> text = "He was carefully disguised but captured quickly by police." - >>> re.findall(r"\w+ly", text) + >>> re.findall(r"\w+ly\b", text) ['carefully', 'quickly'] @@ -1576,7 +1586,7 @@ a writer wanted to find all of the adverbs *and their positions* in some text, they would use :func:`finditer` in the following manner:: >>> text = "He was carefully disguised but captured quickly by police." - >>> for m in re.finditer(r"\w+ly", text): + >>> for m in re.finditer(r"\w+ly\b", text): ... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0))) 07-16: carefully 40-47: quickly diff --git a/Doc/library/security_warnings.rst b/Doc/library/security_warnings.rst new file mode 100644 index 00000000000000..26b015c0f8fc7a --- /dev/null +++ b/Doc/library/security_warnings.rst @@ -0,0 +1,34 @@ +.. _security-warnings: + +.. index:: single: security considerations + +Security Considerations +======================= + +The following modules have specific security considerations: + +* :mod:`base64`: :ref:`base64 security considerations ` in + :rfc:`4648` +* :mod:`cgi`: :ref:`CGI security considerations ` +* :mod:`hashlib`: :ref:`all constructors take a "usedforsecurity" keyword-only + argument disabling known insecure and blocked algorithms + ` +* :mod:`http.server` is not suitable for production use, only implementing + basic security checks +* :mod:`logging`: :ref:`Logging configuration uses eval() + ` +* :mod:`multiprocessing`: :ref:`Connection.recv() uses pickle + ` +* :mod:`pickle`: :ref:`Restricting globals in pickle ` +* :mod:`random` shouldn't be used for security purposes, use :mod:`secrets` + instead +* :mod:`shelve`: :ref:`shelve is based on pickle and thus unsuitable for + dealing with untrusted sources ` +* :mod:`ssl`: :ref:`SSL/TLS security considerations ` +* :mod:`subprocess`: :ref:`Subprocess security considerations + ` +* :mod:`tempfile`: :ref:`mktemp is deprecated due to vulnerability to race + conditions ` +* :mod:`xml`: :ref:`XML vulnerabilities ` +* :mod:`zipfile`: :ref:`maliciously prepared .zip files can cause disk volume + exhaustion ` diff --git a/Doc/library/select.rst b/Doc/library/select.rst index a354187c266c7f..46b5ff8b6d5863 100644 --- a/Doc/library/select.rst +++ b/Doc/library/select.rst @@ -534,7 +534,7 @@ https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 | :const:`KQ_FILTER_PROC` | Watch for events on a process id | +---------------------------+---------------------------------------------+ | :const:`KQ_FILTER_NETDEV` | Watch for events on a network device | - | | [not available on Mac OS X] | + | | [not available on macOS] | +---------------------------+---------------------------------------------+ | :const:`KQ_FILTER_SIGNAL` | Returns whenever the watched signal is | | | delivered to the process | @@ -626,7 +626,7 @@ https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 | :const:`KQ_NOTE_TRACKERR` | unable to attach to a child | +----------------------------+--------------------------------------------+ - :const:`KQ_FILTER_NETDEV` filter flags (not available on Mac OS X): + :const:`KQ_FILTER_NETDEV` filter flags (not available on macOS): +----------------------------+--------------------------------------------+ | Constant | Meaning | diff --git a/Doc/library/shelve.rst b/Doc/library/shelve.rst index 07caf91d5b7d99..684f239ef06fa8 100644 --- a/Doc/library/shelve.rst +++ b/Doc/library/shelve.rst @@ -54,13 +54,16 @@ lots of shared sub-objects. The keys are ordinary strings. with shelve.open('spam') as db: db['eggs'] = 'eggs' +.. _shelve-security: + .. warning:: Because the :mod:`shelve` module is backed by :mod:`pickle`, it is insecure to load a shelf from an untrusted source. Like with pickle, loading a shelf can execute arbitrary code. -Shelf objects support all methods supported by dictionaries. This eases the +Shelf objects support most of methods and operations supported by dictionaries +(except copying, constructors and operators ``|`` and ``|=``). This eases the transition from dictionary based scripts to those requiring persistent storage. Two additional methods are supported: diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index d5080da15bba41..11c67074921672 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -595,6 +595,10 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. .. audit-event:: shutil.make_archive base_name,format,root_dir,base_dir shutil.make_archive + .. note:: + + This function is not thread-safe. + .. versionchanged:: 3.8 The modern pax (POSIX.1-2001) format is now used instead of the legacy GNU format for archives created with ``format="tar"``. diff --git a/Doc/library/site.rst b/Doc/library/site.rst index 2e3646f6a74f80..e2ad3c48f9754e 100644 --- a/Doc/library/site.rst +++ b/Doc/library/site.rst @@ -32,7 +32,7 @@ It starts by constructing up to four directories from a head and a tail part. For the head part, it uses ``sys.prefix`` and ``sys.exec_prefix``; empty heads are skipped. For the tail part, it uses the empty string and then :file:`lib/site-packages` (on Windows) or -:file:`lib/python{X.Y}/site-packages` (on Unix and Macintosh). For each +:file:`lib/python{X.Y}/site-packages` (on Unix and macOS). For each of the distinct head-tail combinations, it sees if it refers to an existing directory, and if so, adds it to ``sys.path`` and also inspects the newly added path for configuration files. @@ -176,8 +176,8 @@ Module contents Path to the user site-packages for the running Python. Can be ``None`` if :func:`getusersitepackages` hasn't been called yet. Default value is - :file:`~/.local/lib/python{X.Y}/site-packages` for UNIX and non-framework Mac - OS X builds, :file:`~/Library/Python/{X.Y}/lib/python/site-packages` for Mac + :file:`~/.local/lib/python{X.Y}/site-packages` for UNIX and non-framework + macOS builds, :file:`~/Library/Python/{X.Y}/lib/python/site-packages` for macOS framework builds, and :file:`{%APPDATA%}\\Python\\Python{XY}\\site-packages` on Windows. This directory is a site directory, which means that :file:`.pth` files in it will be processed. @@ -187,8 +187,8 @@ Module contents Path to the base directory for the user site-packages. Can be ``None`` if :func:`getuserbase` hasn't been called yet. Default value is - :file:`~/.local` for UNIX and Mac OS X non-framework builds, - :file:`~/Library/Python/{X.Y}` for Mac framework builds, and + :file:`~/.local` for UNIX and macOS non-framework builds, + :file:`~/Library/Python/{X.Y}` for macOS framework builds, and :file:`{%APPDATA%}\\Python` for Windows. This value is used by Distutils to compute the installation directories for scripts, data files, Python modules, etc. for the :ref:`user installation scheme `. diff --git a/Doc/library/smtpd.rst b/Doc/library/smtpd.rst index d84e74a8ceaaff..803430f1bde173 100644 --- a/Doc/library/smtpd.rst +++ b/Doc/library/smtpd.rst @@ -13,11 +13,10 @@ This module offers several classes to implement SMTP (email) servers. -.. seealso:: - - The `aiosmtpd `_ package is a recommended - replacement for this module. It is based on :mod:`asyncio` and provides a - more straightforward API. :mod:`smtpd` should be considered deprecated. +.. deprecated:: 3.6 + The `aiosmtpd `_ package is a recommended + replacement for this module. It is based on :mod:`asyncio` and provides a + more straightforward API. Several server implementations are present; one is a generic do-nothing implementation, which can be overridden, while the other two offer diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 52220f7a7f30ac..aaab6b11d3bbe5 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -15,7 +15,7 @@ -------------- The :mod:`smtplib` module defines an SMTP client session object that can be used -to send mail to any Internet machine with an SMTP or ESMTP listener daemon. For +to send mail to any internet machine with an SMTP or ESMTP listener daemon. For details of SMTP and ESMTP operation, consult :rfc:`821` (Simple Mail Transfer Protocol) and :rfc:`1869` (SMTP Service Extensions). diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 8a1fc96e0362e2..7ce8e5b0d80381 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -66,7 +66,7 @@ created. Socket addresses are represented as follows: .. _host_port: - A pair ``(host, port)`` is used for the :const:`AF_INET` address family, - where *host* is a string representing either a hostname in Internet domain + where *host* is a string representing either a hostname in internet domain notation like ``'daring.cwi.nl'`` or an IPv4 address like ``'100.50.200.5'``, and *port* is an integer. @@ -197,11 +197,15 @@ created. Socket addresses are represented as follows: - *addr* - Optional bytes-like object specifying the hardware physical address, whose interpretation depends on the device. + .. availability:: Linux >= 2.2. + - :const:`AF_QIPCRTR` is a Linux-only socket based interface for communicating with services running on co-processors in Qualcomm platforms. The address family is represented as a ``(node, port)`` tuple where the *node* and *port* are non-negative integers. + .. availability:: Linux >= 4.7. + .. versionadded:: 3.8 - :const:`IPPROTO_UDPLITE` is a variant of UDP which allows you to specify @@ -379,6 +383,11 @@ Constants On Windows, ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` appear if run-time Windows supports. + .. versionchanged:: 3.10 + ``IP_RECVTOS`` was added. + Added ``TCP_KEEPALIVE``. On MacOS this constant can be used in the same + way that ``TCP_KEEPIDLE`` is used on Linux. + .. data:: AF_CAN PF_CAN SOL_CAN_* @@ -511,7 +520,7 @@ Constants .. data:: AF_LINK - .. availability:: BSD, OSX. + .. availability:: BSD, macOS. .. versionadded:: 3.4 @@ -553,7 +562,7 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) +.. 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), @@ -635,7 +644,7 @@ The following functions all create :ref:`socket objects `. .. function:: create_connection(address[, timeout[, source_address]]) - Connect to a TCP service listening on the Internet *address* (a 2-tuple + Connect to a TCP service listening on the internet *address* (a 2-tuple ``(host, port)``), and return the socket object. This is a higher-level function than :meth:`socket.connect`: if *host* is a non-numeric hostname, it will try to resolve it for both :data:`AF_INET` and :data:`AF_INET6`, @@ -785,9 +794,9 @@ The :mod:`socket` module also offers various network-related services: system if IPv6 isn't enabled):: >>> socket.getaddrinfo("example.org", 80, proto=socket.IPPROTO_TCP) - [(socket.AF_INET6, socket.SOCK_STREAM, + [(, , 6, '', ('2606:2800:220:1:248:1893:25c8:1946', 80, 0, 0)), - (socket.AF_INET, socket.SOCK_STREAM, + (, , 6, '', ('93.184.216.34', 80))] .. versionchanged:: 3.2 @@ -803,8 +812,9 @@ The :mod:`socket` module also offers various network-related services: it is interpreted as the local host. To find the fully qualified name, the hostname returned by :func:`gethostbyaddr` is checked, followed by aliases for the host, if available. The first name which includes a period is selected. In - case no fully qualified domain name is available, the hostname as returned by - :func:`gethostname` is returned. + case no fully qualified domain name is available and *name* was provided, + it is returned unchanged. If *name* was empty or equal to ``'0.0.0.0'``, + the hostname from :func:`gethostname` is returned. .. function:: gethostbyname(hostname) @@ -821,8 +831,8 @@ The :mod:`socket` module also offers various network-related services: .. function:: gethostbyname_ex(hostname) Translate a host name to IPv4 address format, extended interface. Return a - triple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the primary - host name responding to the given *ip_address*, *aliaslist* is a (possibly + triple ``(hostname, aliaslist, ipaddrlist)`` where *hostname* is the host's + primary host name, *aliaslist* is a (possibly empty) list of alternative host names for the same address, and *ipaddrlist* is a list of IPv4 addresses for the same interface on the same host (often but not always a single address). :func:`gethostbyname_ex` does not support IPv6 name @@ -872,7 +882,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: getprotobyname(protocolname) - Translate an Internet protocol name (for example, ``'icmp'``) to a constant + Translate an internet protocol name (for example, ``'icmp'``) to a constant suitable for passing as the (optional) third argument to the :func:`.socket` function. This is usually only needed for sockets opened in "raw" mode (:const:`SOCK_RAW`); for the normal socket modes, the correct protocol is chosen @@ -881,7 +891,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: getservbyname(servicename[, protocolname]) - Translate an Internet service name and protocol name to a port number for that + Translate an internet service name and protocol name to a port number for that service. The optional protocol name, if given, should be ``'tcp'`` or ``'udp'``, otherwise any protocol will match. @@ -890,7 +900,7 @@ The :mod:`socket` module also offers various network-related services: .. function:: getservbyport(port[, protocolname]) - Translate an Internet port number and protocol name to a service name for that + Translate an internet port number and protocol name to a service name for that service. The optional protocol name, if given, should be ``'tcp'`` or ``'udp'``, otherwise any protocol will match. diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 232c0616d925dc..b65a3e8fb2b975 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -15,7 +15,7 @@ There are four basic concrete server classes: .. class:: TCPServer(server_address, RequestHandlerClass, bind_and_activate=True) - This uses the Internet TCP protocol, which provides for + This uses the internet TCP protocol, which provides for continuous streams of data between the client and server. If *bind_and_activate* is true, the constructor automatically attempts to invoke :meth:`~BaseServer.server_bind` and @@ -263,7 +263,7 @@ Server Objects The address on which the server is listening. The format of addresses varies depending on the protocol family; see the documentation for the :mod:`socket` module - for details. For Internet protocols, this is a tuple containing a string giving + for details. For internet protocols, this is a tuple containing a string giving the address, and an integer port number: ``('127.0.0.1', 80)``, for example. diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index d0f28db12fda16..1c3bde3b914d0c 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -21,16 +21,17 @@ The sqlite3 module was written by Gerhard Häring. It provides a SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. -To use the module, you must first create a :class:`Connection` object that +To use the module, start by creating a :class:`Connection` object that represents the database. Here the data will be stored in the :file:`example.db` file:: import sqlite3 con = sqlite3.connect('example.db') -You can also supply the special name ``:memory:`` to create a database in RAM. +The special path name ``:memory:`` can be provided to create a temporary +database in RAM. -Once you have a :class:`Connection`, you can create a :class:`Cursor` object +Once a :class:`Connection` has been established, create a :class:`Cursor` object and call its :meth:`~Cursor.execute` method to perform SQL commands:: cur = con.cursor() @@ -49,16 +50,17 @@ and call its :meth:`~Cursor.execute` method to perform SQL commands:: # Just be sure any changes have been committed or they will be lost. con.close() -The data you've saved is persistent and is available in subsequent sessions:: +The saved data is persistent: it can be reloaded in a subsequent session even +after restarting the Python interpreter:: import sqlite3 con = sqlite3.connect('example.db') cur = con.cursor() -To retrieve data after executing a SELECT statement, you can either treat the -cursor as an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to -retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list of the -matching rows. +To retrieve data after executing a SELECT statement, either treat the cursor as +an :term:`iterator`, call the cursor's :meth:`~Cursor.fetchone` method to +retrieve a single matching row, or call :meth:`~Cursor.fetchall` to get a list +of the matching rows. This example uses the iterator form:: @@ -73,27 +75,27 @@ This example uses the iterator form:: .. _sqlite3-placeholders: -Usually your SQL operations will need to use values from Python variables. You -shouldn't assemble your query using Python's string operations because doing so -is insecure; it makes your program vulnerable to an SQL injection attack -(see the `xkcd webcomic `_ for a humorous example of -what can go wrong):: +SQL operations usually need to use values from Python variables. However, +beware of using Python's string operations to assemble queries, as they +are vulnerable to SQL injection attacks (see the `xkcd webcomic +`_ for a humorous example of what can go wrong):: # Never do this -- insecure! symbol = 'RHAT' cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) -Instead, use the DB-API's parameter substitution. Put a placeholder wherever -you want to use a value, and then provide a tuple of values as the second -argument to the cursor's :meth:`~Cursor.execute` method. An SQL statement may +Instead, use the DB-API's parameter substitution. To insert a variable into a +query string, use a placeholder in the string, and substitute the actual values +into the query by providing them as a :class:`tuple` of values to the second +argument of the cursor's :meth:`~Cursor.execute` method. An SQL statement may use one of two kinds of placeholders: question marks (qmark style) or named placeholders (named style). For the qmark style, ``parameters`` must be a :term:`sequence `. For the named style, it can be either a :term:`sequence ` or :class:`dict` instance. The length of the :term:`sequence ` must match the number of placeholders, or a :exc:`ProgrammingError` is raised. If a :class:`dict` is given, it must contain -keys for all named parameters. Any extra items are ignored. Here's an example -of both styles: +keys for all named parameters. Any extra items are ignored. Here's an example of +both styles: .. literalinclude:: ../includes/sqlite3/execute_1.py @@ -117,6 +119,24 @@ Module functions and constants ------------------------------ +.. data:: apilevel + + String constant stating the supported DB-API level. Required by the DB-API. + Hard-coded to ``"2.0"``. + +.. data:: paramstyle + + String constant stating the type of parameter marker formatting expected by + the :mod:`sqlite3` module. Required by the DB-API. Hard-coded to + ``"qmark"``. + + .. note:: + + The :mod:`sqlite3` module supports both ``qmark`` and ``numeric`` DB-API + parameter styles, because that is what the underlying SQLite library + supports. However, the DB-API does not allow multiple values for + the ``paramstyle`` attribute. + .. data:: version The version number of this module, as a string. This is not the version of @@ -139,6 +159,26 @@ Module functions and constants The version number of the run-time SQLite library, as a tuple of integers. +.. data:: threadsafety + + Integer constant required by the DB-API, stating the level of thread safety + the :mod:`sqlite3` module supports. Currently hard-coded to ``1``, meaning + *"Threads may share the module, but not connections."* However, this may not + always be true. You can check the underlying SQLite library's compile-time + threaded mode using the following query:: + + import sqlite3 + con = sqlite3.connect(":memory:") + con.execute(""" + select * from pragma_compile_options + where compile_options like 'THREADSAFE=%' + """).fetchall() + + Note that the `SQLITE_THREADSAFE levels + `_ do not match the DB-API 2.0 + ``threadsafety`` levels. + + .. data:: PARSE_DECLTYPES This constant is meant to be used with the *detect_types* parameter of the @@ -165,7 +205,7 @@ Module functions and constants does not include the type, i. e. if you use something like ``'as "Expiration date [datetime]"'`` in your SQL, then we will parse out everything until the first ``'['`` for the column name and strip - the preceeding space: the column name would simply be "Expiration date". + the preceding space: the column name would simply be "Expiration date". .. function:: connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri]) @@ -451,14 +491,22 @@ Connection Objects Registers *trace_callback* to be called for each SQL statement that is actually executed by the SQLite backend. - The only argument passed to the callback is the statement (as string) that - is being executed. The return value of the callback is ignored. Note that - the backend does not only run statements passed to the :meth:`Cursor.execute` - methods. Other sources include the transaction management of the Python - module and the execution of triggers defined in the current database. + The only argument passed to the callback is the statement (as + :class:`str`) that is being executed. The return value of the callback is + ignored. Note that the backend does not only run statements passed to the + :meth:`Cursor.execute` methods. Other sources include the + :ref:`transaction management ` of the + sqlite3 module and the execution of triggers defined in the current + database. Passing :const:`None` as *trace_callback* will disable the trace callback. + .. note:: + Exceptions raised in the trace callback are not propagated. As a + development and debugging aid, use + :meth:`~sqlite3.enable_callback_tracebacks` to enable printing + tracebacks from exceptions raised in the trace callback. + .. versionadded:: 3.3 @@ -520,8 +568,8 @@ Connection Objects Using this attribute you can control what objects are returned for the ``TEXT`` data type. By default, this attribute is set to :class:`str` and the - :mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to - return bytestrings instead, you can set it to :class:`bytes`. + :mod:`sqlite3` module will return :class:`str` objects for ``TEXT``. + If you want to return :class:`bytes` instead, you can set it to :class:`bytes`. You can also set it to any other callable that accepts a single bytestring parameter and returns the resulting object. @@ -648,7 +696,8 @@ Cursor Objects This is a nonstandard convenience method for executing multiple SQL statements at once. It issues a ``COMMIT`` statement first, then executes the SQL script it - gets as a parameter. + gets as a parameter. This method disregards :attr:`isolation_level`; any + transaction control must be added to *sql_script*. *sql_script* can be an instance of :class:`str`. @@ -692,6 +741,14 @@ Cursor Objects The cursor will be unusable from this point forward; a :exc:`ProgrammingError` exception will be raised if any operation is attempted with the cursor. + .. method:: setinputsizes(sizes) + + Required by the DB-API. Is a no-op in :mod:`sqlite3`. + + .. method:: setoutputsize(size [, column]) + + Required by the DB-API. Is a no-op in :mod:`sqlite3`. + .. attribute:: rowcount Although the :class:`Cursor` class of the :mod:`sqlite3` module implements this @@ -709,14 +766,15 @@ Cursor Objects .. attribute:: lastrowid - This read-only attribute provides the rowid of the last modified row. It is - only set if you issued an ``INSERT`` or a ``REPLACE`` statement using the - :meth:`execute` method. For operations other than ``INSERT`` or - ``REPLACE`` or when :meth:`executemany` is called, :attr:`lastrowid` is - set to :const:`None`. + This read-only attribute provides the row id of the last inserted row. It + is only updated after successful ``INSERT`` or ``REPLACE`` statements + using the :meth:`execute` method. For other statements, after + :meth:`executemany` or :meth:`executescript`, or if the insertion failed, + the value of ``lastrowid`` is left unchanged. The initial value of + ``lastrowid`` is :const:`None`. - If the ``INSERT`` or ``REPLACE`` statement failed to insert the previous - successful rowid is returned. + .. note:: + Inserts into ``WITHOUT ROWID`` tables are not recorded. .. versionchanged:: 3.6 Added support for the ``REPLACE`` statement. @@ -1017,6 +1075,12 @@ If a timestamp stored in SQLite has a fractional part longer than 6 numbers, its value will be truncated to microsecond precision by the timestamp converter. +.. note:: + + The default "timestamp" converter ignores UTC offsets in the database and + always returns a naive :class:`datetime.datetime` object. To preserve UTC + offsets in timestamps, either leave converters disabled, or register an + offset-aware converter with :func:`register_converter`. .. _sqlite3-controlling-transactions: @@ -1048,6 +1112,9 @@ setting :attr:`isolation_level` to ``None``. This will leave the underlying control the transaction state by explicitly issuing ``BEGIN``, ``ROLLBACK``, ``SAVEPOINT``, and ``RELEASE`` statements in your code. +Note that :meth:`~Cursor.executescript` disregards +:attr:`isolation_level`; any transaction control must be added explicitly. + .. versionchanged:: 3.6 :mod:`sqlite3` used to implicitly commit an open transaction before DDL statements. This is no longer the case. @@ -1097,7 +1164,7 @@ committed: .. rubric:: Footnotes .. [#f1] The sqlite3 module is not built with loadable extension support by - default, because some platforms (notably Mac OS X) have SQLite + default, because some platforms (notably macOS) have SQLite libraries which are compiled without this feature. To get loadable extension support, you must pass the :option:`--enable-loadable-sqlite-extensions` option to configure. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index afa3d87f5767a1..a20f97a26535e8 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -18,7 +18,7 @@ This module provides access to Transport Layer Security (often known as "Secure Sockets Layer") encryption and peer authentication facilities for network sockets, both client-side and server-side. This module uses the OpenSSL -library. It is available on all modern Unix systems, Windows, Mac OS X, and +library. It is available on all modern Unix systems, Windows, macOS, and probably additional platforms, as long as OpenSSL is installed on that platform. .. note:: @@ -681,19 +681,23 @@ Constants .. deprecated:: 3.10 + TLS clients and servers require different default settings for secure + communication. The generic TLS protocol constant is deprecated in + favor of :data:`PROTOCOL_TLS_CLIENT` and :data:`PROTOCOL_TLS_SERVER`. + .. data:: PROTOCOL_TLS_CLIENT - Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`, - but only support client-side :class:`SSLSocket` connections. The protocol - enables :data:`CERT_REQUIRED` and :attr:`~SSLContext.check_hostname` by - default. + Auto-negotiate the highest protocol version that both the client and + server support, and configure the context client-side connections. The + protocol enables :data:`CERT_REQUIRED` and + :attr:`~SSLContext.check_hostname` by default. .. versionadded:: 3.6 .. data:: PROTOCOL_TLS_SERVER - Auto-negotiate the highest protocol version like :data:`PROTOCOL_TLS`, - but only support server-side :class:`SSLSocket` connections. + Auto-negotiate the highest protocol version that both the client and + server support, and configure the context server-side connections. .. versionadded:: 3.6 @@ -1052,7 +1056,7 @@ Constants Option for :func:`create_default_context` and :meth:`SSLContext.load_default_certs`. This value indicates that the - context may be used to authenticate Web servers (therefore, it will + context may be used to authenticate web servers (therefore, it will be used to create client-side sockets). .. versionadded:: 3.4 @@ -1061,7 +1065,7 @@ Constants Option for :func:`create_default_context` and :meth:`SSLContext.load_default_certs`. This value indicates that the - context may be used to authenticate Web clients (therefore, it will + context may be used to authenticate web clients (therefore, it will be used to create server-side sockets). .. versionadded:: 3.4 @@ -1572,7 +1576,7 @@ to speed up repeated connections from the same clients. Load a set of default "certification authority" (CA) certificates from default locations. On Windows it loads CA certs from the ``CA`` and - ``ROOT`` system stores. On other systems it calls + ``ROOT`` system stores. On all systems it calls :meth:`SSLContext.set_default_verify_paths`. In the future the method may load CA certificates from other locations, too. @@ -2066,7 +2070,7 @@ to speed up repeated connections from the same clients. :attr:`SSLContext.verify_flags` returns :class:`VerifyFlags` flags: >>> ssl.create_default_context().verify_flags # doctest: +SKIP - ssl.VERIFY_X509_TRUSTED_FIRST + .. attribute:: SSLContext.verify_mode @@ -2078,7 +2082,7 @@ to speed up repeated connections from the same clients. :attr:`SSLContext.verify_mode` returns :class:`VerifyMode` enum: >>> ssl.create_default_context().verify_mode - ssl.CERT_REQUIRED + .. index:: single: certificates diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst index f48a0a9faa6b0c..98219eaee97619 100644 --- a/Doc/library/stat.rst +++ b/Doc/library/stat.rst @@ -372,11 +372,11 @@ The following flags can be used in the *flags* argument of :func:`os.chflags`: .. data:: UF_COMPRESSED - The file is stored compressed (Mac OS X 10.6+). + The file is stored compressed (macOS 10.6+). .. data:: UF_HIDDEN - The file should not be displayed in a GUI (Mac OS X 10.5+). + The file should not be displayed in a GUI (macOS 10.5+). .. data:: SF_ARCHIVED @@ -398,7 +398,7 @@ The following flags can be used in the *flags* argument of :func:`os.chflags`: The file is a snapshot file. -See the \*BSD or Mac OS systems man page :manpage:`chflags(2)` for more information. +See the \*BSD or macOS systems man page :manpage:`chflags(2)` for more information. On Windows, the following file attribute constants are available for use when testing bits in the ``st_file_attributes`` member returned by :func:`os.stat`. diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 117d2b63cbea15..fd486191c01900 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -76,7 +76,7 @@ These functions calculate statistics regarding relations between two inputs. ========================= ===================================================== :func:`covariance` Sample covariance for two variables. :func:`correlation` Pearson's correlation coefficient for two variables. -:func:`linear_regression` Intercept and slope for simple linear regression. +:func:`linear_regression` Slope and intercept for simple linear regression. ========================= ===================================================== @@ -116,10 +116,11 @@ However, for reading convenience, most of the examples show sorted sequences. .. note:: - The mean is strongly affected by outliers and is not a robust estimator - for central location: the mean is not necessarily a typical example of - the data points. For more robust measures of central location, see - :func:`median` and :func:`mode`. + The mean is strongly affected by `outliers + `_ and is not necessarily a + typical example of the data points. For a more robust, although less + efficient, measure of `central tendency + `_, see :func:`median`. The sample mean gives an unbiased estimate of the true population mean, so that when taken on average over all the possible samples, @@ -626,47 +627,40 @@ However, for reading convenience, most of the examples show sorted sequences. .. versionadded:: 3.10 -.. function:: linear_regression(regressor, dependent_variable) +.. function:: linear_regression(x, y, /) - Return the intercept and slope of `simple linear regression + Return the slope and intercept of `simple linear regression `_ parameters estimated using ordinary least squares. Simple linear - regression describes relationship between *regressor* and - *dependent variable* in terms of linear function: + regression describes the relationship between an independent variable *x* and + a dependent variable *y* in terms of this linear function: - *dependent_variable = intercept + slope \* regressor + noise* + *y = slope \* x + intercept + noise* - where ``intercept`` and ``slope`` are the regression parameters that are - estimated, and noise term is an unobserved random variable, for the + where ``slope`` and ``intercept`` are the regression parameters that are + estimated, and ``noise`` represents the variability of the data that was not explained by the linear regression - (it is equal to the difference between prediction and the actual values - of dependent variable). + (it is equal to the difference between predicted and actual values + of the dependent variable). - Both inputs must be of the same length (no less than two), and regressor - needs not to be constant, otherwise :exc:`StatisticsError` is raised. + Both inputs must be of the same length (no less than two), and + the independent variable *x* cannot be constant; + otherwise a :exc:`StatisticsError` is raised. - For example, if we took the data on the data on `release dates of the Monty - Python films `_, and used - it to predict the cumulative number of Monty Python films produced, we could - predict what would be the number of films they could have made till year - 2019, assuming that they kept the pace. + For example, we can use the `release dates of the Monty + Python films `_ + to predict the cumulative number of Monty Python films + that would have been produced by 2019 + assuming that they had kept the pace. .. doctest:: >>> year = [1971, 1975, 1979, 1982, 1983] >>> films_total = [1, 2, 3, 4, 5] - >>> intercept, slope = linear_regression(year, films_total) - >>> round(intercept + slope * 2019) + >>> slope, intercept = linear_regression(year, films_total) + >>> round(slope * 2019 + intercept) 16 - We could also use it to "predict" how many Monty Python films existed when - Brian Cohen was born. - - .. doctest:: - - >>> round(intercept + slope * 1) - -610 - .. versionadded:: 3.10 diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c4e6b4d1186d04..8fa252b04d7068 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -178,13 +178,14 @@ operators are only defined where they make sense; for example, they raise a single: __ge__() (instance method) Non-identical instances of a class normally compare as non-equal unless the -class defines the :meth:`__eq__` method. +class defines the :meth:`~object.__eq__` method. Instances of a class cannot be ordered with respect to other instances of the same class, or other types of object, unless the class defines enough of the -methods :meth:`__lt__`, :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` (in -general, :meth:`__lt__` and :meth:`__eq__` are sufficient, if you want the -conventional meanings of the comparison operators). +methods :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, and +:meth:`~object.__ge__` (in general, :meth:`~object.__lt__` and +:meth:`~object.__eq__` are sufficient, if you want the conventional meanings of the +comparison operators). The behavior of the :keyword:`is` and :keyword:`is not` operators cannot be customized; also they can be applied to any two objects and never raise an @@ -660,7 +661,7 @@ Hashing of numeric types ------------------------ For numbers ``x`` and ``y``, possibly of different types, it's a requirement -that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`__hash__` +that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`~object.__hash__` method documentation for more details). For ease of implementation and efficiency across a variety of numeric types (including :class:`int`, :class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`) @@ -739,7 +740,7 @@ number, :class:`float`, or :class:`complex`:: """Compute the hash of a float x.""" if math.isnan(x): - return super().__hash__() + return object.__hash__(x) elif math.isinf(x): return sys.hash_info.inf if x > 0 else -sys.hash_info.inf else: @@ -772,21 +773,21 @@ using two distinct methods; these are used to allow user-defined classes to support iteration. Sequences, described below in more detail, always support the iteration methods. -One method needs to be defined for container objects to provide iteration +One method needs to be defined for container objects to provide :term:`iterable` support: .. XXX duplicated in reference/datamodel! .. method:: container.__iter__() - Return an iterator object. The object is required to support the iterator - protocol described below. If a container supports different types of - iteration, additional methods can be provided to specifically request + Return an :term:`iterator` object. The object is required to support the + iterator protocol described below. If a container supports different types + of iteration, additional methods can be provided to specifically request iterators for those iteration types. (An example of an object supporting multiple forms of iteration would be a tree structure which supports both breadth-first and depth-first traversal.) This method corresponds to the - :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python objects in the Python/C - API. + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. The iterator objects themselves are required to support the following two methods, which together form the :dfn:`iterator protocol`: @@ -794,18 +795,19 @@ methods, which together form the :dfn:`iterator protocol`: .. method:: iterator.__iter__() - Return the iterator object itself. This is required to allow both containers - and iterators to be used with the :keyword:`for` and :keyword:`in` statements. - This method corresponds to the :c:member:`~PyTypeObject.tp_iter` slot of the type structure for - Python objects in the Python/C API. + Return the :term:`iterator` object itself. This is required to allow both + containers and iterators to be used with the :keyword:`for` and + :keyword:`in` statements. This method corresponds to the + :c:member:`~PyTypeObject.tp_iter` slot of the type structure for Python + objects in the Python/C API. .. method:: iterator.__next__() - Return the next item from the container. If there are no further items, raise - the :exc:`StopIteration` exception. This method corresponds to the - :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for Python objects in the - Python/C API. + Return the next item from the :term:`iterator`. If there are no further + items, raise the :exc:`StopIteration` exception. This method corresponds to + the :c:member:`~PyTypeObject.tp_iternext` slot of the type structure for + Python objects in the Python/C API. Python defines several iterator objects to support iteration over general and specific sequence types, dictionaries, and other more specialized forms. The @@ -919,6 +921,16 @@ This means that to compare equal, every element must compare equal and the two sequences must be of the same type and have the same length. (For full details see :ref:`comparisons` in the language reference.) +.. index:: + single: loop; over mutable sequence + single: mutable sequence; loop over + +Forward and reversed iterators over mutable sequences access values using an +index. That index will continue to march forward (or backward) even if the +underlying sequence is mutated. The iterator terminates only when an +:exc:`IndexError` or a :exc:`StopIteration` is encountered (or when the index +drops below zero). + Notes: (1) @@ -1112,7 +1124,7 @@ accepts integers that meet the value restriction ``0 <= x <= 255``). | | index given by *i* | | | | (same as ``s[i:i] = [x]``) | | +------------------------------+--------------------------------+---------------------+ -| ``s.pop([i])`` | retrieves the item at *i* and | \(2) | +| ``s.pop()`` or ``s.pop(i)`` | retrieves the item at *i* and | \(2) | | | also removes it from *s* | | +------------------------------+--------------------------------+---------------------+ | ``s.remove(x)`` | remove the first item from *s* | \(3) | @@ -1295,7 +1307,7 @@ loops. range(start, stop[, step]) The arguments to the range constructor must be integers (either built-in - :class:`int` or any object that implements the ``__index__`` special + :class:`int` or any object that implements the :meth:`~object.__index__` special method). If the *step* argument is omitted, it defaults to ``1``. If the *start* argument is omitted, it defaults to ``0``. If *step* is zero, :exc:`ValueError` is raised. @@ -1423,7 +1435,7 @@ Strings are immutable written in a variety of ways: * Single quotes: ``'allows embedded "double" quotes'`` -* Double quotes: ``"allows embedded 'single' quotes"``. +* Double quotes: ``"allows embedded 'single' quotes"`` * Triple quoted: ``'''Three single quotes'''``, ``"""Three double quotes"""`` Triple quoted strings may span multiple lines - all associated whitespace will @@ -1749,9 +1761,9 @@ expression support in the :mod:`re` module). >>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') - True, False + (True, False) >>> 'def'.isidentifier(), iskeyword('def') - True, True + (True, True) .. method:: str.islower() @@ -2018,7 +2030,7 @@ expression support in the :mod:`re` module). .. index:: single: universal newlines; str.splitlines method -.. method:: str.splitlines([keepends]) +.. method:: str.splitlines(keepends=False) Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless *keepends* is given and @@ -2431,7 +2443,7 @@ data and are closely related to string objects in a variety of other ways. literals, except that a ``b`` prefix is added: * Single quotes: ``b'still allows embedded "double" quotes'`` - * Double quotes: ``b"still allows embedded 'single' quotes"``. + * Double quotes: ``b"still allows embedded 'single' quotes"`` * Triple quoted: ``b'''3 single quotes'''``, ``b"""3 double quotes"""`` Only ASCII characters are permitted in bytes literals (regardless of the @@ -3632,17 +3644,16 @@ Memory Views of an object that supports the :ref:`buffer protocol ` without copying. -.. class:: memoryview(obj) +.. class:: memoryview(object) - Create a :class:`memoryview` that references *obj*. *obj* must support the - buffer protocol. Built-in objects that support the buffer protocol include - :class:`bytes` and :class:`bytearray`. + Create a :class:`memoryview` that references *object*. *object* must + support the buffer protocol. Built-in objects that support the buffer + protocol include :class:`bytes` and :class:`bytearray`. A :class:`memoryview` has the notion of an *element*, which is the - atomic memory unit handled by the originating object *obj*. For many - simple types such as :class:`bytes` and :class:`bytearray`, an element - is a single byte, but other types such as :class:`array.array` may have - bigger elements. + atomic memory unit handled by the originating *object*. For many simple + types such as :class:`bytes` and :class:`bytearray`, an element is a single + byte, but other types such as :class:`array.array` may have bigger elements. ``len(view)`` is equal to the length of :class:`~memoryview.tolist`. If ``view.ndim = 0``, the length is 1. If ``view.ndim = 1``, the length @@ -4333,9 +4344,9 @@ Dictionaries can be created by placing a comma-separated list of ``key: value`` pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: 'jack', 4127: 'sjoerd'}``, or by the :class:`dict` constructor. -.. class:: dict(**kwarg) - dict(mapping, **kwarg) - dict(iterable, **kwarg) +.. class:: dict(**kwargs) + dict(mapping, **kwargs) + dict(iterable, **kwargs) Return a new dictionary initialized from an optional positional argument and a possibly empty set of keyword arguments. @@ -4755,9 +4766,9 @@ their implementation of the context management protocol. See the Python's :term:`generator`\s and the :class:`contextlib.contextmanager` decorator provide a convenient way to implement these protocols. If a generator function is decorated with the :class:`contextlib.contextmanager` decorator, it will return a -context manager implementing the necessary :meth:`__enter__` and -:meth:`__exit__` methods, rather than the iterator produced by an undecorated -generator function. +context manager implementing the necessary :meth:`~contextmanager.__enter__` and +:meth:`~contextmanager.__exit__` methods, rather than the iterator produced by an +undecorated generator function. Note that there is no specific slot for any of these methods in the type structure for Python objects in the Python/C API. Extension types wanting to @@ -5041,16 +5052,16 @@ enables cleaner type hinting syntax compared to :data:`typing.Union`. TypeError: isinstance() argument 2 cannot contain a parameterized generic The user-exposed type for the union object can be accessed from -:data:`types.Union` and used for :func:`isinstance` checks. An object cannot be +:data:`types.UnionType` and used for :func:`isinstance` checks. An object cannot be instantiated from the type:: >>> import types - >>> isinstance(int | str, types.Union) + >>> isinstance(int | str, types.UnionType) True - >>> types.Union() + >>> types.UnionType() Traceback (most recent call last): File "", line 1, in - TypeError: cannot create 'types.Union' instances + TypeError: cannot create 'types.UnionType' instances .. note:: The :meth:`__or__` method for type objects was added to support the syntax diff --git a/Doc/library/string.rst b/Doc/library/string.rst index d935419f7b75e7..b27782f8d8e9b4 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -386,8 +386,8 @@ The ``'#'`` option causes the "alternate form" to be used for the conversion. The alternate form is defined differently for different types. This option is only valid for integer, float and complex types. For integers, when binary, octal, or hexadecimal output -is used, this option adds the prefix respective ``'0b'``, ``'0o'``, or -``'0x'`` to the output value. For float and complex the +is used, this option adds the respective prefix ``'0b'``, ``'0o'``, +``'0x'``, or ``'0X'`` to the output value. For float and complex the alternate form causes the result of the conversion to always contain a decimal-point character, even if no digits follow it. Normally, a decimal-point character appears in the result of these conversions @@ -467,6 +467,8 @@ The available integer presentation types are: +---------+----------------------------------------------------------+ | ``'X'`` | Hex format. Outputs the number in base 16, using | | | upper-case letters for the digits above 9. | + | | In case ``'#'`` is specified, the prefix ``'0x'`` will | + | | be upper-cased to ``'0X'`` as well. | +---------+----------------------------------------------------------+ | ``'n'`` | Number. This is the same as ``'d'``, except that it uses | | | the current locale setting to insert the appropriate | diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index b60db58d182e6c..21a96a4bd5ff5d 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -689,7 +689,10 @@ execute, will be re-raised in the parent. The most common exception raised is :exc:`OSError`. This occurs, for example, when trying to execute a non-existent file. Applications should prepare for -:exc:`OSError` exceptions. +:exc:`OSError` exceptions. Note that, when ``shell=True``, :exc:`OSError` +will be raised by the child only if the selected shell itself was not found. +To determine if the shell failed to find the requested application, it is +necessary to check the return code or output from the subprocess. A :exc:`ValueError` will be raised if :class:`Popen` is called with invalid arguments. @@ -707,6 +710,7 @@ Exceptions defined in this module all inherit from :exc:`SubprocessError`. .. versionadded:: 3.3 The :exc:`SubprocessError` base class was added. +.. _subprocess-security: Security Considerations ----------------------- @@ -1145,6 +1149,8 @@ calls these functions. code was zero then return, otherwise raise :exc:`CalledProcessError`. The :exc:`CalledProcessError` object will have the return code in the :attr:`~CalledProcessError.returncode` attribute. + If :func:`check_call` was unable to start the process it will propagate the exception + that was raised. Code needing to capture stdout or stderr should use :func:`run` instead:: @@ -1292,11 +1298,17 @@ Replacing :func:`os.system` sts = os.system("mycmd" + " myarg") # becomes - sts = call("mycmd" + " myarg", shell=True) + retcode = call("mycmd" + " myarg", shell=True) Notes: * Calling the program through the shell is usually not required. +* The :func:`call` return value is encoded differently to that of + :func:`os.system`. + +* The :func:`os.system` function ignores SIGINT and SIGQUIT signals while + the command is running, but the caller must do this separately when + using the :mod:`subprocess` module. A more realistic example would look like this:: diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index ec12e02fb37d45..29cb54b5d1ac30 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1073,7 +1073,11 @@ always available. This is a dictionary that maps module names to modules which have already been loaded. This can be manipulated to force reloading of modules and other tricks. However, replacing the dictionary will not necessarily work as expected and - deleting essential items from the dictionary may cause Python to fail. + deleting essential items from the dictionary may cause Python to fail. If + you want to iterate over this global dictionary always use + ``sys.modules.copy()`` or ``tuple(sys.modules)`` to avoid exceptions as its + size may change during iteration as a side effect of code or activity in + other threads. .. data:: orig_argv @@ -1212,13 +1216,10 @@ always available. .. data:: prefix A string giving the site-specific directory prefix where the platform - independent Python files are installed; by default, this is the string + independent Python files are installed; on Unix, the default is ``'/usr/local'``. This can be set at build time with the ``--prefix`` - argument to the :program:`configure` script. The main collection of Python - library modules is installed in the directory :file:`{prefix}/lib/python{X.Y}` - while the platform independent header files (all except :file:`pyconfig.h`) are - stored in :file:`{prefix}/include/python{X.Y}`, where *X.Y* is the version - number of Python, for example ``3.2``. + argument to the :program:`configure` script. See + :ref:`installation_paths` for derived paths. .. note:: If a :ref:`virtual environment ` is in effect, this value will be changed in ``site.py`` to point to the virtual diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst index bb8e2d88c0fc95..7ef3b2489673e6 100644 --- a/Doc/library/sysconfig.rst +++ b/Doc/library/sysconfig.rst @@ -60,6 +60,7 @@ Example of usage:: >>> sysconfig.get_config_vars('AR', 'CXX') ['ar', 'g++'] +.. _installation_paths: Installation paths ------------------ @@ -72,9 +73,9 @@ Every new component that is installed using :mod:`distutils` or a Distutils-based system will follow the same scheme to copy its file in the right places. -Python currently supports seven schemes: +Python currently supports six schemes: -- *posix_prefix*: scheme for POSIX platforms like Linux or Mac OS X. This is +- *posix_prefix*: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed. - *posix_home*: scheme for POSIX platforms used when a *home* option is used upon installation. This scheme is used when a component is installed through @@ -84,6 +85,7 @@ Python currently supports seven schemes: located under the user home directory. - *nt*: scheme for NT platforms like Windows. - *nt_user*: scheme for NT platforms, when the *user* option is used. +- *osx_framework_user*: scheme for macOS, when the *user* option is used. Each scheme is itself composed of a series of paths and each path has a unique identifier. Python currently uses eight paths: @@ -175,7 +177,7 @@ identifier. Python currently uses eight paths: If *expand* is set to ``False``, the path will not be expanded using the variables. - If *name* is not found, return ``None``. + If *name* is not found, raise a :exc:`KeyError`. .. function:: get_paths([scheme, [vars, [expand]]]) @@ -225,7 +227,7 @@ Other functions - win-amd64 (64bit Windows on AMD64, aka x86_64, Intel64, and EM64T) - win32 (all others - specifically, sys.platform is returned) - Mac OS X can return: + macOS can return: - macosx-10.6-ppc - macosx-10.4-ppc64 diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 13088a10d77c57..6afb8397b7866d 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -102,6 +102,9 @@ Some facts and figures: ``'x:bz2'``, :func:`tarfile.open` accepts the keyword argument *compresslevel* (default ``9``) to specify the compression level of the file. + For modes ``'w:xz'`` and ``'x:xz'``, :func:`tarfile.open` accepts the + keyword argument *preset* to specify the compression level of the file. + For special purposes, there is a second format for *mode*: ``'filemode|[compression]'``. :func:`tarfile.open` will return a :class:`TarFile` object that processes its data as a stream of blocks. No random seeking will diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst index 2970252036780d..b8a5fa0027ffbd 100644 --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -341,6 +341,7 @@ Here are some examples of typical usage of the :mod:`tempfile` module:: >>> # directory and contents have been removed +.. _tempfile-mktemp-deprecated: Deprecated functions and variables ---------------------------------- diff --git a/Doc/library/test.rst b/Doc/library/test.rst index e4f779bd83eb87..a8dc35476fc9bd 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -267,10 +267,10 @@ The :mod:`test.support` module defines the following constants: .. data:: INTERNET_TIMEOUT - Timeout in seconds for network requests going to the Internet. + Timeout in seconds for network requests going to the internet. The timeout is short enough to prevent a test to wait for too long if the - Internet request is blocked for whatever reason. + internet request is blocked for whatever reason. Usually, a timeout using :data:`INTERNET_TIMEOUT` should not mark a test as failed, but skip the test instead: see @@ -684,8 +684,8 @@ The :mod:`test.support` module defines the following functions: .. decorator:: requires_mac_version(*min_version) - Decorator for the minimum version when running test on Mac OS X. If the - MAC OS X version is less than the minimum, raise :exc:`unittest.SkipTest`. + Decorator for the minimum version when running test on macOS. If the + macOS version is less than the minimum, raise :exc:`unittest.SkipTest`. .. decorator:: requires_IEEE_754 @@ -928,8 +928,16 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.10 +.. function:: check_disallow_instantiation(test_case, tp, *args, **kwds) + + Assert that type *tp* cannot be instantiated using *args* and *kwds*. + + .. versionadded:: 3.10 + + The :mod:`test.support` module defines the following classes: + .. class:: SuppressCrashReport() A context manager used to try to prevent crash dialog popups on tests that @@ -1241,7 +1249,7 @@ The :mod:`test.support.threading_helper` module provides support for threading t Context manager catching :class:`threading.Thread` exception using :func:`threading.excepthook`. - Attributes set when an exception is catched: + Attributes set when an exception is caught: * ``exc_type`` * ``exc_value`` @@ -1450,7 +1458,7 @@ The :mod:`test.support.os_helper` module provides support for os tests. .. function:: unlink(filename) Call :func:`os.unlink` on *filename*. On Windows platforms, this is - wrapped with a wait loop that checks for the existence fo the file. + wrapped with a wait loop that checks for the existence of the file. :mod:`test.support.import_helper` --- Utilities for import tests diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst index 16837104b6cebc..7780e241769657 100644 --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -17,20 +17,29 @@ If you're just wrapping or filling one or two text strings, the convenience functions should be good enough; otherwise, you should use an instance of :class:`TextWrapper` for efficiency. -.. function:: wrap(text, width=70, **kwargs) +.. function:: wrap(text, width=70, *, initial_indent="", \ + subsequent_indent="", expand_tabs=True, \ + replace_whitespace=True, fix_sentence_endings=False, \ + break_long_words=True, drop_whitespace=True, \ + break_on_hyphens=True, tabsize=8, max_lines=None) Wraps the single paragraph in *text* (a string) so every line is at most *width* characters long. Returns a list of output lines, without final newlines. Optional keyword arguments correspond to the instance attributes of - :class:`TextWrapper`, documented below. *width* defaults to ``70``. + :class:`TextWrapper`, documented below. See the :meth:`TextWrapper.wrap` method for additional details on how :func:`wrap` behaves. -.. function:: fill(text, width=70, **kwargs) +.. function:: fill(text, width=70, *, initial_indent="", \ + subsequent_indent="", expand_tabs=True, \ + replace_whitespace=True, fix_sentence_endings=False, \ + break_long_words=True, drop_whitespace=True, \ + break_on_hyphens=True, tabsize=8, \ + max_lines=None) Wraps the single paragraph in *text*, and returns a single string containing the wrapped paragraph. :func:`fill` is shorthand for :: @@ -41,7 +50,9 @@ functions should be good enough; otherwise, you should use an instance of :func:`wrap`. -.. function:: shorten(text, width, **kwargs) +.. function:: shorten(text, width, *, fix_sentence_endings=False, \ + break_long_words=True, break_on_hyphens=True, \ + placeholder=' [...]') Collapse and truncate the given *text* to fit in the given *width*. @@ -65,7 +76,6 @@ functions should be good enough; otherwise, you should use an instance of .. versionadded:: 3.4 - .. function:: dedent(text) Remove any common leading whitespace from every line in *text*. diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 16f23c3a0c3548..8c7664328a49df 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -121,10 +121,11 @@ This module defines the following functions: .. function:: enumerate() - Return a list of all :class:`Thread` objects currently alive. The list - includes daemonic threads, dummy thread objects created by - :func:`current_thread`, and the main thread. It excludes terminated threads - and threads that have not yet been started. + Return a list of all :class:`Thread` objects currently active. The list + includes daemonic threads and dummy thread objects created by + :func:`current_thread`. It excludes terminated threads and threads + that have not yet been started. However, the main thread is always part + of the result, even when terminated. .. function:: main_thread() diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index 668fcb860cea87..d4e8b749db4808 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -15,8 +15,8 @@ This module provides a simple way to time small bits of Python code. It has both a :ref:`timeit-command-line-interface` as well as a :ref:`callable ` one. It avoids a number of common traps for measuring execution times. -See also Tim Peters' introduction to the "Algorithms" chapter in the *Python -Cookbook*, published by O'Reilly. +See also Tim Peters' introduction to the "Algorithms" chapter in the second +edition of *Python Cookbook*, published by O'Reilly. Basic Examples diff --git a/Doc/library/tk.rst b/Doc/library/tk.rst index c6c73f057cab16..0cb8fda4e32ebb 100644 --- a/Doc/library/tk.rst +++ b/Doc/library/tk.rst @@ -19,16 +19,15 @@ The :mod:`tkinter` package is a thin object-oriented layer on top of Tcl/Tk. To use :mod:`tkinter`, you don't need to write Tcl code, but you will need to consult the Tk documentation, and occasionally the Tcl documentation. :mod:`tkinter` is a set of wrappers that implement the Tk widgets as Python -classes. In addition, the internal module :mod:`_tkinter` provides a threadsafe -mechanism which allows Python and Tcl to interact. +classes. :mod:`tkinter`'s chief virtues are that it is fast, and that it usually comes bundled with Python. Although its standard documentation is weak, good material is available, which includes: references, tutorials, a book and others. :mod:`tkinter` is also famous for having an outdated look and feel, which has been vastly improved in Tk 8.5. Nevertheless, there are many other -GUI libraries that you could be interested in. For more information about -alternatives, see the :ref:`other-gui-packages` section. +GUI libraries that you could be interested in. The Python wiki lists several +alternative `GUI frameworks and tools `_. .. toctree:: @@ -42,7 +41,6 @@ alternatives, see the :ref:`other-gui-packages` section. tkinter.ttk.rst tkinter.tix.rst idle.rst - othergui.rst .. Other sections I have in mind are Tkinter internals diff --git a/Doc/library/tkinter.rst b/Doc/library/tkinter.rst index 7739f2f60a7980..a48bc13c8b436b 100644 --- a/Doc/library/tkinter.rst +++ b/Doc/library/tkinter.rst @@ -11,80 +11,117 @@ -------------- The :mod:`tkinter` package ("Tk interface") is the standard Python interface to -the Tk GUI toolkit. Both Tk and :mod:`tkinter` are available on most Unix -platforms, as well as on Windows systems. (Tk itself is not part of Python; it -is maintained at ActiveState.) +the Tcl/Tk GUI toolkit. Both Tk and :mod:`tkinter` are available on most Unix +platforms, including macOS, as well as on Windows systems. Running ``python -m tkinter`` from the command line should open a window demonstrating a simple Tk interface, letting you know that :mod:`tkinter` is properly installed on your system, and also showing what version of Tcl/Tk is installed, so you can read the Tcl/Tk documentation specific to that version. +Tkinter supports a range of Tcl/Tk versions, built either with or +without thread support. The official Python binary release bundles Tcl/Tk 8.6 +threaded. See the source code for the :mod:`_tkinter` module +for more information about supported versions. + +Tkinter is not a thin wrapper, but adds a fair amount of its own logic to +make the experience more pythonic. This documentation will concentrate on these +additions and changes, and refer to the official Tcl/Tk documentation for +details that are unchanged. + +.. note:: + + Tcl/Tk 8.5 (2007) introduced a modern set of themed user interface components + along with a new API to use them. Both old and new APIs are still available. + Most documentation you will find online still uses the old API and + can be woefully outdated. + .. seealso:: - Tkinter documentation: + * `TkDocs `_ + Extensive tutorial on creating user interfaces with Tkinter. Explains key concepts, + and illustrates recommended approaches using the modern API. - `Python Tkinter Resources `_ - The Python Tkinter Topic Guide provides a great deal of information on using Tk - from Python and links to other sources of information on Tk. + * `Tkinter 8.5 reference: a GUI for Python `_ + Reference documentation for Tkinter 8.5 detailing available classes, methods, and options. - `TKDocs `_ - Extensive tutorial plus friendlier widget pages for some of the widgets. + Tcl/Tk Resources: - `Tkinter 8.5 reference: a GUI for Python `_ - On-line reference material. + * `Tk commands `_ + Comprehensive reference to each of the underlying Tcl/Tk commands used by Tkinter. - `Tkinter docs from effbot `_ - Online reference for tkinter supported by effbot.org. + * `Tcl/Tk Home Page `_ + Additional documentation, and links to Tcl/Tk core development. - `Programming Python `_ - Book by Mark Lutz, has excellent coverage of Tkinter. + Books: - `Modern Tkinter for Busy Python Developers `_ - Book by Mark Roseman about building attractive and modern graphical user interfaces with Python and Tkinter. + * `Modern Tkinter for Busy Python Developers `_ + By Mark Roseman. (ISBN 978-1999149567) - `Python and Tkinter Programming `_ - Book by John Grayson (ISBN 1-884777-81-3). + * `Python and Tkinter Programming `_ + By Alan Moore. (ISBN 978-1788835886) - Tcl/Tk documentation: + * `Programming Python `_ + By Mark Lutz; has excellent coverage of Tkinter. (ISBN 978-0596158101) - `Tk commands `_ - Most commands are available as :mod:`tkinter` or :mod:`tkinter.ttk` classes. - Change '8.6' to match the version of your Tcl/Tk installation. + * `Tcl and the Tk Toolkit (2nd edition) `_ + By John Ousterhout, inventor of Tcl/Tk, and Ken Jones; does not cover Tkinter. (ISBN 978-0321336330) - `Tcl/Tk recent man pages `_ - Recent Tcl/Tk manuals on www.tcl.tk. - `ActiveState Tcl Home Page `_ - The Tk/Tcl development is largely taking place at ActiveState. +Architecture +------------ - `Tcl and the Tk Toolkit `_ - Book by John Ousterhout, the inventor of Tcl. +Tcl/Tk is not a single library but rather consists of a few distinct +modules, each with separate functionality and its own official +documentation. Python's binary releases also ship an add-on module +together with it. - `Practical Programming in Tcl and Tk `_ - Brent Welch's encyclopedic book. +Tcl + Tcl is a dynamic interpreted programming language, just like Python. Though + it can be used on its own as a general-purpose programming language, it is + most commonly embedded into C applications as a scripting engine or an + interface to the Tk toolkit. The Tcl library has a C interface to + create and manage one or more instances of a Tcl interpreter, run Tcl + commands and scripts in those instances, and add custom commands + implemented in either Tcl or C. Each interpreter has an event queue, + and there are facilities to send events to it and process them. + Unlike Python, Tcl's execution model is designed around cooperative + multitasking, and Tkinter bridges this difference + (see `Threading model`_ for details). +Tk + Tk is a `Tcl package `_ implemented in C + that adds custom commands to create and manipulate GUI widgets. Each + :class:`Tk` object embeds its own Tcl interpreter instance with Tk loaded into + it. Tk's widgets are very customizable, though at the cost of a dated appearance. + Tk uses Tcl's event queue to generate and process GUI events. -Tkinter Modules ---------------- +Ttk + Themed Tk (Ttk) is a newer family of Tk widgets that provide a much better + appearance on different platforms than many of the classic Tk widgets. + Ttk is distributed as part of Tk, starting with Tk version 8.5. Python + bindings are provided in a separate module, :mod:`tkinter.ttk`. -Most of the time, :mod:`tkinter` is all you really need, but a number of -additional modules are available as well. The Tk interface is located in a -binary module named :mod:`_tkinter`. This module contains the low-level -interface to Tk, and should never be used directly by application programmers. -It is usually a shared library (or DLL), but might in some cases be statically -linked with the Python interpreter. +Internally, Tk and Ttk use facilities of the underlying operating system, +i.e., Xlib on Unix/X11, Cocoa on macOS, GDI on Windows. -In addition to the Tk interface module, :mod:`tkinter` includes a number of -Python modules, :mod:`tkinter.constants` being one of the most important. -Importing :mod:`tkinter` will automatically import :mod:`tkinter.constants`, -so, usually, to use Tkinter all you need is a simple import statement:: +When your Python application uses a class in Tkinter, e.g., to create a widget, +the :mod:`tkinter` module first assembles a Tcl/Tk command string. It passes that +Tcl command string to an internal :mod:`_tkinter` binary module, which then +calls the Tcl interpreter to evaluate it. The Tcl interpreter will then call into the +Tk and/or Ttk packages, which will in turn make calls to Xlib, Cocoa, or GDI. - import tkinter -Or, more often:: +Tkinter Modules +--------------- + +Support for Tkinter is spread across several modules. Most applications will need the +main :mod:`tkinter` module, as well as the :mod:`tkinter.ttk` module, which provides +the modern themed widget set and API:: + from tkinter import * + from tkinter import ttk .. class:: Tk(screenName=None, baseName=None, className='Tk', useTk=1) @@ -107,7 +144,10 @@ Or, more often:: subsystem initialized) by calling its :meth:`loadtk` method. -Other modules that provide Tk support include: +The modules that provide Tk support include: + +:mod:`tkinter` + Main Tkinter module. :mod:`tkinter.colorchooser` Dialog to let the user choose a color. @@ -130,9 +170,35 @@ Other modules that provide Tk support include: :mod:`tkinter.simpledialog` Basic dialogs and convenience functions. +:mod:`tkinter.ttk` + Themed widget set introduced in Tk 8.5, providing modern alternatives + for many of the classic widgets in the main :mod:`tkinter` module. + +Additional modules: + +:mod:`_tkinter` + A binary module that contains the low-level interface to Tcl/Tk. + It is automatically imported by the main :mod:`tkinter` module, + and should never be used directly by application programmers. + It is usually a shared library (or DLL), but might in some cases be + statically linked with the Python interpreter. + +:mod:`idlelib` + Python's Integrated Development and Learning Environment (IDLE). Based + on :mod:`tkinter`. + +:mod:`tkinter.constants` + Symbolic constants that can be used in place of strings when passing + various parameters to Tkinter calls. Automatically imported by the + main :mod:`tkinter` module. + :mod:`tkinter.dnd` - Drag-and-drop support for :mod:`tkinter`. This is experimental and should - become deprecated when it is replaced with the Tk DND. + (experimental) Drag-and-drop support for :mod:`tkinter`. This will + become deprecated when it is replaced with the Tk DND. + +:mod:`tkinter.tix` + (deprecated) An older third-party Tcl/Tk package that adds several new + widgets. Better alternatives for most can be found in :mod:`tkinter.ttk`. :mod:`turtle` Turtle graphics in a Tk window. @@ -141,243 +207,294 @@ Other modules that provide Tk support include: Tkinter Life Preserver ---------------------- -.. sectionauthor:: Matt Conway - - This section is not designed to be an exhaustive tutorial on either Tk or -Tkinter. Rather, it is intended as a stop gap, providing some introductory -orientation on the system. +Tkinter. For that, refer to one of the external resources noted earlier. +Instead, this section provides a very quick orientation to what a Tkinter +application looks like, identifies foundational Tk concepts, and +explains how the Tkinter wrapper is structured. -Credits: +The remainder of this section will help you to identify the classes, +methods, and options you'll need in your Tkinter application, and where to +find more detailed documentation on them, including in the official Tcl/Tk +reference manual. -* Tk was written by John Ousterhout while at Berkeley. -* Tkinter was written by Steen Lumholt and Guido van Rossum. +A Hello World Program +^^^^^^^^^^^^^^^^^^^^^ -* This Life Preserver was written by Matt Conway at the University of Virginia. +We'll start by walking through a "Hello World" application in Tkinter. This +isn't the smallest one we could write, but has enough to illustrate some +key concepts you'll need to know. -* The HTML rendering, and some liberal editing, was produced from a FrameMaker - version by Ken Manheimer. +:: -* Fredrik Lundh elaborated and revised the class interface descriptions, to get - them current with Tk 4.2. + from tkinter import * + from tkinter import ttk + root = Tk() + frm = ttk.Frame(root, padding=10) + frm.grid() + ttk.Label(frm, text="Hello World!").grid(column=0, row=0) + ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0) + root.mainloop() -* Mike Clarkson converted the documentation to LaTeX, and compiled the User - Interface chapter of the reference manual. +After the imports, the next line creates an instance of the :class:`Tk` class, +which initializes Tk and creates its associated Tcl interpreter. It also +creates a toplevel window, known as the root window, which serves as the main +window of the application. -How To Use This Section -^^^^^^^^^^^^^^^^^^^^^^^ +The following line creates a frame widget, which in this case will contain +a label and a button we'll create next. The frame is fit inside the root +window. -This section is designed in two parts: the first half (roughly) covers -background material, while the second half can be taken to the keyboard as a -handy reference. +The next line creates a label widget holding a static text string. The +:meth:`grid` method is used to specify the relative layout (position) of the +label within its containing frame widget, similar to how tables in HTML work. -When trying to answer questions of the form "how do I do blah", it is often best -to find out how to do "blah" in straight Tk, and then convert this back into the -corresponding :mod:`tkinter` call. Python programmers can often guess at the -correct Python command by looking at the Tk documentation. This means that in -order to use Tkinter, you will have to know a little bit about Tk. This document -can't fulfill that role, so the best we can do is point you to the best -documentation that exists. Here are some hints: +A button widget is then created, and placed to the right of the label. When +pressed, it will call the :meth:`destroy` method of the root window. -* The authors strongly suggest getting a copy of the Tk man pages. - Specifically, the man pages in the ``manN`` directory are most useful. - The ``man3`` man pages describe the C interface to the Tk library and thus - are not especially helpful for script writers. +Finally, the :meth:`mainloop` method puts everything on the display, and +responds to user input until the program terminates. -* Addison-Wesley publishes a book called Tcl and the Tk Toolkit by John - Ousterhout (ISBN 0-201-63337-X) which is a good introduction to Tcl and Tk for - the novice. The book is not exhaustive, and for many details it defers to the - man pages. -* :file:`tkinter/__init__.py` is a last resort for most, but can be a good - place to go when nothing else makes sense. +Important Tk Concepts +^^^^^^^^^^^^^^^^^^^^^ -A Simple Hello World Program -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Even this simple program illustrates the following key Tk concepts: -:: +widgets + A Tkinter user interface is made up of individual *widgets*. Each widget is + represented as a Python object, instantiated from classes like + :class:`ttk.Frame`, :class:`ttk.Label`, and :class:`ttk.Button`. - import tkinter as tk +widget hierarchy + Widgets are arranged in a *hierarchy*. The label and button were contained + within a frame, which in turn was contained within the root window. When + creating each *child* widget, its *parent* widget is passed as the first + argument to the widget constructor. - class Application(tk.Frame): - def __init__(self, master=None): - super().__init__(master) - self.master = master - self.pack() - self.create_widgets() +configuration options + Widgets have *configuration options*, which modify their appearance and + behavior, such as the text to display in a label or button. Different + classes of widgets will have different sets of options. - def create_widgets(self): - self.hi_there = tk.Button(self) - self.hi_there["text"] = "Hello World\n(click me)" - self.hi_there["command"] = self.say_hi - self.hi_there.pack(side="top") +geometry management + Widgets aren't automatically added to the user interface when they are + created. A *geometry manager* like ``grid`` controls where in the + user interface they are placed. - self.quit = tk.Button(self, text="QUIT", fg="red", - command=self.master.destroy) - self.quit.pack(side="bottom") +event loop + Tkinter reacts to user input, changes from your program, and even refreshes + the display only when actively running an *event loop*. If your program + isn't running the event loop, your user interface won't update. - def say_hi(self): - print("hi there, everyone!") - root = tk.Tk() - app = Application(master=root) - app.mainloop() +Understanding How Tkinter Wraps Tcl/Tk +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +When your application uses Tkinter's classes and methods, internally Tkinter +is assembling strings representing Tcl/Tk commands, and executing those +commands in the Tcl interpreter attached to your applicaton's :class:`Tk` +instance. -A (Very) Quick Look at Tcl/Tk ------------------------------ +Whether it's trying to navigate reference documentation, trying to find +the right method or option, adapting some existing code, or debugging your +Tkinter application, there are times that it will be useful to understand +what those underlying Tcl/Tk commands look like. -The class hierarchy looks complicated, but in actual practice, application -programmers almost always refer to the classes at the very bottom of the -hierarchy. +To illustrate, here is the Tcl/Tk equivalent of the main part of the Tkinter +script above. -Notes: +:: -* These classes are provided for the purposes of organizing certain functions - under one namespace. They aren't meant to be instantiated independently. + ttk::frame .frm -padding 10 + grid .frm + grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0 + grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0 -* The :class:`Tk` class is meant to be instantiated only once in an application. - Application programmers need not instantiate one explicitly, the system creates - one whenever any of the other classes are instantiated. -* The :class:`Widget` class is not meant to be instantiated, it is meant only - for subclassing to make "real" widgets (in C++, this is called an 'abstract - class'). +Tcl's syntax is similar to many shell languages, where the first word is the +command to be executed, with arguments to that command following it, separated +by spaces. Without getting into too many details, notice the following: -To make use of this reference material, there will be times when you will need -to know how to read short passages of Tk and how to identify the various parts -of a Tk command. (See section :ref:`tkinter-basic-mapping` for the -:mod:`tkinter` equivalents of what's below.) +* The commands used to create widgets (like ``ttk::frame``) correspond to + widget classes in Tkinter. -Tk scripts are Tcl programs. Like all Tcl programs, Tk scripts are just lists -of tokens separated by spaces. A Tk widget is just its *class*, the *options* -that help configure it, and the *actions* that make it do useful things. +* Tcl widget options (like ``-text``) correspond to keyword arguments in + Tkinter. -To make a widget in Tk, the command is always of the form:: +* Widgets are referred to by a *pathname* in Tcl (like ``.frm.btn``), + whereas Tkinter doesn't use names but object references. - classCommand newPathname options +* A widget's place in the widget hierarchy is encoded in its (hierarchical) + pathname, which uses a ``.`` (dot) as a path separator. The pathname for + the root window is just ``.`` (dot). In Tkinter, the hierarchy is defined + not by pathname but by specifying the parent widget when creating each + child widget. -*classCommand* - denotes which kind of widget to make (a button, a label, a menu...) +* Operations which are implemented as separate *commands* in Tcl (like + ``grid`` or ``destroy``) are represented as *methods* on Tkinter widget + objects. As you'll see shortly, at other times Tcl uses what appear to be + method calls on widget objects, which more closely mirror what would is + used in Tkinter. -.. index:: single: . (dot); in Tkinter -*newPathname* - is the new name for this widget. All names in Tk must be unique. To help - enforce this, widgets in Tk are named with *pathnames*, just like files in a - file system. The top level widget, the *root*, is called ``.`` (period) and - children are delimited by more periods. For example, - ``.myApp.controlPanel.okButton`` might be the name of a widget. +How do I...? What option does...? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -*options* - configure the widget's appearance and in some cases, its behavior. The options - come in the form of a list of flags and values. Flags are preceded by a '-', - like Unix shell command flags, and values are put in quotes if they are more - than one word. +If you're not sure how to do something in Tkinter, and you can't immediately +find it in the tutorial or reference documentation you're using, there are a +few strategies that can be helpful. -For example:: +First, remember that the details of how individual widgets work may vary +across different versions of both Tkinter and Tcl/Tk. If you're searching +documentation, make sure it corresponds to the Python and Tcl/Tk versions +installed on your system. - button .fred -fg red -text "hi there" - ^ ^ \______________________/ - | | | - class new options - command widget (-opt val -opt val ...) +When searching for how to use an API, it helps to know the exact name of the +class, option, or method that you're using. Introspection, either in an +interactive Python shell or with :func:`print`, can help you identify what +you need. -Once created, the pathname to the widget becomes a new command. This new -*widget command* is the programmer's handle for getting the new widget to -perform some *action*. In C, you'd express this as someAction(fred, -someOptions), in C++, you would express this as fred.someAction(someOptions), -and in Tk, you say:: +To find out what configuration options are available on any widget, call its +:meth:`configure` method, which returns a dictionary containing a variety of +information about each object, including its default and current values. Use +:meth:`keys` to get just the names of each option. - .fred someAction someOptions - -Note that the object name, ``.fred``, starts with a dot. +:: -As you'd expect, the legal values for *someAction* will depend on the widget's -class: ``.fred disable`` works if fred is a button (fred gets greyed out), but -does not work if fred is a label (disabling of labels is not supported in Tk). + btn = ttk.Button(frm, ...) + print(btn.configure().keys()) -The legal values of *someOptions* is action dependent. Some actions, like -``disable``, require no arguments, others, like a text-entry box's ``delete`` -command, would need arguments to specify what range of text to delete. +As most widgets have many configuration options in common, it can be useful +to find out which are specific to a particular widget class. Comparing the +list of options to that of a simpler widget, like a frame, is one way to +do that. +:: -.. _tkinter-basic-mapping: + print(set(btn.configure().keys()) - set(frm.configure().keys())) -Mapping Basic Tk into Tkinter ------------------------------ +Similarly, you can find the available methods for a widget object using the +standard :func:`dir` function. If you try it, you'll see there are over 200 +common widget methods, so again identifying those specific to a widget class +is helpful. -Class commands in Tk correspond to class constructors in Tkinter. :: +:: - button .fred =====> fred = Button() + print(dir(btn)) + print(set(dir(btn)) - set(dir(frm))) -The master of an object is implicit in the new name given to it at creation -time. In Tkinter, masters are specified explicitly. :: - button .panel.fred =====> fred = Button(panel) +Navigating the Tcl/Tk Reference Manual +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The configuration options in Tk are given in lists of hyphened tags followed by -values. In Tkinter, options are specified as keyword-arguments in the instance -constructor, and keyword-args for configure calls or as instance indices, in -dictionary style, for established instances. See section -:ref:`tkinter-setting-options` on setting options. :: +As noted, the official `Tk commands `_ +reference manual (man pages) is often the most accurate description of what +specific operations on widgets do. Even when you know the name of the option +or method that you need, you may still have a few places to look. - button .fred -fg red =====> fred = Button(panel, fg="red") - .fred configure -fg red =====> fred["fg"] = red - OR ==> fred.config(fg="red") +While all operations in Tkinter are implemented as method calls on widget +objects, you've seen that many Tcl/Tk operations appear as commands that +take a widget pathname as its first parameter, followed by optional +parameters, e.g. -In Tk, to perform an action on a widget, use the widget name as a command, and -follow it with an action name, possibly with arguments (options). In Tkinter, -you call methods on the class instance to invoke actions on the widget. The -actions (methods) that a given widget can perform are listed in -:file:`tkinter/__init__.py`. :: +:: - .fred invoke =====> fred.invoke() + destroy . + grid .frm.btn -column 0 -row 0 -To give a widget to the packer (geometry manager), you call pack with optional -arguments. In Tkinter, the Pack class holds all this functionality, and the -various forms of the pack command are implemented as methods. All widgets in -:mod:`tkinter` are subclassed from the Packer, and so inherit all the packing -methods. See the :mod:`tkinter.tix` module documentation for additional -information on the Form geometry manager. :: +Others, however, look more like methods called on a widget object (in fact, +when you create a widget in Tcl/Tk, it creates a Tcl command with the name +of the widget pathname, with the first parameter to that command being the +name of a method to call). - pack .fred -side left =====> fred.pack(side="left") +:: + .frm.btn invoke + .frm.lbl configure -text "Goodbye" -How Tk and Tkinter are Related ------------------------------- -From the top down: +In the official Tcl/Tk reference documentation, you'll find most operations +that look like method calls on the man page for a specific widget (e.g., +you'll find the :meth:`invoke` method on the +`ttk::button `_ +man page), while functions that take a widget as a parameter often have +their own man page (e.g., +`grid `_). -Your App Here (Python) - A Python application makes a :mod:`tkinter` call. +You'll find many common options and methods in the +`options `_ or +`ttk::widget `_ man +pages, while others are found in the man page for a specific widget class. -tkinter (Python Package) - This call (say, for example, creating a button widget), is implemented in - the :mod:`tkinter` package, which is written in Python. This Python - function will parse the commands and the arguments and convert them into a - form that makes them look as if they had come from a Tk script instead of - a Python script. +You'll also find that many Tkinter methods have compound names, e.g., +:func:`winfo_x`, :func:`winfo_height`, :func:`winfo_viewable`. You'd find +documentation for all of these in the +`winfo `_ man page. -_tkinter (C) - These commands and their arguments will be passed to a C function in the - :mod:`_tkinter` - note the underscore - extension module. +.. note:: + Somewhat confusingly, there are also methods on all Tkinter widgets + that don't actually operate on the widget, but operate at a global + scope, independent of any widget. Examples are methods for accessing + the clipboard or the system bell. (They happen to be implemented as + methods in the base :class:`Widget` class that all Tkinter widgets + inherit from). -Tk Widgets (C and Tcl) - This C function is able to make calls into other C modules, including the C - functions that make up the Tk library. Tk is implemented in C and some Tcl. - The Tcl part of the Tk widgets is used to bind certain default behaviors to - widgets, and is executed once at the point where the Python :mod:`tkinter` - package is imported. (The user never sees this stage). -Tk (C) - The Tk part of the Tk Widgets implement the final mapping to ... +Threading model +--------------- -Xlib (C) - the Xlib library to draw graphics on the screen. +Python and Tcl/Tk have very different threading models, which :mod:`tkinter` +tries to bridge. If you use threads, you may need to be aware of this. + +A Python interpreter may have many threads associated with it. In Tcl, multiple +threads can be created, but each thread has a separate Tcl interpreter instance +associated with it. Threads can also create more than one interpreter instance, +though each interpreter instance can be used only by the one thread that created it. + +Each :class:`Tk` object created by :mod:`tkinter` contains a Tcl interpreter. +It also keeps track of which thread created that interpreter. Calls to +:mod:`tkinter` can be made from any Python thread. Internally, if a call comes +from a thread other than the one that created the :class:`Tk` object, an event +is posted to the interpreter's event queue, and when executed, the result is +returned to the calling Python thread. + +Tcl/Tk applications are normally event-driven, meaning that after initialization, +the interpreter runs an event loop (i.e. :func:`Tk.mainloop`) and responds to events. +Because it is single-threaded, event handlers must respond quickly, otherwise they +will block other events from being processed. To avoid this, any long-running +computations should not run in an event handler, but are either broken into smaller +pieces using timers, or run in another thread. This is different from many GUI +toolkits where the GUI runs in a completely separate thread from all application +code including event handlers. + +If the Tcl interpreter is not running the event loop and processing events, any +:mod:`tkinter` calls made from threads other than the one running the Tcl +interpreter will fail. + +A number of special cases exist: + + * Tcl/Tk libraries can be built so they are not thread-aware. In this case, + :mod:`tkinter` calls the library from the originating Python thread, even + if this is different than the thread that created the Tcl interpreter. A global + lock ensures only one call occurs at a time. + + * While :mod:`tkinter` allows you to create more than one instance of a :class:`Tk` + object (with its own interpreter), all interpreters that are part of the same + thread share a common event queue, which gets ugly fast. In practice, don't create + more than one instance of :class:`Tk` at a time. Otherwise, it's best to create + them in separate threads and ensure you're running a thread-aware Tcl/Tk build. + + * Blocking event handlers are not the only way to prevent the Tcl interpreter from + reentering the event loop. It is even possible to run multiple nested event loops + or abandon the event loop entirely. If you're doing anything tricky when it comes + to events or threads, be aware of these possibilities. + + * There are a few select :mod:`tkinter` functions that presently work only when + called from the thread that created the Tcl interpreter. Handy Reference diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index 6967d7509657b3..2db4c0f9143f64 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -759,7 +759,7 @@ ones inherited from :class:`ttk.Widget`. Platform-specific notes ^^^^^^^^^^^^^^^^^^^^^^^ -* On MacOS X, toplevel windows automatically include a built-in size grip +* On macOS, toplevel windows automatically include a built-in size grip by default. Adding a :class:`Sizegrip` is harmless, since the built-in grip will just mask the widget. diff --git a/Doc/library/tracemalloc.rst b/Doc/library/tracemalloc.rst index 20f668c7282028..68432aeaecbcc1 100644 --- a/Doc/library/tracemalloc.rst +++ b/Doc/library/tracemalloc.rst @@ -740,12 +740,12 @@ Traceback .. method:: format(limit=None, most_recent_first=False) - Format the traceback as a list of lines with newlines. Use the - :mod:`linecache` module to retrieve lines from the source code. - If *limit* is set, format the *limit* most recent frames if *limit* - is positive. Otherwise, format the ``abs(limit)`` oldest frames. - If *most_recent_first* is ``True``, the order of the formatted frames - is reversed, returning the most recent frame first instead of last. + Format the traceback as a list of lines. Use the :mod:`linecache` module to + retrieve lines from the source code. If *limit* is set, format the *limit* + most recent frames if *limit* is positive. Otherwise, format the + ``abs(limit)`` oldest frames. If *most_recent_first* is ``True``, the order + of the formatted frames is reversed, returning the most recent frame first + instead of last. Similar to the :func:`traceback.format_tb` function, except that :meth:`.format` does not include newlines. diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst index 6a9d61916ad1a5..228cf1e01e74ab 100644 --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -193,8 +193,8 @@ Methods of TurtleScreen/Screen Window control | :func:`bgcolor` | :func:`bgpic` - | :func:`clear` | :func:`clearscreen` - | :func:`reset` | :func:`resetscreen` + | :func:`clearscreen` + | :func:`resetscreen` | :func:`screensize` | :func:`setworldcoordinates` @@ -1069,7 +1069,6 @@ More drawing control ~~~~~~~~~~~~~~~~~~~~ .. function:: reset() - :noindex: Delete the turtle's drawings from the screen, re-center the turtle and set variables to the default values. @@ -1091,7 +1090,6 @@ More drawing control .. function:: clear() - :noindex: Delete the turtle's drawings from the screen. Do not move turtle. State and position of the turtle as well as drawings of other turtles are not affected. @@ -1627,11 +1625,7 @@ Window control .. function:: clear() - clearscreen() - - Delete all drawings and all turtles from the TurtleScreen. Reset the now - empty TurtleScreen to its initial state: white background, no background - image, no event bindings and tracing on. + :noindex: .. note:: This TurtleScreen method is available as a global function only under the @@ -1639,10 +1633,15 @@ Window control derived from the Turtle method ``clear``. -.. function:: reset() - resetscreen() +.. function:: clearscreen() - Reset all Turtles on the Screen to their initial state. + Delete all drawings and all turtles from the TurtleScreen. Reset the now + empty TurtleScreen to its initial state: white background, no background + image, no event bindings and tracing on. + + +.. function:: reset() + :noindex: .. note:: This TurtleScreen method is available as a global function only under the @@ -1650,6 +1649,11 @@ Window control derived from the Turtle method ``reset``. +.. function:: resetscreen() + + Reset all Turtles on the Screen to their initial state. + + .. function:: screensize(canvwidth=None, canvheight=None, bg=None) :param canvwidth: positive integer, new width of canvas in pixels diff --git a/Doc/library/types.rst b/Doc/library/types.rst index b3fac293ecc9e1..5cd42f1fc2928d 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -243,7 +243,7 @@ Standard names are defined for the following types: .. note:: A future version of Python may stop setting this attribute by default. - To guard against this potential change, preferrably read from the + To guard against this potential change, preferably read from the :attr:`__spec__` attribute instead or use ``getattr(module, "__loader__", None)`` if you explicitly need to use this attribute. @@ -268,7 +268,7 @@ Standard names are defined for the following types: .. note:: A future version of Python may stop setting this attribute by default. - To guard against this potential change, preferrably read from the + To guard against this potential change, preferably read from the :attr:`__spec__` attribute instead or use ``getattr(module, "__package__", None)`` if you explicitly need to use this attribute. @@ -278,8 +278,8 @@ Standard names are defined for the following types: .. attribute:: __spec__ - A record of the the module's import-system-related state. Expected to be - an instance of :class:`importlib.machinery.ModuleSpec`. + A record of the module's import-system-related state. Expected to be an + instance of :class:`importlib.machinery.ModuleSpec`. .. versionadded:: 3.4 @@ -312,7 +312,7 @@ Standard names are defined for the following types: This type can now be subclassed. -.. data:: Union +.. class:: UnionType The type of :ref:`union type expressions`. diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 8b1ce34d98ec66..929749bc0b3416 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -17,13 +17,10 @@ -------------- -This module provides runtime support for type hints as specified by -:pep:`484`, :pep:`526`, :pep:`544`, :pep:`586`, :pep:`589`, :pep:`591`, -:pep:`612` and :pep:`613`. -The most fundamental support consists of the types :data:`Any`, :data:`Union`, -:data:`Tuple`, :data:`Callable`, :class:`TypeVar`, and -:class:`Generic`. For full specification please see :pep:`484`. For -a simplified introduction to type hints see :pep:`483`. +This module provides runtime support for type hints. The most fundamental +support consists of the types :data:`Any`, :data:`Union`, :data:`Callable`, +:class:`TypeVar`, and :class:`Generic`. For a full specification, please see +:pep:`484`. For a simplified introduction to type hints, see :pep:`483`. The function below takes and returns a string and is annotated as follows:: @@ -35,6 +32,43 @@ In the function ``greeting``, the argument ``name`` is expected to be of type :class:`str` and the return type :class:`str`. Subtypes are accepted as arguments. +.. _relevant-peps: + +Relevant PEPs +============= + +Since the initial introduction of type hints in :pep:`484` and :pep:`483`, a +number of PEPs have modified and enhanced Python's framework for type +annotations. These include: + +* :pep:`526`: Syntax for Variable Annotations + *Introducing* syntax for annotating variables outside of function + definitions, and :data:`ClassVar` +* :pep:`544`: Protocols: Structural subtyping (static duck typing) + *Introducing* :class:`Protocol` and the + :func:`@runtime_checkable` decorator +* :pep:`585`: Type Hinting Generics In Standard Collections + *Introducing* :class:`types.GenericAlias` and the ability to use standard + library classes as :ref:`generic types` +* :pep:`586`: Literal Types + *Introducing* :data:`Literal` +* :pep:`589`: TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys + *Introducing* :class:`TypedDict` +* :pep:`591`: Adding a final qualifier to typing + *Introducing* :data:`Final` and the :func:`@final` decorator +* :pep:`593`: Flexible function and variable annotations + *Introducing* :data:`Annotated` +* :pep:`604`: Allow writing union types as ``X | Y`` + *Introducing* :data:`types.UnionType` and the ability to use + the binary-or operator ``|`` to signify a + :ref:`union of types` +* :pep:`612`: Parameter Specification Variables + *Introducing* :class:`ParamSpec` and :data:`Concatenate` +* :pep:`613`: Explicit Type Aliases + *Introducing* :data:`TypeAlias` +* :pep:`647`: User-Defined Type Guards + *Introducing* :data:`TypeGuard` + .. _type-aliases: Type aliases @@ -77,7 +111,7 @@ Note that ``None`` as a type hint is a special case and is replaced by NewType ======= -Use the :func:`NewType` helper function to create distinct types:: +Use the :class:`NewType` helper class to create distinct types:: from typing import NewType @@ -106,15 +140,14 @@ accidentally creating a ``UserId`` in an invalid way:: Note that these checks are enforced only by the static type checker. At runtime, the statement ``Derived = NewType('Derived', Base)`` will make ``Derived`` a -function that immediately returns whatever parameter you pass it. That means +class that immediately returns whatever parameter you pass it. That means the expression ``Derived(some_value)`` does not create a new class or introduce -any overhead beyond that of a regular function call. +much overhead beyond that of a regular function call. More precisely, the expression ``some_value is Derived(some_value)`` is always true at runtime. -This also means that it is not possible to create a subtype of ``Derived`` -since it is an identity function at runtime, not an actual type:: +It is invalid to create a subtype of ``Derived``:: from typing import NewType @@ -123,7 +156,7 @@ since it is an identity function at runtime, not an actual type:: # Fails at runtime and does not typecheck class AdminUserId(UserId): pass -However, it is possible to create a :func:`NewType` based on a 'derived' ``NewType``:: +However, it is possible to create a :class:`NewType` based on a 'derived' ``NewType``:: from typing import NewType @@ -151,6 +184,12 @@ See :pep:`484` for more details. .. versionadded:: 3.5.2 +.. versionchanged:: 3.10 + ``NewType`` is now a class rather than a function. There is some additional + runtime cost when calling ``NewType`` over a regular function. However, this + cost will be reduced in 3.11.0. + + Callable ======== @@ -217,6 +256,7 @@ called :class:`TypeVar`. def first(l: Sequence[T]) -> T: # Generic function return l[0] +.. _user-defined-generics: User-defined generic types ========================== @@ -251,8 +291,8 @@ A user-defined class can be defined as a generic class. single type parameter ``T`` . This also makes ``T`` valid as a type within the class body. -The :class:`Generic` base class defines :meth:`__class_getitem__` so that -``LoggedVar[t]`` is valid as a type:: +The :class:`Generic` base class defines :meth:`~object.__class_getitem__` so +that ``LoggedVar[t]`` is valid as a type:: from collections.abc import Iterable @@ -316,11 +356,11 @@ not generic but implicitly inherits from ``Iterable[Any]``:: User defined generic type aliases are also supported. Examples:: from collections.abc import Iterable - from typing import TypeVar, Union + from typing import TypeVar S = TypeVar('S') - Response = Union[Iterable[S], int] + Response = Iterable[S] | int - # Return type here is same as Union[Iterable[str], int] + # Return type here is same as Iterable[str] | int def response(query: str) -> Response[str]: ... @@ -388,12 +428,12 @@ value of type :data:`Any` and assign it to any variable:: from typing import Any - a = None # type: Any - a = [] # OK - a = 2 # OK + a: Any = None + a = [] # OK + a = 2 # OK - s = '' # type: str - s = a # OK + s: str = '' + s = a # OK def foo(item: Any) -> int: # Typechecks; 'item' could be any type, @@ -583,9 +623,9 @@ These can be used as types in annotations using ``[]``, each having a unique syn .. data:: Union - Union type; ``Union[X, Y]`` means either X or Y. + Union type; ``Union[X, Y]`` is equivalent to ``X | Y`` and means either X or Y. - To define a union, use e.g. ``Union[int, str]``. Details: + To define a union, use e.g. ``Union[int, str]`` or the shorthand ``int | str``. Using that shorthand is recommended. Details: * The arguments must be types and there must be at least one. @@ -599,18 +639,16 @@ These can be used as types in annotations using ``[]``, each having a unique syn * Redundant arguments are skipped, e.g.:: - Union[int, str, int] == Union[int, str] + Union[int, str, int] == Union[int, str] == int | str * When comparing unions, the argument order is ignored, e.g.:: Union[int, str] == Union[str, int] - * You cannot subclass or instantiate a union. + * You cannot subclass or instantiate a ``Union``. * You cannot write ``Union[X][Y]``. - * You can use ``Optional[X]`` as a shorthand for ``Union[X, None]``. - .. versionchanged:: 3.7 Don't remove explicit subclasses from unions at runtime. @@ -622,7 +660,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn Optional type. - ``Optional[X]`` is equivalent to ``Union[X, None]``. + ``Optional[X]`` is equivalent to ``X | None`` (or ``Union[X, None]``). Note that this is not the same concept as an optional argument, which is one that has a default. An optional argument with a @@ -639,6 +677,10 @@ These can be used as types in annotations using ``[]``, each having a unique syn def foo(arg: Optional[int] = None) -> None: ... + .. versionchanged:: 3.10 + Optional can now be written as ``X | None``. See + :ref:`union type expressions`. + .. data:: Callable Callable type; ``Callable[[int], str]`` is a function of (int) -> str. @@ -695,7 +737,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn from collections.abc import Callable from threading import Lock - from typing import Any, Concatenate, ParamSpec, TypeVar + from typing import Concatenate, ParamSpec, TypeVar P = ParamSpec('P') R = TypeVar('R') @@ -765,7 +807,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn :ref:`type variables `, and unions of any of these types. For example:: - def new_non_team_user(user_class: Type[Union[BasicUser, ProUser]]): ... + def new_non_team_user(user_class: Type[BasicUser | ProUser]): ... ``Type[Any]`` is equivalent to ``Type`` which in turn is equivalent to ``type``, which is the root of Python's metaclass hierarchy. @@ -799,10 +841,10 @@ These can be used as types in annotations using ``[]``, each having a unique syn .. versionadded:: 3.8 .. versionchanged:: 3.9.1 - ``Literal`` now de-duplicates parameters. Equality comparison of + ``Literal`` now de-duplicates parameters. Equality comparisons of ``Literal`` objects are no longer order dependent. ``Literal`` objects will now raise a :exc:`TypeError` exception during equality comparisons - if one of their parameters are not :term:`immutable`. + if one of their parameters are not :term:`hashable`. .. data:: ClassVar @@ -946,7 +988,7 @@ These can be used as types in annotations using ``[]``, each having a unique syn conditional code flow and applying the narrowing to a block of code. The conditional expression here is sometimes referred to as a "type guard":: - def is_str(val: Union[str, float]): + def is_str(val: str | float): # "isinstance" type guard if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` @@ -1232,8 +1274,13 @@ These are not used in annotations. They are building blocks for creating generic .. note:: - :func:`runtime_checkable` will check only the presence of the required methods, - not their type signatures. + :func:`runtime_checkable` will check only the presence of the required + methods, not their type signatures. For example, :class:`ssl.SSLObject` + is a class, therefore it passes an :func:`issubclass` + check against :data:`Callable`. However, the + :meth:`ssl.SSLObject.__init__` method exists only to raise a + :exc:`TypeError` with a more informative message, therefore making + it impossible to call (instantiate) :class:`ssl.SSLObject`. .. versionadded:: 3.8 @@ -1301,17 +1348,21 @@ These are not used in annotations. They are building blocks for declaring types. Removed the ``_field_types`` attribute in favor of the more standard ``__annotations__`` attribute which has the same information. -.. function:: NewType(name, tp) +.. class:: NewType(name, tp) - A helper function to indicate a distinct type to a typechecker, - see :ref:`distinct`. At runtime it returns a function that returns - its argument. Usage:: + A helper class to indicate a distinct type to a typechecker, + see :ref:`distinct`. At runtime it returns an object that returns + its argument when called. + Usage:: UserId = NewType('UserId', int) first_user = UserId(1) .. versionadded:: 3.5.2 + .. versionchanged:: 3.10 + ``NewType`` is now a class rather than a function. + .. class:: TypedDict(dict) Special construct to add type hints to a dictionary. @@ -1488,7 +1539,11 @@ Other concrete types Generic type ``IO[AnyStr]`` and its subclasses ``TextIO(IO[str])`` and ``BinaryIO(IO[bytes])`` represent the types of I/O streams such as returned by - :func:`open`. These types are also in the ``typing.io`` namespace. + :func:`open`. + + .. deprecated-removed:: 3.8 3.12 + The ``typing.io`` namespace is deprecated and will be removed. + These types should be directly imported from ``typing`` instead. .. class:: Pattern Match @@ -1498,7 +1553,11 @@ Other concrete types :func:`re.match`. These types (and the corresponding functions) are generic in ``AnyStr`` and can be made specific by writing ``Pattern[str]``, ``Pattern[bytes]``, ``Match[str]``, or - ``Match[bytes]``. These types are also in the ``typing.re`` namespace. + ``Match[bytes]``. + + .. deprecated-removed:: 3.8 3.12 + The ``typing.re`` namespace is deprecated and will be removed. + These types should be directly imported from ``typing`` instead. .. deprecated:: 3.9 Classes ``Pattern`` and ``Match`` from :mod:`re` now support ``[]``. @@ -1720,11 +1779,10 @@ Asynchronous programming correspond to those of :class:`Generator`, for example:: from collections.abc import Coroutine - c = None # type: Coroutine[list[str], str, int] - ... - x = c.send('hi') # type: list[str] + c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere + x = c.send('hi') # Inferred type of 'x' is list[str] async def bar() -> None: - x = await c # type: int + y = await c # Inferred type of 'y' is int .. versionadded:: 3.5.3 @@ -1991,6 +2049,13 @@ Introspection helpers 'name': Annotated[str, 'some marker'] } + .. note:: + + :func:`get_type_hints` does not work with imported + :ref:`type aliases ` that include forward references. + Enabling postponed evaluation of annotations (:pep:`563`) may remove + the need for most forward references. + .. versionchanged:: 3.9 Added ``include_extras`` parameter as part of :pep:`593`. @@ -2002,7 +2067,7 @@ Introspection helpers For a typing object of the form ``X[Y, Z, ...]`` these functions return ``X`` and ``(Y, Z, ...)``. If ``X`` is a generic alias for a builtin or :mod:`collections` class, it gets normalized to the original class. - If ``X`` is a :class:`Union` or :class:`Literal` contained in another + If ``X`` is a union or :class:`Literal` contained in another generic type, the order of ``(Y, Z, ...)`` may be different from the order of the original arguments ``[Y, Z, ...]`` due to type caching. For unsupported objects return ``None`` and ``()`` correspondingly. @@ -2027,7 +2092,7 @@ Introspection helpers year: int is_typeddict(Film) # => True - is_typeddict(Union[list, str]) # => False + is_typeddict(list | str) # => False .. versionadded:: 3.10 diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 1604731b99e3fe..4d74f9cee84ee8 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -328,8 +328,8 @@ the *new_callable* argument to :func:`patch`. .. method:: assert_called_once_with(*args, **kwargs) - Assert that the mock was called exactly once and that that call was - with the specified arguments. + Assert that the mock was called exactly once and that call was with the + specified arguments. >>> mock = Mock(return_value=None) >>> mock('foo', bar='baz') @@ -1516,7 +1516,7 @@ attribute in a class) that does not exist will fail with :exc:`AttributeError`:: >>> test() Traceback (most recent call last): ... - AttributeError: does not have the attribute 'non_existing' + AttributeError: does not have the attribute 'non_existing_attribute' but adding ``create=True`` in the call to :func:`patch` will make the previous example work as expected:: @@ -2208,7 +2208,7 @@ In this example we monkey patch ``method`` to return ``sentinel.some_object``: >>> real.method.return_value = sentinel.some_object >>> result = real.method() >>> assert result is sentinel.some_object - >>> sentinel.some_object + >>> result sentinel.some_object diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 0c29408cb19214..ae0c7d59964f16 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -223,7 +223,7 @@ Command-line options Only run test methods and classes that match the pattern or substring. This option may be used multiple times, in which case all test cases that - match of the given patterns are included. + match any of the given patterns are included. Patterns that contain a wildcard character (``*``) are matched against the test name using :meth:`fnmatch.fnmatchcase`; otherwise simple case-sensitive @@ -597,8 +597,9 @@ The following decorators and exception implement test skipping and expected fail .. decorator:: expectedFailure Mark the test as an expected failure or error. If the test fails or errors - it will be considered a success. If the test passes, it will be considered - a failure. + in the test function itself (rather than in one of the :dfn:`test fixture` + methods) then it will be considered a success. If the test passes, it will + be considered a failure. .. exception:: SkipTest(reason) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 0aaac562883f18..1478b34bc95514 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -20,7 +20,7 @@ strings up in components (addressing scheme, network location, path etc.), to combine the components back into a URL string, and to convert a "relative URL" to an absolute URL given a "base URL." -The module has been designed to match the Internet RFC on Relative Uniform +The module has been designed to match the internet RFC on Relative Uniform Resource Locators. It supports the following URL schemes: ``file``, ``ftp``, ``gopher``, ``hdl``, ``http``, ``https``, ``imap``, ``mailto``, ``mms``, ``news``, ``nntp``, ``prospero``, ``rsync``, ``rtsp``, ``rtspu``, ``sftp``, @@ -48,17 +48,29 @@ or on combining URL components into a URL string. result, except for a leading slash in the *path* component, which is retained if present. For example: + .. doctest:: + :options: +NORMALIZE_WHITESPACE + >>> from urllib.parse import urlparse - >>> o = urlparse('http://www.cwi.nl:80/%7Eguido/Python.html') - >>> o # doctest: +NORMALIZE_WHITESPACE - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') + >>> urlparse("scheme://netloc/path;parameters?query#fragment") + ParseResult(scheme='scheme', netloc='netloc', path='/path;parameters', params='', + query='query', fragment='fragment') + >>> o = urlparse("http://docs.python.org:80/3/library/urllib.parse.html?" + ... "highlight=params#url-parsing") + >>> o + ParseResult(scheme='http', netloc='docs.python.org:80', + path='/3/library/urllib.parse.html', params='', + query='highlight=params', fragment='url-parsing') >>> o.scheme 'http' + >>> o.netloc + 'docs.python.org:80' + >>> o.hostname + 'docs.python.org' >>> o.port 80 - >>> o.geturl() - 'http://www.cwi.nl:80/%7Eguido/Python.html' + >>> o._replace(fragment="").geturl() + 'http://docs.python.org:80/3/library/urllib.parse.html?highlight=params' Following the syntax specifications in :rfc:`1808`, urlparse recognizes a netloc only if it is properly introduced by '//'. Otherwise the @@ -92,31 +104,30 @@ or on combining URL components into a URL string. The return value is a :term:`named tuple`, which means that its items can be accessed by index or as named attributes, which are: - +------------------+-------+--------------------------+----------------------+ - | Attribute | Index | Value | Value if not present | - +==================+=======+==========================+======================+ - | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | - +------------------+-------+--------------------------+----------------------+ - | :attr:`netloc` | 1 | Network location part | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`path` | 2 | Hierarchical path | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`params` | 3 | Parameters for last path | empty string | - | | | element | | - +------------------+-------+--------------------------+----------------------+ - | :attr:`query` | 4 | Query component | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`fragment` | 5 | Fragment identifier | empty string | - +------------------+-------+--------------------------+----------------------+ - | :attr:`username` | | User name | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`password` | | Password | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`hostname` | | Host name (lower case) | :const:`None` | - +------------------+-------+--------------------------+----------------------+ - | :attr:`port` | | Port number as integer, | :const:`None` | - | | | if present | | - +------------------+-------+--------------------------+----------------------+ + +------------------+-------+-------------------------+------------------------+ + | Attribute | Index | Value | Value if not present | + +==================+=======+=========================+========================+ + | :attr:`scheme` | 0 | URL scheme specifier | *scheme* parameter | + +------------------+-------+-------------------------+------------------------+ + | :attr:`netloc` | 1 | Network location part | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`path` | 2 | Hierarchical path | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`params` | 3 | No longer used | always an empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`query` | 4 | Query component | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`fragment` | 5 | Fragment identifier | empty string | + +------------------+-------+-------------------------+------------------------+ + | :attr:`username` | | User name | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`password` | | Password | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`hostname` | | Host name (lower case) | :const:`None` | + +------------------+-------+-------------------------+------------------------+ + | :attr:`port` | | Port number as integer, | :const:`None` | + | | | if present | | + +------------------+-------+-------------------------+------------------------+ Reading the :attr:`port` attribute will raise a :exc:`ValueError` if an invalid port is specified in the URL. See section diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index b4435a62ad43d9..659a3632ac9be8 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -169,8 +169,8 @@ The :mod:`urllib.request` module defines the following functions: This helper function returns a dictionary of scheme to proxy server URL mappings. It scans the environment for variables named ``_proxy``, in a case insensitive approach, for all operating systems first, and when it - cannot find it, looks for proxy information from Mac OSX System - Configuration for Mac OS X and Windows Systems Registry for Windows. + cannot find it, looks for proxy information from System + Configuration for macOS and Windows Systems Registry for Windows. If both lowercase and uppercase environment variables exist (and disagree), lowercase is preferred. @@ -303,8 +303,8 @@ The following classes are provided: the list of proxies from the environment variables ``_proxy``. If no proxy environment variables are set, then in a Windows environment proxy settings are obtained from the registry's - Internet Settings section, and in a Mac OS X environment proxy information - is retrieved from the OS X System Configuration Framework. + Internet Settings section, and in a macOS environment proxy information + is retrieved from the System Configuration Framework. To disable autodetected proxy pass an empty dictionary. @@ -655,7 +655,7 @@ OpenerDirector Objects optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used). The timeout feature actually works only for - HTTP, HTTPS and FTP connections). + HTTP, HTTPS and FTP connections. .. method:: OpenerDirector.error(proto, *args) @@ -1543,7 +1543,7 @@ some point in the future. * The :func:`urlopen` and :func:`urlretrieve` functions can cause arbitrarily long delays while waiting for a network connection to be set up. This means - that it is difficult to build an interactive Web client using these functions + that it is difficult to build an interactive web client using these functions without using threads. .. index:: diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst index 544f50273dd17c..f063e463753e0b 100644 --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -19,7 +19,7 @@ This module provides a single class, :class:`RobotFileParser`, which answers questions about whether or not a particular user agent can fetch a URL on the -Web site that published the :file:`robots.txt` file. For more details on the +web site that published the :file:`robots.txt` file. For more details on the structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index 2a4eede91a7c17..127a8717cf7d12 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -425,7 +425,7 @@ subclass which installs setuptools and pip into a created virtual environment:: 'more target ' 'directories.') parser.add_argument('dirs', metavar='ENV_DIR', nargs='+', - help='A directory in which to create the + help='A directory in which to create the ' 'virtual environment.') parser.add_argument('--no-setuptools', default=False, action='store_true', dest='nodist', diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index fe11aabbcbdd6b..289b28229e1a00 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -105,7 +105,7 @@ The following warnings category classes are currently defined: | | :class:`bytes` and :class:`bytearray`. | +----------------------------------+-----------------------------------------------+ | :exc:`ResourceWarning` | Base category for warnings related to | -| | resource usage. | +| | resource usage (ignored by default). | +----------------------------------+-----------------------------------------------+ .. versionchanged:: 3.7 diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index b88543e4453723..4b0945c020f843 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -88,6 +88,10 @@ support weak references but can add support through subclassing:: Extension types can easily be made to support weak references; see :ref:`weakref-support`. +When ``__slots__`` are defined for a given type, weak reference support is +disabled unless a ``'__weakref__'`` string is also present in the sequence of +strings in the ``__slots__`` declaration. +See :ref:`__slots__ documentation ` for details. .. class:: ref(object[, callback]) diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst index b7bfb655a71579..c0990882e58fe9 100644 --- a/Doc/library/webbrowser.rst +++ b/Doc/library/webbrowser.rst @@ -1,8 +1,8 @@ -:mod:`webbrowser` --- Convenient Web-browser controller +:mod:`webbrowser` --- Convenient web-browser controller ======================================================= .. module:: webbrowser - :synopsis: Easy-to-use controller for Web browsers. + :synopsis: Easy-to-use controller for web browsers. .. moduleauthor:: Fred L. Drake, Jr. .. sectionauthor:: Fred L. Drake, Jr. @@ -12,7 +12,7 @@ -------------- The :mod:`webbrowser` module provides a high-level interface to allow displaying -Web-based documents to users. Under most circumstances, simply calling the +web-based documents to users. Under most circumstances, simply calling the :func:`.open` function from this module will do the right thing. Under Unix, graphical browsers are preferred under X11, but text-mode browsers @@ -39,7 +39,7 @@ parameters: ``-n`` opens the URL in a new browser window, if possible; ``-t`` opens the URL in a new browser page ("tab"). The options are, naturally, mutually exclusive. Usage example:: - python -m webbrowser -t "http://www.python.org" + python -m webbrowser -t "https://www.python.org" The following exception is defined: @@ -143,9 +143,9 @@ for the controller classes, all defined in this module. +------------------------+-----------------------------------------+-------+ | ``'windows-default'`` | :class:`WindowsDefault` | \(2) | +------------------------+-----------------------------------------+-------+ -| ``'macosx'`` | :class:`MacOSX('default')` | \(3) | +| ``'macosx'`` | :class:`MacOSXOSAScript('default')` | \(3) | +------------------------+-----------------------------------------+-------+ -| ``'safari'`` | :class:`MacOSX('safari')` | \(3) | +| ``'safari'`` | :class:`MacOSXOSAScript('safari')` | \(3) | +------------------------+-----------------------------------------+-------+ | ``'google-chrome'`` | :class:`Chrome('google-chrome')` | | +------------------------+-----------------------------------------+-------+ @@ -169,14 +169,14 @@ Notes: Only on Windows platforms. (3) - Only on Mac OS X platform. + Only on macOS platform. .. versionadded:: 3.3 Support for Chrome/Chromium has been added. Here are some simple examples:: - url = 'http://docs.python.org/' + url = 'https://docs.python.org/' # Open URL in a new tab, if a browser window is already open. webbrowser.open_new_tab(url) diff --git a/Doc/library/xml.dom.minidom.rst b/Doc/library/xml.dom.minidom.rst index bf72c46561b7c7..20984b98b1778c 100644 --- a/Doc/library/xml.dom.minidom.rst +++ b/Doc/library/xml.dom.minidom.rst @@ -145,7 +145,7 @@ module documentation. This section lists the differences between the API and For the :class:`Document` node, an additional keyword argument *encoding* can be used to specify the encoding field of the XML header. - Silimarly, explicitly stating the *standalone* argument causes the + Similarly, explicitly stating the *standalone* argument causes the standalone document declarations to be added to the prologue of the XML document. If the value is set to `True`, `standalone="yes"` is added, @@ -156,6 +156,9 @@ module documentation. This section lists the differences between the API and The :meth:`writexml` method now preserves the attribute order specified by the user. + .. versionchanged:: 3.9 + The *standalone* parameter was added. + .. method:: Node.toxml(encoding=None, standalone=None) Return a string or byte string containing the XML represented by @@ -174,6 +177,9 @@ module documentation. This section lists the differences between the API and The :meth:`toxml` method now preserves the attribute order specified by the user. + .. versionchanged:: 3.9 + The *standalone* parameter was added. + .. method:: Node.toprettyxml(indent="\\t", newl="\\n", encoding=None, \ standalone=None) @@ -190,6 +196,8 @@ module documentation. This section lists the differences between the API and The :meth:`toprettyxml` method now preserves the attribute order specified by the user. + .. versionchanged:: 3.9 + The *standalone* parameter was added. .. _dom-example: diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index 1981cab7cd438d..e3b35162961147 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -60,22 +60,26 @@ circumvent firewalls. The following table gives an overview of the known attacks and whether the various modules are vulnerable to them. -========================= ============== =============== ============== ============== ============== -kind sax etree minidom pulldom xmlrpc -========================= ============== =============== ============== ============== ============== -billion laughs **Vulnerable** **Vulnerable** **Vulnerable** **Vulnerable** **Vulnerable** -quadratic blowup **Vulnerable** **Vulnerable** **Vulnerable** **Vulnerable** **Vulnerable** -external entity expansion Safe (4) Safe (1) Safe (2) Safe (4) Safe (3) -`DTD`_ retrieval Safe (4) Safe Safe Safe (4) Safe -decompression bomb Safe Safe Safe Safe **Vulnerable** -========================= ============== =============== ============== ============== ============== - -1. :mod:`xml.etree.ElementTree` doesn't expand external entities and raises a +========================= ================== ================== ================== ================== ================== +kind sax etree minidom pulldom xmlrpc +========================= ================== ================== ================== ================== ================== +billion laughs **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) +quadratic blowup **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) **Vulnerable** (1) +external entity expansion Safe (5) Safe (2) Safe (3) Safe (5) Safe (4) +`DTD`_ retrieval Safe (5) Safe Safe Safe (5) Safe +decompression bomb Safe Safe Safe Safe **Vulnerable** +========================= ================== ================== ================== ================== ================== + +1. Expat 2.4.1 and newer is not vulnerable to the "billion laughs" and + "quadratic blowup" vulnerabilities. Items still listed as vulnerable due to + potential reliance on system-provided libraries. Check + :data:`pyexpat.EXPAT_VERSION`. +2. :mod:`xml.etree.ElementTree` doesn't expand external entities and raises a :exc:`ParserError` when an entity occurs. -2. :mod:`xml.dom.minidom` doesn't expand external entities and simply returns +3. :mod:`xml.dom.minidom` doesn't expand external entities and simply returns the unexpanded entity verbatim. -3. :mod:`xmlrpclib` doesn't expand external entities and omits them. -4. Since Python 3.7.1, external general entities are no longer processed by +4. :mod:`xmlrpclib` doesn't expand external entities and omits them. +5. Since Python 3.7.1, external general entities are no longer processed by default. diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index 3db55e646c47cc..43520b697c9d25 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -78,7 +78,6 @@ The module defines the following items: of the last modification to the file; the fields are described in section :ref:`zipinfo-objects`. - .. function:: is_zipfile(filename) Returns ``True`` if *filename* is a valid ZIP file based on its magic number, @@ -406,6 +405,11 @@ ZipFile Objects If ``arcname`` (or ``filename``, if ``arcname`` is not given) contains a null byte, the name of the file in the archive will be truncated at the null byte. + .. note:: + + A leading slash in the filename may lead to the archive being impossible to + open in some zip programs on Windows systems. + .. versionchanged:: 3.6 Calling :meth:`write` on a ZipFile created with mode ``'r'`` or a closed ZipFile will raise a :exc:`ValueError`. Previously, @@ -857,6 +861,8 @@ Exceeding limitations on different file systems can cause decompression failed. Such as allowable characters in the directory entries, length of the file name, length of the pathname, size of a single file, and number of files, etc. +.. _zipfile-resources-limitations: + Resources limitations ~~~~~~~~~~~~~~~~~~~~~ diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index cd7030fed01732..fe1adcae163c23 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -23,8 +23,8 @@ and a path within the archive can be specified to only import from a subdirectory. For example, the path :file:`example.zip/lib/` would only import from the :file:`lib/` subdirectory within the archive. -Any files may be present in the ZIP archive, but only files :file:`.py` and -:file:`.pyc` are available for import. ZIP import of dynamic modules +Any files may be present in the ZIP archive, but importers are only invoked for +:file:`.py` and :file:`.pyc` files. ZIP import of dynamic modules (:file:`.pyd`, :file:`.so`) is disallowed. Note that if an archive only contains :file:`.py` files, Python will not attempt to modify the archive by adding the corresponding :file:`.pyc` file, meaning that if a ZIP archive diff --git a/Doc/license.rst b/Doc/license.rst index f487d98b2b43a3..e0ca5f2662dc1c 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -100,7 +100,7 @@ PSF LICENSE AGREEMENT FOR PYTHON |release| analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python |release| alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2021 Python Software Foundation; All Rights + copyright, i.e., "Copyright © 2001-2022 Python Software Foundation; All Rights Reserved" are retained in Python |release| alone or in any derivative version prepared by Licensee. @@ -203,9 +203,9 @@ CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the - Internet using the following unique, persistent identifier (known as a handle): + internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the - Internet using the following URL: http://hdl.handle.net/1895.22/1013." + internet using the following URL: http://hdl.handle.net/1895.22/1013." 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative @@ -655,7 +655,7 @@ OpenSSL The modules :mod:`hashlib`, :mod:`posix`, :mod:`ssl`, :mod:`crypt` use the OpenSSL library for added performance if made available by the -operating system. Additionally, the Windows and Mac OS X installers for +operating system. Additionally, the Windows and macOS installers for Python may include a copy of the OpenSSL libraries, so we include a copy of the OpenSSL license here:: @@ -955,7 +955,7 @@ W3C C14N test suite The C14N 2.0 test suite in the :mod:`test` package (``Lib/test/xmltestdata/c14n-20/``) was retrieved from the W3C website at https://www.w3.org/TR/xml-c14n2-testcases/ and is distributed under the -3-clause BSD license: +3-clause BSD license:: Copyright (c) 2013 W3C(R) (MIT, ERCIM, Keio, Beihang), All Rights Reserved. diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 96bd9b028d5044..7f37bb4fdf9c99 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -196,27 +196,6 @@ the built-in function :func:`range` returns an iterator of integers suitable to emulate the effect of Pascal's ``for i := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1, 2]``. -.. note:: - - .. index:: - single: loop; over mutable sequence - single: mutable sequence; loop over - - There is a subtlety when the sequence is being modified by the loop (this can - only occur for mutable sequences, e.g. lists). An internal counter is used - to keep track of which item is used next, and this is incremented on each - iteration. When this counter has reached the length of the sequence the loop - terminates. This means that if the suite deletes the current (or a previous) - item from the sequence, the next item will be skipped (since it gets the - index of the current item which has already been treated). Likewise, if the - suite inserts an item in the sequence before the current item, the current - item will be treated again the next time through the loop. This can lead to - nasty bugs that can be avoided by making a temporary copy using a slice of - the whole sequence, e.g., :: - - for x in a[:]: - if x < 0: a.remove(x) - .. _try: .. _except: @@ -418,8 +397,8 @@ usage patterns to be encapsulated for convenient reuse. The execution of the :keyword:`with` statement with one "item" proceeds as follows: -#. The context expression (the expression given in the :token:`with_item`) is - evaluated to obtain a context manager. +#. The context expression (the expression given in the + :token:`~python-grammar:with_item`) is evaluated to obtain a context manager. #. The context manager's :meth:`__enter__` is loaded for later use. @@ -585,8 +564,8 @@ Here's an overview of the logical flow of a match statement: #. If the pattern succeeds, the corresponding guard (if present) is evaluated. In this case all name bindings are guaranteed to have happened. - * If the guard evaluates as truthy or missing, the ``block`` inside ``case_block`` is - executed. + * If the guard evaluates as true or is missing, the ``block`` inside + ``case_block`` is executed. * Otherwise, the next ``case_block`` is attempted as described above. @@ -637,10 +616,10 @@ The logical flow of a ``case`` block with a ``guard`` follows: #. If the pattern succeeded, evaluate the ``guard``. - * If the ``guard`` condition evaluates to "truthy", the case block is + * If the ``guard`` condition evaluates as true, the case block is selected. - * If the ``guard`` condition evaluates to "falsy", the case block is not + * If the ``guard`` condition evaluates as false, the case block is not selected. * If the ``guard`` raises an exception during evaluation, the exception @@ -797,7 +776,8 @@ Syntax: capture_pattern: !'_' NAME A single underscore ``_`` is not a capture pattern (this is what ``!'_'`` -expresses). And is instead treated as a :token:`wildcard_pattern`. +expresses). It is instead treated as a +:token:`~python-grammar:wildcard_pattern`. In a given pattern, a given name can only be bound once. E.g. ``case x, x: ...`` is invalid while ``case [x] | x: ...`` is allowed. @@ -820,7 +800,9 @@ and binds no name. Syntax: .. productionlist:: python-grammar wildcard_pattern: '_' -``_`` is a :ref:`soft keyword `. +``_`` is a :ref:`soft keyword ` within any pattern, +but only within patterns. It is an identifier, as usual, even within +``match`` subject expressions, ``guard``\ s, and ``case`` blocks. In simple terms, ``_`` will always succeed. @@ -898,8 +880,8 @@ sequence pattern. The following is the logical flow for matching a sequence pattern against a subject value: -#. If the subject value is not an instance of a - :class:`collections.abc.Sequence` the sequence pattern fails. +#. If the subject value is not a sequence [#]_, the sequence pattern + fails. #. If the subject value is an instance of ``str``, ``bytes`` or ``bytearray`` the sequence pattern fails. @@ -941,7 +923,7 @@ subject value: In simple terms ``[P1, P2, P3,`` ... ``, P]`` matches only if all the following happens: -* ``isinstance(, collections.abc.Sequence)`` +* check ```` is a sequence * ``len(subject) == `` * ``P1`` matches ``[0]`` (note that this match can also bind names) * ``P2`` matches ``[1]`` (note that this match can also bind names) @@ -966,22 +948,22 @@ Syntax: At most one double star pattern may be in a mapping pattern. The double star pattern must be the last subpattern in the mapping pattern. -Duplicate key values in mapping patterns are disallowed. (If all key patterns -are literal patterns this is considered a syntax error; otherwise this is a -runtime error and will raise :exc:`ValueError`.) +Duplicate keys in mapping patterns are disallowed. Duplicate literal keys will +raise a :exc:`SyntaxError`. Two keys that otherwise have the same value will +raise a :exc:`ValueError` at runtime. The following is the logical flow for matching a mapping pattern against a subject value: -#. If the subject value is not an instance of :class:`collections.abc.Mapping`, - the mapping pattern fails. +#. If the subject value is not a mapping [#]_,the mapping pattern fails. #. If every key given in the mapping pattern is present in the subject mapping, and the pattern for each key matches the corresponding item of the subject mapping, the mapping pattern succeeds. #. If duplicate keys are detected in the mapping pattern, the pattern is - considered invalid and :exc:`ValueError` is raised. + considered invalid. A :exc:`SyntaxError` is raised for duplicate literal + values; or a :exc:`ValueError` for named keys of the same value. .. note:: Key-value pairs are matched using the two-argument form of the mapping subject's ``get()`` method. Matched key-value pairs must already be present @@ -991,7 +973,7 @@ subject value: In simple terms ``{KEY1: P1, KEY2: P2, ... }`` matches only if all the following happens: -* ``isinstance(, collections.abc.Mapping)`` +* check ```` is a mapping * ``KEY1 in `` * ``P1`` matches ``[KEY1]`` * ... and so on for the corresponding KEY/pattern pair. @@ -1015,7 +997,7 @@ A class pattern represents a class and its positional and keyword arguments The same keyword should not be repeated in class patterns. -The following is the logical flow for matching a mapping pattern against a +The following is the logical flow for matching a class pattern against a subject value: #. If ``name_or_attr`` is not an instance of the builtin :class:`type` , raise @@ -1053,7 +1035,7 @@ subject value: patterns using the :data:`~object.__match_args__` attribute on the class ``name_or_attr`` before matching: - I. The equivalent of ``getattr(cls, "__match_args__", ()))`` is called. + I. The equivalent of ``getattr(cls, "__match_args__", ())`` is called. * If this raises an exception, the exception bubbles up. @@ -1180,9 +1162,9 @@ is roughly equivalent to :: except that the original function is not temporarily bound to the name ``func``. .. versionchanged:: 3.9 - Functions may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Functions may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. .. index:: triple: default; parameter; value @@ -1358,9 +1340,9 @@ The evaluation rules for the decorator expressions are the same as for function decorators. The result is then bound to the class name. .. versionchanged:: 3.9 - Classes may be decorated with any valid :token:`assignment_expression`. - Previously, the grammar was much more restrictive; see :pep:`614` for - details. + Classes may be decorated with any valid + :token:`~python-grammar:assignment_expression`. Previously, the grammar was + much more restrictive; see :pep:`614` for details. **Programmer's note:** Variables defined in the class definition are class attributes; they are shared by instances. Instance attributes can be set in a @@ -1524,6 +1506,35 @@ body of a coroutine function. there is a :keyword:`finally` clause which happens to raise another exception. That new exception causes the old one to be lost. +.. [#] In pattern matching, a sequence is defined as one of the following: + + * a class that inherits from :class:`collections.abc.Sequence` + * a Python class that has been registered as :class:`collections.abc.Sequence` + * a builtin class that has its (CPython) :data:`Py_TPFLAGS_SEQUENCE` bit set + * a class that inherits from any of the above + + The following standard library classes are sequences: + + * :class:`array.array` + * :class:`collections.deque` + * :class:`list` + * :class:`memoryview` + * :class:`range` + * :class:`tuple` + + .. note:: Subject values of type ``str``, ``bytes``, and ``bytearray`` + do not match sequence patterns. + +.. [#] In pattern matching, a mapping is defined as one of the following: + + * a class that inherits from :class:`collections.abc.Mapping` + * a Python class that has been registered as :class:`collections.abc.Mapping` + * a builtin class that has its (CPython) :data:`Py_TPFLAGS_MAPPING` bit set + * a class that inherits from any of the above + + The standard library classes :class:`dict` and :class:`types.MappingProxyType` + are mappings. + .. [#] A string literal appearing as the first statement in the function body is transformed into the function's ``__doc__`` attribute and therefore the function's :term:`docstring`. diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index eefdc3d5100b56..be1f7141132934 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -188,7 +188,7 @@ Ellipsis representation in computers. The string representations of the numeric classes, computed by - :meth:`__repr__` and :meth:`__str__`, have the following + :meth:`~object.__repr__` and :meth:`~object.__str__`, have the following properties: * They are valid numeric literals which, when passed to their @@ -648,13 +648,13 @@ Callable types A function or method which uses the :keyword:`yield` statement (see section :ref:`yield`) is called a :dfn:`generator function`. Such a function, when - called, always returns an iterator object which can be used to execute the - body of the function: calling the iterator's :meth:`iterator.__next__` - method will cause the function to execute until it provides a value - using the :keyword:`!yield` statement. When the function executes a - :keyword:`return` statement or falls off the end, a :exc:`StopIteration` - exception is raised and the iterator will have reached the end of the set of - values to be returned. + called, always returns an :term:`iterator` object which can be used to + execute the body of the function: calling the iterator's + :meth:`iterator.__next__` method will cause the function to execute until + it provides a value using the :keyword:`!yield` statement. When the + function executes a :keyword:`return` statement or falls off the end, a + :exc:`StopIteration` exception is raised and the iterator will have + reached the end of the set of values to be returned. Coroutine functions .. index:: @@ -674,10 +674,11 @@ Callable types A function or method which is defined using :keyword:`async def` and which uses the :keyword:`yield` statement is called a :dfn:`asynchronous generator function`. Such a function, when called, - returns an asynchronous iterator object which can be used in an + returns an :term:`asynchronous iterator` object which can be used in an :keyword:`async for` statement to execute the body of the function. - Calling the asynchronous iterator's :meth:`aiterator.__anext__` method + Calling the asynchronous iterator's + :meth:`aiterator.__anext__ ` method will return an :term:`awaitable` which when awaited will execute until it provides a value using the :keyword:`yield` expression. When the function executes an empty :keyword:`return` @@ -715,13 +716,13 @@ Callable types Classes Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that - override :meth:`__new__`. The arguments of the call are passed to - :meth:`__new__` and, in the typical case, to :meth:`__init__` to + override :meth:`~object.__new__`. The arguments of the call are passed to + :meth:`__new__` and, in the typical case, to :meth:`~object.__init__` to initialize the new instance. Class Instances Instances of arbitrary classes can be made callable by defining a - :meth:`__call__` method in their class. + :meth:`~object.__call__` method in their class. Modules @@ -880,14 +881,14 @@ Class instances section :ref:`descriptors` for another way in which attributes of a class retrieved via its instances may differ from the objects actually stored in the class's :attr:`~object.__dict__`. If no class attribute is found, and the - object's class has a :meth:`__getattr__` method, that is called to satisfy + object's class has a :meth:`~object.__getattr__` method, that is called to satisfy the lookup. .. index:: triple: class instance; attribute; assignment Attribute assignments and deletions update the instance's dictionary, never a - class's dictionary. If the class has a :meth:`__setattr__` or - :meth:`__delattr__` method, this is called instead of updating the instance + class's dictionary. If the class has a :meth:`~object.__setattr__` or + :meth:`~object.__delattr__` method, this is called instead of updating the instance dictionary directly. .. index:: @@ -1141,7 +1142,8 @@ Internal types Slice objects .. index:: builtin: slice - Slice objects are used to represent slices for :meth:`__getitem__` + Slice objects are used to represent slices for + :meth:`~object.__getitem__` methods. They are also created by the built-in :func:`slice` function. .. index:: @@ -1194,7 +1196,8 @@ A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python's approach to :dfn:`operator overloading`, allowing classes to define their own behavior with respect to language -operators. For instance, if a class defines a method named :meth:`__getitem__`, +operators. For instance, if a class defines a method named +:meth:`~object.__getitem__`, and ``x`` is an instance of this class, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x, i)``. Except where mentioned, attempts to execute an operation raise an exception when no appropriate method is defined (typically @@ -1202,9 +1205,9 @@ operation raise an exception when no appropriate method is defined (typically Setting a special method to ``None`` indicates that the corresponding operation is not available. For example, if a class sets -:meth:`__iter__` to ``None``, the class is not iterable, so calling +:meth:`~object.__iter__` to ``None``, the class is not iterable, so calling :func:`iter` on its instances will raise a :exc:`TypeError` (without -falling back to :meth:`__getitem__`). [#]_ +falling back to :meth:`~object.__getitem__`). [#]_ When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the @@ -1236,7 +1239,7 @@ Basic customization as necessary before returning it. If :meth:`__new__` is invoked during object construction and it returns an - instance or subclass of *cls*, then the new instance’s :meth:`__init__` method + instance of *cls*, then the new instance’s :meth:`__init__` method will be invoked like ``__init__(self[, ...])``, where *self* is the new instance and the remaining arguments are the same as were passed to the object constructor. @@ -1523,7 +1526,7 @@ Basic customization This is intended to provide protection against a denial-of-service caused by carefully-chosen inputs that exploit the worst case performance of a - dict insertion, O(n^2) complexity. See + dict insertion, O(n\ :sup:`2`) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details. Changing hash values affects the iteration order of sets. @@ -1739,28 +1742,6 @@ class' :attr:`~object.__dict__`. Called to delete the attribute on an instance *instance* of the owner class. -.. method:: object.__set_name__(self, owner, name) - - Called at the time the owning class *owner* is created. The - descriptor has been assigned to *name*. - - .. note:: - - :meth:`__set_name__` is only called implicitly as part of the - :class:`type` constructor, so it will need to be called explicitly with - the appropriate parameters when a descriptor is added to a class after - initial creation:: - - class A: - pass - descr = custom_descriptor() - A.attr = descr - descr.__set_name__(A, 'attr') - - See :ref:`class-object-creation` for more details. - - .. versionadded:: 3.6 - The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module as specifying the class where this object was defined (setting this appropriately can assist in runtime introspection of dynamic class attributes). @@ -1776,7 +1757,8 @@ Invoking Descriptors In general, a descriptor is an object attribute with "binding behavior", one whose attribute access has been overridden by methods in the descriptor -protocol: :meth:`__get__`, :meth:`__set__`, and :meth:`__delete__`. If any of +protocol: :meth:`~object.__get__`, :meth:`~object.__set__`, and +:meth:`~object.__delete__`. If any of those methods are defined for an object, it is said to be a descriptor. The default behavior for attribute access is to get, set, or delete the @@ -1807,12 +1789,13 @@ Class Binding Super Binding If ``a`` is an instance of :class:`super`, then the binding ``super(B, obj).m()`` searches ``obj.__class__.__mro__`` for the base class ``A`` - immediately preceding ``B`` and then invokes the descriptor with the call: + immediately following ``B`` and then invokes the descriptor with the call: ``A.__dict__['m'].__get__(obj, obj.__class__)``. For instance bindings, the precedence of descriptor invocation depends on which descriptor methods are defined. A descriptor can define any combination -of :meth:`__get__`, :meth:`__set__` and :meth:`__delete__`. If it does not +of :meth:`~object.__get__`, :meth:`~object.__set__` and +:meth:`~object.__delete__`. If it does not define :meth:`__get__`, then accessing the attribute will return the descriptor object itself unless there is a value in the object's instance dictionary. If the descriptor defines :meth:`__set__` and/or :meth:`__delete__`, it is a data @@ -1823,7 +1806,8 @@ descriptors have just the :meth:`__get__` method. Data descriptors with instance dictionary. In contrast, non-data descriptors can be overridden by instances. -Python methods (including :func:`staticmethod` and :func:`classmethod`) are +Python methods (including those decorated with +:func:`@staticmethod ` and :func:`@classmethod `) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class. @@ -1838,46 +1822,50 @@ __slots__ ^^^^^^^^^ *__slots__* allow us to explicitly declare data members (like -properties) and deny the creation of *__dict__* and *__weakref__* +properties) and deny the creation of :attr:`~object.__dict__` and *__weakref__* (unless explicitly declared in *__slots__* or available in a parent.) -The space saved over using *__dict__* can be significant. +The space saved over using :attr:`~object.__dict__` can be significant. Attribute lookup speed can be significantly improved as well. .. data:: object.__slots__ This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. *__slots__* reserves space - for the declared variables and prevents the automatic creation of *__dict__* + for the declared variables and prevents the automatic creation of + :attr:`~object.__dict__` and *__weakref__* for each instance. Notes on using *__slots__* """""""""""""""""""""""""" -* When inheriting from a class without *__slots__*, the *__dict__* and +* When inheriting from a class without *__slots__*, the + :attr:`~object.__dict__` and *__weakref__* attribute of the instances will always be accessible. -* Without a *__dict__* variable, instances cannot be assigned new variables not +* Without a :attr:`~object.__dict__` variable, instances cannot be assigned new + variables not listed in the *__slots__* definition. Attempts to assign to an unlisted variable name raises :exc:`AttributeError`. If dynamic assignment of new variables is desired, then add ``'__dict__'`` to the sequence of strings in the *__slots__* declaration. * Without a *__weakref__* variable for each instance, classes defining - *__slots__* do not support weak references to its instances. If weak reference + *__slots__* do not support :mod:`weak references ` to its instances. + If weak reference support is needed, then add ``'__weakref__'`` to the sequence of strings in the *__slots__* declaration. -* *__slots__* are implemented at the class level by creating descriptors - (:ref:`descriptors`) for each variable name. As a result, class attributes +* *__slots__* are implemented at the class level by creating :ref:`descriptors ` + for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by *__slots__*; otherwise, the class attribute would overwrite the descriptor assignment. * The action of a *__slots__* declaration is not limited to the class where it is defined. *__slots__* declared in parents are available in - child classes. However, child subclasses will get a *__dict__* and + child classes. However, child subclasses will get a :attr:`~object.__dict__` and *__weakref__* unless they also define *__slots__* (which should only contain names of any *additional* slots). @@ -1889,18 +1877,24 @@ Notes on using *__slots__* * Nonempty *__slots__* does not work for classes derived from "variable-length" built-in types such as :class:`int`, :class:`bytes` and :class:`tuple`. -* Any non-string iterable may be assigned to *__slots__*. Mappings may also be - used; however, in the future, special meaning may be assigned to the values - corresponding to each key. +* Any non-string :term:`iterable` may be assigned to *__slots__*. -* *__class__* assignment works only if both classes have the same *__slots__*. +* If a :class:`dictionary ` is used to assign *__slots__*, the dictionary + keys will be used as the slot names. The values of the dictionary can be used + to provide per-attribute docstrings that will be recognised by + :func:`inspect.getdoc` and displayed in the output of :func:`help`. -* Multiple inheritance with multiple slotted parent classes can be used, +* :attr:`~instance.__class__` assignment works only if both classes have the + same *__slots__*. + +* :ref:`Multiple inheritance ` with multiple slotted parent + classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise :exc:`TypeError`. -* If an iterator is used for *__slots__* then a descriptor is created for each +* If an :term:`iterator` is used for *__slots__* then a :term:`descriptor` is + created for each of the iterator's values. However, the *__slots__* attribute will be an empty iterator. @@ -1909,7 +1903,7 @@ Notes on using *__slots__* Customizing class creation -------------------------- -Whenever a class inherits from another class, *__init_subclass__* is +Whenever a class inherits from another class, :meth:`~object.__init_subclass__` is called on that class. This way, it is possible to write classes which change the behavior of subclasses. This is closely related to class decorators, but where class decorators only affect the specific class they're @@ -1949,6 +1943,33 @@ class defining the method. .. versionadded:: 3.6 +When a class is created, :meth:`type.__new__` scans the class variables +and makes callbacks to those with a :meth:`~object.__set_name__` hook. + +.. method:: object.__set_name__(self, owner, name) + + Automatically called at the time the owning class *owner* is + created. The object has been assigned to *name* in that class:: + + class A: + x = C() # Automatically calls: x.__set_name__(A, 'x') + + If the class variable is assigned after the class is created, + :meth:`__set_name__` will not be called automatically. + If needed, :meth:`__set_name__` can be called directly:: + + class A: + pass + + c = C() + A.x = c # The hook is not called + c.__set_name__(A, 'x') # Manually invoke the hook + + See :ref:`class-object-creation` for more details. + + .. versionadded:: 3.6 + + .. _metaclasses: Metaclasses @@ -2035,7 +2056,8 @@ Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a ``__prepare__`` attribute, it is called as ``namespace = metaclass.__prepare__(name, bases, **kwds)`` (where the additional keyword arguments, if any, come from the class definition). The -``__prepare__`` method should be implemented as a :func:`classmethod`. The +``__prepare__`` method should be implemented as a +:func:`classmethod `. The namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. @@ -2098,15 +2120,15 @@ current call is identified based on the first argument passed to the method. Failing to do so will result in a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately -calls ``type.__new__``, the following additional customisation steps are +calls ``type.__new__``, the following additional customization steps are invoked after creating the class object: -* first, ``type.__new__`` collects all of the descriptors in the class - namespace that define a :meth:`~object.__set_name__` method; -* second, all of these ``__set_name__`` methods are called with the class - being defined and the assigned name of that particular descriptor; -* finally, the :meth:`~object.__init_subclass__` hook is called on the - immediate parent of the new class in its method resolution order. +1) The ``type.__new__`` method collects all of the attributes in the class + namespace that define a :meth:`~object.__set_name__` method; +2) Those ``__set_name__`` methods are called with the class + being defined and the assigned name of that particular attribute; +3) The :meth:`~object.__init_subclass__` hook is called on the + immediate parent of the new class in its method resolution order. After the class object is created, it is passed to the class decorators included in the class definition (if any) and the resulting object is bound @@ -2175,22 +2197,142 @@ case the instance is itself a class. Emulating generic types ----------------------- -One can implement the generic class syntax as specified by :pep:`484` -(for example ``List[int]``) by defining a special method: +When using :term:`type annotations`, it is often useful to +*parameterize* a :term:`generic type` using Python's square-brackets notation. +For example, the annotation ``list[int]`` might be used to signify a +:class:`list` in which all the elements are of type :class:`int`. + +.. seealso:: + + :pep:`484` - Type Hints + Introducing Python's framework for type annotations + + :ref:`Generic Alias Types` + Documentation for objects representing parameterized generic classes + + :ref:`Generics`, :ref:`user-defined generics` and :class:`typing.Generic` + Documentation on how to implement generic classes that can be + parameterized at runtime and understood by static type-checkers. + +A class can *generally* only be parameterized if it defines the special +class method ``__class_getitem__()``. .. classmethod:: object.__class_getitem__(cls, key) Return an object representing the specialization of a generic class by type arguments found in *key*. -This method is looked up on the class object itself, and when defined in -the class body, this method is implicitly a class method. Note, this -mechanism is primarily reserved for use with static type hints, other usage -is discouraged. + When defined on a class, ``__class_getitem__()`` is automatically a class + method. As such, there is no need for it to be decorated with + :func:`@classmethod` when it is defined. -.. seealso:: - :pep:`560` - Core support for typing module and generic types +The purpose of *__class_getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The purpose of :meth:`~object.__class_getitem__` is to allow runtime +parameterization of standard-library generic classes in order to more easily +apply :term:`type hints` to these classes. + +To implement custom generic classes that can be parameterized at runtime and +understood by static type-checkers, users should either inherit from a standard +library class that already implements :meth:`~object.__class_getitem__`, or +inherit from :class:`typing.Generic`, which has its own implementation of +``__class_getitem__()``. + +Custom implementations of :meth:`~object.__class_getitem__` on classes defined +outside of the standard library may not be understood by third-party +type-checkers such as mypy. Using ``__class_getitem__()`` on any class for +purposes other than type hinting is discouraged. + + +.. _classgetitem-versus-getitem: + + +*__class_getitem__* versus *__getitem__* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Usually, the :ref:`subscription` of an object using square +brackets will call the :meth:`~object.__getitem__` instance method defined on +the object's class. However, if the object being subscribed is itself a class, +the class method :meth:`~object.__class_getitem__` may be called instead. +``__class_getitem__()`` should return a :ref:`GenericAlias` +object if it is properly defined. + +Presented with the :term:`expression` ``obj[x]``, the Python interpreter +follows something like the following process to decide whether +:meth:`~object.__getitem__` or :meth:`~object.__class_getitem__` should be +called:: + + from inspect import isclass + + def subscribe(obj, x): + """Return the result of the expression `obj[x]`""" + + class_of_obj = type(obj) + + # If the class of obj defines __getitem__, + # call class_of_obj.__getitem__(obj, x) + if hasattr(class_of_obj, '__getitem__'): + return class_of_obj.__getitem__(obj, x) + + # Else, if obj is a class and defines __class_getitem__, + # call obj.__class_getitem__(x) + elif isclass(obj) and hasattr(obj, '__class_getitem__'): + return obj.__class_getitem__(x) + + # Else, raise an exception + else: + raise TypeError( + f"'{class_of_obj.__name__}' object is not subscriptable" + ) + +In Python, all classes are themselves instances of other classes. The class of +a class is known as that class's :term:`metaclass`, and most classes have the +:class:`type` class as their metaclass. :class:`type` does not define +:meth:`~object.__getitem__`, meaning that expressions such as ``list[int]``, +``dict[str, float]`` and ``tuple[str, bytes]`` all result in +:meth:`~object.__class_getitem__` being called:: + + >>> # list has class "type" as its metaclass, like most classes: + >>> type(list) + + >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes) + True + >>> # "list[int]" calls "list.__class_getitem__(int)" + >>> list[int] + list[int] + >>> # list.__class_getitem__ returns a GenericAlias object: + >>> type(list[int]) + + +However, if a class has a custom metaclass that defines +:meth:`~object.__getitem__`, subscribing the class may result in different +behaviour. An example of this can be found in the :mod:`enum` module:: + + >>> from enum import Enum + >>> class Menu(Enum): + ... """A breakfast menu""" + ... SPAM = 'spam' + ... BACON = 'bacon' + ... + >>> # Enum classes have a custom metaclass: + >>> type(Menu) + + >>> # EnumMeta defines __getitem__, + >>> # so __class_getitem__ is not called, + >>> # and the result is not a GenericAlias object: + >>> Menu['SPAM'] + + >>> type(Menu['SPAM']) + + + +.. seealso:: + :pep:`560` - Core Support for typing module and generic types + Introducing :meth:`~object.__class_getitem__`, and outlining when a + :ref:`subscription` results in ``__class_getitem__()`` + being called instead of :meth:`~object.__getitem__` .. _callable-types: @@ -2213,31 +2355,36 @@ Emulating container types ------------------------- The following methods can be defined to implement container objects. Containers -usually are sequences (such as lists or tuples) or mappings (like dictionaries), +usually are :term:`sequences ` (such as :class:`lists ` or +:class:`tuples `) or :term:`mappings ` (like +:class:`dictionaries `), but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers *k* for which ``0 <= k < -N`` where *N* is the length of the sequence, or slice objects, which define a +N`` where *N* is the length of the sequence, or :class:`slice` objects, which define a range of items. It is also recommended that mappings provide the methods :meth:`keys`, :meth:`values`, :meth:`items`, :meth:`get`, :meth:`clear`, :meth:`setdefault`, :meth:`pop`, :meth:`popitem`, :meth:`!copy`, and -:meth:`update` behaving similar to those for Python's standard dictionary +:meth:`update` behaving similar to those for Python's standard :class:`dictionary ` objects. The :mod:`collections.abc` module provides a :class:`~collections.abc.MutableMapping` -abstract base class to help create those methods from a base set of -:meth:`__getitem__`, :meth:`__setitem__`, :meth:`__delitem__`, and :meth:`keys`. +:term:`abstract base class` to help create those methods from a base set of +:meth:`~object.__getitem__`, :meth:`~object.__setitem__`, :meth:`~object.__delitem__`, and :meth:`keys`. Mutable sequences should provide methods :meth:`append`, :meth:`count`, :meth:`index`, :meth:`extend`, :meth:`insert`, :meth:`pop`, :meth:`remove`, -:meth:`reverse` and :meth:`sort`, like Python standard list objects. Finally, +:meth:`reverse` and :meth:`sort`, like Python standard :class:`list` +objects. Finally, sequence types should implement addition (meaning concatenation) and -multiplication (meaning repetition) by defining the methods :meth:`__add__`, -:meth:`__radd__`, :meth:`__iadd__`, :meth:`__mul__`, :meth:`__rmul__` and -:meth:`__imul__` described below; they should not define other numerical +multiplication (meaning repetition) by defining the methods +:meth:`~object.__add__`, :meth:`~object.__radd__`, :meth:`~object.__iadd__`, +:meth:`~object.__mul__`, :meth:`~object.__rmul__` and :meth:`~object.__imul__` +described below; they should not define other numerical operators. It is recommended that both mappings and sequences implement the -:meth:`__contains__` method to allow efficient use of the ``in`` operator; for +:meth:`~object.__contains__` method to allow efficient use of the ``in`` +operator; for mappings, ``in`` should search the mapping's keys; for sequences, it should search through the values. It is further recommended that both mappings and -sequences implement the :meth:`__iter__` method to allow efficient iteration +sequences implement the :meth:`~object.__iter__` method to allow efficient iteration through the container; for mappings, :meth:`__iter__` should iterate through the object's keys; for sequences, it should iterate through the values. @@ -2290,19 +2437,27 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__getitem__(self, key) - Called to implement evaluation of ``self[key]``. For sequence types, the - accepted keys should be integers and slice objects. Note that the special - interpretation of negative indexes (if the class wishes to emulate a sequence - type) is up to the :meth:`__getitem__` method. If *key* is of an inappropriate - type, :exc:`TypeError` may be raised; if of a value outside the set of indexes - for the sequence (after any special interpretation of negative values), - :exc:`IndexError` should be raised. For mapping types, if *key* is missing (not - in the container), :exc:`KeyError` should be raised. + Called to implement evaluation of ``self[key]``. For :term:`sequence` types, + the accepted keys should be integers and slice objects. Note that the + special interpretation of negative indexes (if the class wishes to emulate a + :term:`sequence` type) is up to the :meth:`__getitem__` method. If *key* is + of an inappropriate type, :exc:`TypeError` may be raised; if of a value + outside the set of indexes for the sequence (after any special + interpretation of negative values), :exc:`IndexError` should be raised. For + :term:`mapping` types, if *key* is missing (not in the container), + :exc:`KeyError` should be raised. .. note:: - :keyword:`for` loops expect that an :exc:`IndexError` will be raised for illegal - indexes to allow proper detection of the end of the sequence. + :keyword:`for` loops expect that an :exc:`IndexError` will be raised for + illegal indexes to allow proper detection of the end of the sequence. + + .. note:: + + When :ref:`subscripting` a *class*, the special + class method :meth:`~object.__class_getitem__` may be called instead of + ``__getitem__()``. See :ref:`classgetitem-versus-getitem` for more + details. .. method:: object.__setitem__(self, key, value) @@ -2331,12 +2486,10 @@ through the object's keys; for sequences, it should iterate through the values. .. method:: object.__iter__(self) - This method is called when an iterator is required for a container. This method - should return a new iterator object that can iterate over all the objects in the - container. For mappings, it should iterate over the keys of the container. - - Iterator objects also need to implement this method; they are required to return - themselves. For more information on iterator objects, see :ref:`typeiter`. + This method is called when an :term:`iterator` is required for a container. + This method should return a new iterator object that can iterate over all the + objects in the container. For mappings, it should iterate over the keys of + the container. .. method:: object.__reversed__(self) @@ -2536,8 +2689,8 @@ left undefined. return the value of the object truncated to an :class:`~numbers.Integral` (typically an :class:`int`). - If :meth:`__int__` is not defined then the built-in function :func:`int` - falls back to :meth:`__trunc__`. + The built-in function :func:`int` falls back to :meth:`__trunc__` if neither + :meth:`__int__` nor :meth:`__index__` is defined. .. _context-managers: @@ -2643,7 +2796,8 @@ exception:: TypeError: object of type 'C' has no len() The rationale behind this behaviour lies with a number of special methods such -as :meth:`__hash__` and :meth:`__repr__` that are implemented by all objects, +as :meth:`~object.__hash__` and :meth:`~object.__repr__` that are implemented +by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself:: @@ -2666,7 +2820,7 @@ the instance when looking up special methods:: In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the -:meth:`__getattribute__` method even of the object's metaclass:: +:meth:`~object.__getattribute__` method even of the object's metaclass:: >>> class Meta(type): ... def __getattribute__(*args): @@ -2690,7 +2844,7 @@ correctness, implicit special method lookup generally also bypasses the >>> len(c) # Implicit lookup 10 -Bypassing the :meth:`__getattribute__` machinery in this fashion +Bypassing the :meth:`~object.__getattribute__` machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method *must* be set on the class @@ -2707,7 +2861,7 @@ Coroutines Awaitable Objects ----------------- -An :term:`awaitable` object generally implements an :meth:`__await__` method. +An :term:`awaitable` object generally implements an :meth:`~object.__await__` method. :term:`Coroutine objects ` returned from :keyword:`async def` functions are awaitable. @@ -2715,7 +2869,7 @@ are awaitable. The :term:`generator iterator` objects returned from generators decorated with :func:`types.coroutine` or :func:`asyncio.coroutine` - are also awaitable, but they do not implement :meth:`__await__`. + are also awaitable, but they do not implement :meth:`~object.__await__`. .. method:: object.__await__(self) @@ -2734,7 +2888,7 @@ Coroutine Objects ----------------- :term:`Coroutine objects ` are :term:`awaitable` objects. -A coroutine's execution can be controlled by calling :meth:`__await__` and +A coroutine's execution can be controlled by calling :meth:`~object.__await__` and iterating over the result. When the coroutine has finished executing and returns, the iterator raises :exc:`StopIteration`, and the exception's :attr:`~StopIteration.value` attribute holds the return value. If the @@ -2753,7 +2907,7 @@ generators, coroutines do not directly support iteration. Starts or resumes execution of the coroutine. If *value* is ``None``, this is equivalent to advancing the iterator returned by - :meth:`__await__`. If *value* is not ``None``, this method delegates + :meth:`~object.__await__`. If *value* is not ``None``, this method delegates to the :meth:`~generator.send` method of the iterator that caused the coroutine to suspend. The result (return value, :exc:`StopIteration`, or other exception) is the same as when @@ -2766,7 +2920,7 @@ generators, coroutines do not directly support iteration. the coroutine to suspend, if it has such a method. Otherwise, the exception is raised at the suspension point. The result (return value, :exc:`StopIteration`, or other exception) is the same as - when iterating over the :meth:`__await__` return value, described + when iterating over the :meth:`~object.__await__` return value, described above. If the exception is not caught in the coroutine, it propagates back to the caller. @@ -2820,11 +2974,11 @@ An example of an asynchronous iterable object:: .. versionadded:: 3.5 .. versionchanged:: 3.7 - Prior to Python 3.7, ``__aiter__`` could return an *awaitable* + Prior to Python 3.7, :meth:`~object.__aiter__` could return an *awaitable* that would resolve to an :term:`asynchronous iterator `. - Starting with Python 3.7, ``__aiter__`` must return an + Starting with Python 3.7, :meth:`~object.__aiter__` must return an asynchronous iterator object. Returning anything else will result in a :exc:`TypeError` error. @@ -2867,8 +3021,9 @@ An example of an asynchronous context manager class:: controlled conditions. It generally isn't a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly. -.. [#] The :meth:`__hash__`, :meth:`__iter__`, :meth:`__reversed__`, and - :meth:`__contains__` methods have special handling for this; others +.. [#] The :meth:`~object.__hash__`, :meth:`~object.__iter__`, + :meth:`~object.__reversed__`, and :meth:`~object.__contains__` methods have + special handling for this; others will still raise a :exc:`TypeError`, but may do so by relying on the behavior that ``None`` is not callable. @@ -2879,5 +3034,6 @@ An example of an asynchronous context manager class:: *blocking* such fallback. .. [#] For operands of the same type, it is assumed that if the non-reflected - method -- such as :meth:`__add__` -- fails then the overall operation is not + method -- such as :meth:`~object.__add__` -- fails then the overall + operation is not supported, which is why the reflected method is not called. diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index 55ac01b6a844dc..e652915bd271c3 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -56,15 +56,25 @@ Binding of names .. index:: single: from; import statement -The following constructs bind names: formal parameters to functions, -:keyword:`import` statements, class and function definitions (these bind the -class or function name in the defining block), and targets that are identifiers -if occurring in an assignment, :keyword:`for` loop header, or after -:keyword:`!as` in a :keyword:`with` statement or :keyword:`except` clause. -The :keyword:`!import` statement -of the form ``from ... import *`` binds all names defined in the imported -module, except those beginning with an underscore. This form may only be used -at the module level. +The following constructs bind names: + +* formal parameters to functions, +* class definitions, +* function definitions, +* assignment expressions, +* :ref:`targets ` that are identifiers if occurring in + an assignment: + + + :keyword:`for` loop header, + + after :keyword:`!as` in a :keyword:`with` statement, :keyword:`except` + clause or in the as-pattern in structural pattern matching, + + in a capture pattern in structural pattern matching + +* :keyword:`import` statements. + +The :keyword:`!import` statement of the form ``from ... import *`` binds all +names defined in the imported module, except those beginning with an underscore. +This form may only be used at the module level. A target occurring in a :keyword:`del` statement is also considered bound for this purpose (though the actual semantics are to unbind the name). @@ -119,14 +129,14 @@ is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations. -If the :keyword:`global` statement occurs within a block, all uses of the name -specified in the statement refer to the binding of that name in the top-level +If the :keyword:`global` statement occurs within a block, all uses of the names +specified in the statement refer to the bindings of those names in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module :mod:`builtins`. The -global namespace is searched first. If the name is not found there, the +global namespace is searched first. If the names are not found there, the builtins namespace is searched. The :keyword:`!global` statement must precede -all uses of the name. +all uses of the listed names. The :keyword:`global` statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 5ad640ad35d615..d4aae29725fb4c 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -422,9 +422,9 @@ Yield expressions The yield expression is used when defining a :term:`generator` function or an :term:`asynchronous generator` function and thus can only be used in the body of a function definition. Using a yield -expression in a function's body causes that function to be a generator, +expression in a function's body causes that function to be a generator function, and using it in an :keyword:`async def` function's body causes that -coroutine function to be an asynchronous generator. For example:: +coroutine function to be an asynchronous generator function. For example:: def gen(): # defines a generator function yield 123 @@ -445,21 +445,20 @@ functions are described separately in section :ref:`asynchronous-generator-functions`. When a generator function is called, it returns an iterator known as a -generator. That generator then controls the execution of the generator function. -The execution starts when one of the generator's methods is called. At that -time, the execution proceeds to the first yield expression, where it is -suspended again, returning the value of :token:`expression_list` to the generator's -caller. By suspended, we mean that all local state is retained, including the -current bindings of local variables, the instruction pointer, the internal -evaluation stack, and the state of any exception handling. When the execution -is resumed by calling one of the -generator's methods, the function can proceed exactly as if the yield expression -were just another external call. The value of the yield expression after -resuming depends on the method which resumed the execution. If -:meth:`~generator.__next__` is used (typically via either a :keyword:`for` or -the :func:`next` builtin) then the result is :const:`None`. Otherwise, if -:meth:`~generator.send` is used, then the result will be the value passed in to -that method. +generator. That generator then controls the execution of the generator +function. The execution starts when one of the generator's methods is called. +At that time, the execution proceeds to the first yield expression, where it is +suspended again, returning the value of :token:`~python-grammar:expression_list` +to the generator's caller. By suspended, we mean that all local state is +retained, including the current bindings of local variables, the instruction +pointer, the internal evaluation stack, and the state of any exception handling. +When the execution is resumed by calling one of the generator's methods, the +function can proceed exactly as if the yield expression were just another +external call. The value of the yield expression after resuming depends on the +method which resumed the execution. If :meth:`~generator.__next__` is used +(typically via either a :keyword:`for` or the :func:`next` builtin) then the +result is :const:`None`. Otherwise, if :meth:`~generator.send` is used, then +the result will be the value passed in to that method. .. index:: single: coroutine @@ -509,8 +508,8 @@ on the right hand side of an assignment statement. usable as simple coroutines. :pep:`380` - Syntax for Delegating to a Subgenerator - The proposal to introduce the :token:`yield_from` syntax, making delegation - to subgenerators easy. + The proposal to introduce the :token:`~python-grammar:yield_from` syntax, + making delegation to subgenerators easy. :pep:`525` - Asynchronous Generators The proposal that expanded on :pep:`492` by adding generator capabilities to @@ -538,9 +537,9 @@ is already executing raises a :exc:`ValueError` exception. :meth:`~generator.__next__` method, the current yield expression always evaluates to :const:`None`. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the - :token:`expression_list` is returned to :meth:`__next__`'s caller. If the - generator exits without yielding another value, a :exc:`StopIteration` - exception is raised. + :token:`~python-grammar:expression_list` is returned to :meth:`__next__`'s + caller. If the generator exits without yielding another value, a + :exc:`StopIteration` exception is raised. This method is normally called implicitly, e.g. by a :keyword:`for` loop, or by the built-in :func:`next` function. @@ -629,21 +628,20 @@ An asynchronous generator object is typically used in an :keyword:`async for` statement in a coroutine function analogously to how a generator object would be used in a :keyword:`for` statement. -Calling one of the asynchronous generator's methods returns an -:term:`awaitable` object, and the execution starts when this object -is awaited on. At that time, the execution proceeds to the first yield -expression, where it is suspended again, returning the value of -:token:`expression_list` to the awaiting coroutine. As with a generator, -suspension means that all local state is retained, including the -current bindings of local variables, the instruction pointer, the internal -evaluation stack, and the state of any exception handling. When the execution -is resumed by awaiting on the next object returned by the asynchronous -generator's methods, the function can proceed exactly as if the yield -expression were just another external call. The value of the yield expression -after resuming depends on the method which resumed the execution. If +Calling one of the asynchronous generator's methods returns an :term:`awaitable` +object, and the execution starts when this object is awaited on. At that time, +the execution proceeds to the first yield expression, where it is suspended +again, returning the value of :token:`~python-grammar:expression_list` to the +awaiting coroutine. As with a generator, suspension means that all local state +is retained, including the current bindings of local variables, the instruction +pointer, the internal evaluation stack, and the state of any exception handling. +When the execution is resumed by awaiting on the next object returned by the +asynchronous generator's methods, the function can proceed exactly as if the +yield expression were just another external call. The value of the yield +expression after resuming depends on the method which resumed the execution. If :meth:`~agen.__anext__` is used then the result is :const:`None`. Otherwise, if -:meth:`~agen.asend` is used, then the result will be the value passed in to -that method. +:meth:`~agen.asend` is used, then the result will be the value passed in to that +method. If an asynchronous generator happens to exit early by :keyword:`break`, the caller task being cancelled, or other exceptions, the generator's async cleanup code @@ -695,10 +693,10 @@ which are used to control the execution of a generator function. Returns an awaitable which when run starts to execute the asynchronous generator or resumes it at the last executed yield expression. When an asynchronous generator function is resumed with an :meth:`~agen.__anext__` - method, the current yield expression always evaluates to :const:`None` in - the returned awaitable, which when run will continue to the next yield - expression. The value of the :token:`expression_list` of the yield - expression is the value of the :exc:`StopIteration` exception raised by + method, the current yield expression always evaluates to :const:`None` in the + returned awaitable, which when run will continue to the next yield + expression. The value of the :token:`~python-grammar:expression_list` of the + yield expression is the value of the :exc:`StopIteration` exception raised by the completing coroutine. If the asynchronous generator exits without yielding another value, the awaitable instead raises a :exc:`StopAsyncIteration` exception, signalling that the asynchronous @@ -1148,6 +1146,7 @@ Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`. Raising a negative number to a fractional power results in a :class:`complex` number. (In earlier versions it raised a :exc:`ValueError`.) +This operation can be customized using the special :meth:`__pow__` method. .. _unary: @@ -1169,14 +1168,16 @@ All unary arithmetic and bitwise operations have the same priority: single: operator; - (minus) single: - (minus); unary operator -The unary ``-`` (minus) operator yields the negation of its numeric argument. +The unary ``-`` (minus) operator yields the negation of its numeric argument; the +operation can be overridden with the :meth:`__neg__` special method. .. index:: single: plus single: operator; + (plus) single: + (plus); unary operator -The unary ``+`` (plus) operator yields its numeric argument unchanged. +The unary ``+`` (plus) operator yields its numeric argument unchanged; the +operation can be overridden with the :meth:`__pos__` special method. .. index:: single: inversion @@ -1184,7 +1185,10 @@ The unary ``+`` (plus) operator yields its numeric argument unchanged. The unary ``~`` (invert) operator yields the bitwise inversion of its integer argument. The bitwise inversion of ``x`` is defined as ``-(x+1)``. It only -applies to integral numbers. +applies to integral numbers or to custom objects that override the +:meth:`__invert__` special method. + + .. index:: exception: TypeError @@ -1220,6 +1224,9 @@ the other must be a sequence. In the former case, the numbers are converted to a common type and then multiplied together. In the latter case, sequence repetition is performed; a negative repetition factor yields an empty sequence. +This operation can be customized using the special :meth:`__mul__` and +:meth:`__rmul__` methods. + .. index:: single: matrix multiplication operator: @ (at) @@ -1242,6 +1249,9 @@ integer; the result is that of mathematical division with the 'floor' function applied to the result. Division by zero raises the :exc:`ZeroDivisionError` exception. +This operation can be customized using the special :meth:`__truediv__` and +:meth:`__floordiv__` methods. + .. index:: single: modulo operator: % (percent) @@ -1265,6 +1275,8 @@ also overloaded by string objects to perform old-style string formatting (also known as interpolation). The syntax for string formatting is described in the Python Library Reference, section :ref:`old-string-formatting`. +The *modulo* operation can be customized using the special :meth:`__mod__` method. + The floor division operator, the modulo operator, and the :func:`divmod` function are not defined for complex numbers. Instead, convert to a floating point number using the :func:`abs` function if appropriate. @@ -1279,6 +1291,9 @@ must either both be numbers or both be sequences of the same type. In the former case, the numbers are converted to a common type and then added together. In the latter case, the sequences are concatenated. +This operation can be customized using the special :meth:`__add__` and +:meth:`__radd__` methods. + .. index:: single: subtraction single: operator; - (minus) @@ -1287,6 +1302,8 @@ In the latter case, the sequences are concatenated. The ``-`` (subtraction) operator yields the difference of its arguments. The numeric arguments are first converted to a common type. +This operation can be customized using the special :meth:`__sub__` method. + .. _shifting: @@ -1306,6 +1323,9 @@ The shifting operations have lower priority than the arithmetic operations: These operators accept integers as arguments. They shift the first argument to the left or right by the number of bits given by the second argument. +This operation can be customized using the special :meth:`__lshift__` and +:meth:`__rshift__` methods. + .. index:: exception: ValueError A right shift by *n* bits is defined as floor division by ``pow(2,n)``. A left @@ -1331,7 +1351,8 @@ Each of the three bitwise operations has a different priority level: operator: & (ampersand) The ``&`` operator yields the bitwise AND of its arguments, which must be -integers. +integers or one of them must be a custom object overriding :meth:`__and__` or +:meth:`__rand__` special methods. .. index:: pair: bitwise; xor @@ -1339,7 +1360,8 @@ integers. operator: ^ (caret) The ``^`` operator yields the bitwise XOR (exclusive OR) of its arguments, which -must be integers. +must be integers or one of them must be a custom object overriding :meth:`__xor__` or +:meth:`__rxor__` special methods. .. index:: pair: bitwise; or @@ -1347,7 +1369,8 @@ must be integers. operator: | (vertical bar) The ``|`` operator yields the bitwise (inclusive) OR of its arguments, which -must be integers. +must be integers or one of them must be a custom object overriding :meth:`__or__` or +:meth:`__ror__` special methods. .. _comparisons: @@ -1375,7 +1398,9 @@ in mathematics: comp_operator: "<" | ">" | "==" | ">=" | "<=" | "!=" : | "is" ["not"] | ["not"] "in" -Comparisons yield boolean values: ``True`` or ``False``. +Comparisons yield boolean values: ``True`` or ``False``. Custom +:dfn:`rich comparison methods` may return non-boolean values. In this case +Python will call :func:`bool` on such value in boolean contexts. .. index:: pair: chaining; comparisons @@ -1672,8 +1697,9 @@ Assignment expressions assignment_expression: [`identifier` ":="] `expression` An assignment expression (sometimes also called a "named expression" or -"walrus") assigns an :token:`expression` to an :token:`identifier`, while also -returning the value of the :token:`expression`. +"walrus") assigns an :token:`~python-grammar:expression` to an +:token:`~python-grammar:identifier`, while also returning the value of the +:token:`~python-grammar:expression`. One common use case is when handling matched regular expressions: diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 2ef5b901b930bf..9834f957ea9f64 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -970,6 +970,8 @@ should expose ``XXX.YYY.ZZZ`` as a usable expression, but .moduleY is not a valid expression. +.. _import-dunder-main: + Special considerations for __main__ =================================== diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 4ad8f8be1e7ddf..21ad3731a32467 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -385,10 +385,20 @@ classes are identified by the patterns of leading and trailing underscore characters: ``_*`` - Not imported by ``from module import *``. The special identifier ``_`` is used - in the interactive interpreter to store the result of the last evaluation; it is - stored in the :mod:`builtins` module. When not in interactive mode, ``_`` - has no special meaning and is not defined. See section :ref:`import`. + Not imported by ``from module import *``. + +``_`` + In a ``case`` pattern within a :keyword:`match` statement, ``_`` is a + :ref:`soft keyword ` that denotes a + :ref:`wildcard `. + + Separately, the interactive interpreter makes the result of the last evaluation + available in the variable ``_``. + (It is stored in the :mod:`builtins` module, alongside built-in + functions like ``print``.) + + Elsewhere, ``_`` is a regular identifier. It is often used to name + "special" items, but it is not special to Python itself. .. note:: @@ -396,6 +406,8 @@ characters: refer to the documentation for the :mod:`gettext` module for more information on this convention. + It is also commonly used for unused variables. + ``__*__`` System-defined names, informally known as "dunder" names. These names are defined by the interpreter and its implementation (including the standard library). @@ -457,10 +469,10 @@ String literals are described by the following lexical definitions: bytesescapeseq: "\" One syntactic restriction not indicated by these productions is that whitespace -is not allowed between the :token:`stringprefix` or :token:`bytesprefix` and the -rest of the literal. The source character set is defined by the encoding -declaration; it is UTF-8 if no encoding declaration is given in the source file; -see section :ref:`encodings`. +is not allowed between the :token:`~python-grammar:stringprefix` or +:token:`~python-grammar:bytesprefix` and the rest of the literal. The source +character set is defined by the encoding declaration; it is UTF-8 if no encoding +declaration is given in the source file; see section :ref:`encodings`. .. index:: triple-quoted string, Unicode Consortium, raw string single: """; string literal diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 3aba2700048bc0..bb1209dfc33beb 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -734,7 +734,7 @@ The :keyword:`!import` statement : ("," `identifier` ["as" `identifier`])* : | "from" `relative_module` "import" "(" `identifier` ["as" `identifier`] : ("," `identifier` ["as" `identifier`])* [","] ")" - : | "from" `module` "import" "*" + : | "from" `relative_module` "import" "*" module: (`identifier` ".")* `identifier` relative_module: "."* `module` | "."+ diff --git a/Doc/requirements.txt b/Doc/requirements.txt index 2b70af3a4fc6b9..95d320f4cb1f33 100644 --- a/Doc/requirements.txt +++ b/Doc/requirements.txt @@ -4,9 +4,13 @@ # won't suddenly cause build failures. Updating the version is fine as long # as no warnings are raised by doing so. sphinx==3.2.1 +# Docutils version is pinned to a version compatible with Sphinx +# version 3.2.1. It can be removed after bumping Sphinx version to at +# least 3.5.4. +docutils==0.17.1 blurb # The theme used by the documentation is stored separately, so we need # to install that as well. -python-docs-theme +python-docs-theme>=2022.1 diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index 76c9d920cbe31f..489f06613eb310 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -10,8 +10,10 @@ * stable API annotations - Usage: Set the `refcount_file` config value to the path to the reference + Usage: + * Set the `refcount_file` config value to the path to the reference count data file. + * Set the `stable_abi_file` config value to the path to stable ABI list. :copyright: Copyright 2007-2014 by Georg Brandl. :license: Python license. @@ -20,11 +22,23 @@ from os import path from docutils import nodes from docutils.parsers.rst import directives +from docutils.parsers.rst import Directive +from docutils.statemachine import StringList +import csv from sphinx import addnodes from sphinx.domains.c import CObject +REST_ROLE_MAP = { + 'function': 'func', + 'var': 'data', + 'type': 'type', + 'macro': 'macro', + 'type': 'type', +} + + class RCEntry: def __init__(self, name): self.name = name @@ -33,12 +47,10 @@ def __init__(self, name): self.result_refs = None -class Annotations(dict): - @classmethod - def fromfile(cls, filename): - d = cls() - fp = open(filename, 'r') - try: +class Annotations: + def __init__(self, refcount_filename, stable_abi_file): + self.refcount_data = {} + with open(refcount_filename, 'r') as fp: for line in fp: line = line.strip() if line[:1] in ("", "#"): @@ -50,9 +62,9 @@ def fromfile(cls, filename): function, type, arg, refcount, comment = parts # Get the entry, creating it if needed: try: - entry = d[function] + entry = self.refcount_data[function] except KeyError: - entry = d[function] = RCEntry(function) + entry = self.refcount_data[function] = RCEntry(function) if not refcount or refcount == "null": refcount = None else: @@ -64,27 +76,58 @@ def fromfile(cls, filename): else: entry.result_type = type entry.result_refs = refcount - finally: - fp.close() - return d + + self.stable_abi_data = {} + with open(stable_abi_file, 'r') as fp: + for record in csv.DictReader(fp): + role = record['role'] + name = record['name'] + self.stable_abi_data[name] = record def add_annotations(self, app, doctree): for node in doctree.traverse(addnodes.desc_content): par = node.parent if par['domain'] != 'c': continue - if par['stableabi']: - node.insert(0, nodes.emphasis(' Part of the stable ABI.', - ' Part of the stable ABI.', - classes=['stableabi'])) - if par['objtype'] != 'function': - continue if not par[0].has_key('ids') or not par[0]['ids']: continue name = par[0]['ids'][0] if name.startswith("c."): name = name[2:] - entry = self.get(name) + + objtype = par['objtype'] + + # Stable ABI annotation. These have two forms: + # Part of the [Stable ABI](link). + # Part of the [Stable ABI](link) since version X.Y. + record = self.stable_abi_data.get(name) + if record: + if record['role'] != objtype: + raise ValueError( + f"Object type mismatch in limited API annotation " + f"for {name}: {record['role']!r} != {objtype!r}") + stable_added = record['added'] + message = ' Part of the ' + emph_node = nodes.emphasis(message, message, + classes=['stableabi']) + ref_node = addnodes.pending_xref( + 'Stable ABI', refdomain="std", reftarget='stable', + reftype='ref', refexplicit="False") + ref_node += nodes.Text('Stable ABI') + emph_node += ref_node + if record['ifdef_note']: + emph_node += nodes.Text(' ' + record['ifdef_note']) + if stable_added == '3.2': + # Stable ABI was introduced in 3.2. + emph_node += nodes.Text('.') + else: + emph_node += nodes.Text(f' since version {stable_added}.') + node.insert(0, emph_node) + + # Return value annotation + if objtype != 'function': + continue + entry = self.refcount_data.get(name) if not entry: continue elif not entry.result_type.endswith("Object*"): @@ -99,13 +142,36 @@ def add_annotations(self, app, doctree): def init_annotations(app): - refcounts = Annotations.fromfile( - path.join(app.srcdir, app.config.refcount_file)) - app.connect('doctree-read', refcounts.add_annotations) + annotations = Annotations( + path.join(app.srcdir, app.config.refcount_file), + path.join(app.srcdir, app.config.stable_abi_file), + ) + app.connect('doctree-read', annotations.add_annotations) + + class LimitedAPIList(Directive): + + has_content = False + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = True + + def run(self): + content = [] + for record in annotations.stable_abi_data.values(): + role = REST_ROLE_MAP[record['role']] + name = record['name'] + content.append(f'* :c:{role}:`{name}`') + + pnode = nodes.paragraph() + self.state.nested_parse(StringList(content), 0, pnode) + return [pnode] + + app.add_directive('limited-api-list', LimitedAPIList) def setup(app): app.add_config_value('refcount_file', '', True) + app.add_config_value('stable_abi_file', '', True) app.connect('builder-inited', init_annotations) # monkey-patch C object... diff --git a/Doc/tools/extensions/peg_highlight.py b/Doc/tools/extensions/peg_highlight.py index 42101be10ea9b6..27f54cdf593c87 100644 --- a/Doc/tools/extensions/peg_highlight.py +++ b/Doc/tools/extensions/peg_highlight.py @@ -56,8 +56,8 @@ class PEGLexer(RegexLexer): (_name + _text_ws + r"(\[[\w\d_\*]+?\])" + _text_ws + "(=)", bygroups(None, None, None, None, None),), ], "invalids": [ - (r"^(\s+\|\s+invalid_\w+\s*\n)", bygroups(None)), - (r"^(\s+\|\s+incorrect_\w+\s*\n)", bygroups(None)), + (r"^(\s+\|\s+.*invalid_\w+.*\n)", bygroups(None)), + (r"^(\s+\|\s+.*incorrect_\w+.*\n)", bygroups(None)), (r"^(#.*invalid syntax.*(?:.|\n)*)", bygroups(None),), ], "root": [ diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index bcd9d26b36846f..92fc5e7c71cd7d 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -44,7 +44,7 @@ ISSUE_URI = 'https://bugs.python.org/issue%s' -SOURCE_URI = 'https://github.com/python/cpython/tree/master/%s' +SOURCE_URI = 'https://github.com/python/cpython/tree/3.10/%s' # monkey-patch reST parser to disable alphabetic and roman enumerated lists from docutils.parsers.rst.states import Body diff --git a/Doc/tools/rstlint.py b/Doc/tools/rstlint.py index cbcb8eb801b135..3092a3b2d81b78 100755 --- a/Doc/tools/rstlint.py +++ b/Doc/tools/rstlint.py @@ -165,7 +165,7 @@ def hide_comments(lines): """Tool to remove comments from given lines. It yields empty lines in place of comments, so line numbers are - still meaningfull. + still meaningful. """ in_multiline_comment = False for line in lines: diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index d56a2b9fd0bfb9..2453faa8ccd746 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -110,6 +110,7 @@ howto/pyporting,,::,Programming Language :: Python :: 3 howto/regex,,::, howto/regex,,:foo,(?:foo) howto/urllib2,,:password,"""joe:password@example.com""" +library/__main__,,`, library/ast,,:upper,lower:upper library/ast,,:step,lower:upper:step library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)]," @@ -209,8 +210,7 @@ library/smtplib,,:port,method must support that as well as a regular host:port library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" library/socket,,:len,fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) -library/sqlite3,,:name,"cur.execute(""select * from lang where lang_name=:name and lang_age=:age""," -library/sqlite3,,:age,"cur.execute(""select * from lang where lang_name=:name and lang_age=:age""," +library/sqlite3,,:year,"cur.execute(""select * from lang where first_appeared=:year"", {""year"": 1972})" library/sqlite3,,:memory, library/sqlite3,,:path,"db = sqlite3.connect('file:path/to/database?mode=ro', uri=True)" library/ssl,,:My,"Organizational Unit Name (eg, section) []:My Group" @@ -234,6 +234,12 @@ library/tarfile,,:xz,'r:xz' library/tarfile,,:xz,'w:xz' library/time,,:mm, library/time,,:ss, +library/tkinter,,::,ttk::frame .frm -padding 10 +library/tkinter,,::,"grid [ttk::label .frm.lbl -text ""Hello World!""] -column 0 -row 0" +library/tkinter,,::,"grid [ttk::button .frm.btn -text ""Quit"" -command ""destroy .""] -column 1 -row 0" +library/tkinter,,::,ttk::frame +library/tkinter,,::,ttk::button +library/tkinter,,::,ttk::widget library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):" library/turtle,,::,Example:: library/unittest,,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message'," @@ -265,6 +271,7 @@ license,,:zooko,mailto:zooko@zooko.com reference/expressions,,:index,x[index:index] reference/lexical_analysis,,`,$ ? ` reference/lexical_analysis,,:fileencoding,# vim:fileencoding= +reference/datamodel,,`, """Return the result of the expression `obj[x]`""" tutorial/datastructures,,:value,It is also possible to delete a key:value tutorial/datastructures,,:value,key:value pairs within the braces adds initial key:value pairs tutorial/stdlib2,,:config,"logging.warning('Warning:config file %s not found', 'server.conf')" @@ -370,7 +377,7 @@ library/importlib.metadata,,:main,"EntryPoint(name='wheel', value='wheel.cli:mai library/importlib.metadata,,`,loading the metadata for packages for the indicated ``context``. library/re,,`,"`" using/configure,84,:db2,=db1:db2:... -library/typing,1004,`,# Type of ``val`` is narrowed to ``str`` -library/typing,1004,`,"# Else, type of ``val`` is narrowed to ``float``." -library/typing,1004,`,# Type of ``val`` is narrowed to ``List[str]``. -library/typing,1004,`,# Type of ``val`` remains as ``List[object]``. +library/typing,,`,# Type of ``val`` is narrowed to ``str`` +library/typing,,`,"# Else, type of ``val`` is narrowed to ``float``." +library/typing,,`,# Type of ``val`` is narrowed to ``List[str]``. +library/typing,,`,# Type of ``val`` remains as ``List[object]``. diff --git a/Doc/tools/templates/customsourcelink.html b/Doc/tools/templates/customsourcelink.html index fca44e9163cac7..21af621efce95b 100644 --- a/Doc/tools/templates/customsourcelink.html +++ b/Doc/tools/templates/customsourcelink.html @@ -4,7 +4,7 @@

{{ _('This Page') }}

  • {% trans %}Report a Bug{% endtrans %}
  • - {{ _('Show Source') }}
  • diff --git a/Doc/tools/templates/indexcontent.html b/Doc/tools/templates/indexcontent.html index 152162ab0dd28c..a96746b69fd41b 100644 --- a/Doc/tools/templates/indexcontent.html +++ b/Doc/tools/templates/indexcontent.html @@ -5,7 +5,7 @@ {% block body %}

    {{ docstitle|e }}

    - {% trans %}Welcome! This is the documentation for Python {{ release }}.{% endtrans %} + {% trans %}Welcome! This is the official documentation for Python {{ release }}.{% endtrans %}

    {% trans %}Parts of the documentation:{% endtrans %}

    diff --git a/Doc/tutorial/appetite.rst b/Doc/tutorial/appetite.rst index 26e5168ab51a7a..3fa68097ee3665 100644 --- a/Doc/tutorial/appetite.rst +++ b/Doc/tutorial/appetite.rst @@ -23,7 +23,7 @@ You could write a Unix shell script or Windows batch files for some of these tasks, but shell scripts are best at moving around files and changing text data, not well-suited for GUI applications or games. You could write a C/C++/Java program, but it can take a lot of development time to get even a first-draft -program. Python is simpler to use, available on Windows, Mac OS X, and Unix +program. Python is simpler to use, available on Windows, macOS, and Unix operating systems, and will help you get the job done more quickly. Python is simple to use, but it is a real programming language, offering much diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 0d780e3ba89643..f44cb0b4e905a9 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -797,7 +797,7 @@ using the :func:`next` built-in function; this example shows how it all works:: >>> s = 'abc' >>> it = iter(s) >>> it - + >>> next(it) 'a' >>> next(it) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 0b09c18170dd84..fad8746014646c 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -110,14 +110,14 @@ The given end point is never part of the generated sequence; ``range(10)`` gener is possible to let the range start at another number, or to specify a different increment (even negative; sometimes this is called the 'step'):: - range(5, 10) - 5, 6, 7, 8, 9 + >>> list(range(5, 10)) + [5, 6, 7, 8, 9] - range(0, 10, 3) - 0, 3, 6, 9 + >>> list(range(0, 10, 3)) + [0, 3, 6, 9] - range(-10, -100, -30) - -10, -40, -70 + >>> list(range(-10, -100, -30)) + [-10, -40, -70] To iterate over the indices of a sequence, you can combine :func:`range` and :func:`len` as follows:: @@ -137,7 +137,7 @@ function, see :ref:`tut-loopidioms`. A strange thing happens if you just print a range:: - >>> print(range(10)) + >>> range(10) range(0, 10) In many ways the object returned by :func:`range` behaves as if it is a list, @@ -155,13 +155,7 @@ that takes an iterable is :func:`sum`:: 6 Later we will see more functions that return iterables and take iterables as -arguments. Lastly, maybe you are curious about how to get a list from a range. -Here is the solution:: - - >>> list(range(4)) - [0, 1, 2, 3] - -In chapter :ref:`tut-structures`, we will discuss in more detail about +arguments. In chapter :ref:`tut-structures`, we will discuss in more detail about :func:`list`. .. _tut-break: @@ -214,6 +208,7 @@ iteration of the loop:: ... print("Found an even number", num) ... continue ... print("Found an odd number", num) + ... Found an even number 2 Found an odd number 3 Found an even number 4 @@ -272,7 +267,7 @@ The simplest form compares a subject value against one or more literals:: case 418: return "I'm a teapot" case _: - return "Something's wrong with the Internet" + return "Something's wrong with the internet" Note the last block: the "variable name" ``_`` acts as a *wildcard* and never fails to match. If no case matches, none of the branches is executed. @@ -383,7 +378,7 @@ Several other key features of this statement: - Mapping patterns: ``{"bandwidth": b, "latency": l}`` captures the ``"bandwidth"`` and ``"latency"`` values from a dictionary. Unlike sequence patterns, extra keys are ignored. An unpacking like ``**rest`` is also - supported. (But ``**_`` would be redundant, so it not allowed.) + supported. (But ``**_`` would be redundant, so it is not allowed.) - Subpatterns may be captured using the ``as`` keyword:: @@ -400,9 +395,11 @@ Several other key features of this statement: from enum import Enum class Color(Enum): - RED = 0 - GREEN = 1 - BLUE = 2 + RED = 'red' + GREEN = 'green' + BLUE = 'blue' + + color = Color(input("Enter your choice of 'red', 'blue' or 'green': ")) match color: case Color.RED: @@ -656,7 +653,7 @@ Here's an example that fails due to this restriction:: >>> function(0, a=0) Traceback (most recent call last): File "", line 1, in - TypeError: function() got multiple values for keyword argument 'a' + TypeError: function() got multiple values for argument 'a' When a final formal parameter of the form ``**name`` is present, it receives a dictionary (see :ref:`typesmapping`) containing all keyword arguments except for @@ -792,7 +789,7 @@ parameters as there is a ``/`` in the function definition:: >>> pos_only_arg(arg=1) Traceback (most recent call last): File "", line 1, in - TypeError: pos_only_arg() got an unexpected keyword argument 'arg' + TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg' The third function ``kwd_only_args`` only allows keyword arguments as indicated by a ``*`` in the function definition:: @@ -822,7 +819,7 @@ definition:: >>> combined_example(pos_only=1, standard=2, kwd_only=3) Traceback (most recent call last): File "", line 1, in - TypeError: combined_example() got an unexpected keyword argument 'pos_only' + TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only' Finally, consider this function definition which has a potential collision between the positional argument ``name`` and ``**kwds`` which has ``name`` as a key:: diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index e42b380db3d23c..927a6722ca2514 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -659,10 +659,12 @@ More on Conditions The conditions used in ``while`` and ``if`` statements can contain any operators, not just comparisons. -The comparison operators ``in`` and ``not in`` check whether a value occurs -(does not occur) in a sequence. The operators ``is`` and ``is not`` compare -whether two objects are really the same object. All comparison operators have -the same priority, which is lower than that of all numerical operators. + +The comparison operators ``in`` and ``not in`` are membership tests that +determine whether a value is in (or not in) a container. The operators ``is`` +and ``is not`` compare whether two objects are really the same object. All +comparison operators have the same priority, which is lower than that of all +numerical operators. Comparisons can be chained. For example, ``a < b == c`` tests whether ``a`` is less than ``b`` and moreover ``b`` equals ``c``. diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst index 25bb4fc567b95b..3f09db21040680 100644 --- a/Doc/tutorial/errors.rst +++ b/Doc/tutorial/errors.rst @@ -53,7 +53,7 @@ programs, however, and result in error messages as shown here:: >>> '2' + 2 Traceback (most recent call last): File "", line 1, in - TypeError: Can't convert 'int' object to str implicitly + TypeError: can only concatenate str (not "int") to str The last line of the error message indicates what happened. Exceptions come in different types, and the type is printed as part of the message: the types in @@ -147,10 +147,10 @@ For example, the following code will print B, C, D in that order:: Note that if the *except clauses* were reversed (with ``except B`` first), it would have printed B, B, B --- the first matching *except clause* is triggered. -The last *except clause* may omit the exception name(s), to serve as a wildcard. -Use this with extreme caution, since it is easy to mask a real programming error -in this way! It can also be used to print an error message and then re-raise -the exception (allowing a caller to handle the exception as well):: +All exceptions inherit from :exc:`BaseException`, and so it can be used to serve +as a wildcard. Use this with extreme caution, since it is easy to mask a real +programming error in this way! It can also be used to print an error message and +then re-raise the exception (allowing a caller to handle the exception as well):: import sys @@ -162,10 +162,13 @@ the exception (allowing a caller to handle the exception as well):: print("OS error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") - except: - print("Unexpected error:", sys.exc_info()[0]) + except BaseException as err: + print(f"Unexpected {err=}, {type(err)=}") raise +Alternatively the last except clause may omit the exception name(s), however the exception +value must then be retrieved from ``sys.exc_info()[1]``. + The :keyword:`try` ... :keyword:`except` statement has an optional *else clause*, which, when present, must follow all *except clauses*. It is useful for code that must be executed if the *try clause* does not raise an exception. @@ -305,7 +308,7 @@ disabled by using ``from None`` idiom: >>> try: ... open('database.sqlite') - ... except IOError: + ... except OSError: ... raise RuntimeError from None ... Traceback (most recent call last): @@ -326,41 +329,7 @@ be derived from the :exc:`Exception` class, either directly or indirectly. Exception classes can be defined which do anything any other class can do, but are usually kept simple, often only offering a number of attributes that allow -information about the error to be extracted by handlers for the exception. When -creating a module that can raise several distinct errors, a common practice is -to create a base class for exceptions defined by that module, and subclass that -to create specific exception classes for different error conditions:: - - class Error(Exception): - """Base class for exceptions in this module.""" - pass - - class InputError(Error): - """Exception raised for errors in the input. - - Attributes: - expression -- input expression in which the error occurred - message -- explanation of the error - """ - - def __init__(self, expression, message): - self.expression = expression - self.message = message - - class TransitionError(Error): - """Raised when an operation attempts a state transition that's not - allowed. - - Attributes: - previous -- state at beginning of transition - next -- attempted new state - message -- explanation of why the specific transition is not allowed - """ - - def __init__(self, previous, next, message): - self.previous = previous - self.next = next - self.message = message +information about the error to be extracted by handlers for the exception. Most exceptions are defined with names that end in "Error", similar to the naming of the standard exceptions. @@ -405,6 +374,10 @@ points discuss more complex cases when an exception occurs: or :keyword:`!else` clause. Again, the exception is re-raised after the :keyword:`!finally` clause has been executed. +* If the :keyword:`!finally` clause executes a :keyword:`break`, + :keyword:`continue` or :keyword:`return` statement, exceptions are not + re-raised. + * If the :keyword:`!try` statement reaches a :keyword:`break`, :keyword:`continue` or :keyword:`return` statement, the :keyword:`!finally` clause will execute just prior to the @@ -489,5 +462,3 @@ used in a way that ensures they are always cleaned up promptly and correctly. :: After the statement is executed, the file *f* is always closed, even if a problem was encountered while processing the lines. Objects which, like files, provide predefined clean-up actions will indicate this in their documentation. - - diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index b98de6e56a0031..7212b40be83772 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -133,7 +133,7 @@ with inexact values become comparable to one another:: Binary floating-point arithmetic holds many surprises like this. The problem with "0.1" is explained in precise detail below, in the "Representation Error" -section. See `The Perils of Floating Point `_ +section. See `The Perils of Floating Point `_ for a more complete account of other common surprises. As that says near the end, "there are no easy answers." Still, don't be unduly diff --git a/Doc/tutorial/index.rst b/Doc/tutorial/index.rst index 8ee011e2827e79..96791f88c867ab 100644 --- a/Doc/tutorial/index.rst +++ b/Doc/tutorial/index.rst @@ -11,7 +11,7 @@ together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms. The Python interpreter and the extensive standard library are freely available -in source or binary form for all major platforms from the Python Web site, +in source or binary form for all major platforms from the Python web site, https://www.python.org/, and may be freely distributed. The same site also contains distributions of and pointers to many free third party Python modules, programs and tools, and additional documentation. diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 4e27cff83ce59f..7f83c4d4612eb3 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -480,7 +480,8 @@ If you have an object ``x``, you can view its JSON string representation with a simple line of code:: >>> import json - >>> json.dumps([1, 'simple', 'list']) + >>> x = [1, 'simple', 'list'] + >>> json.dumps(x) '[1, "simple", "list"]' Another variant of the :func:`~json.dumps` function, called :func:`~json.dump`, diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index 2a1666128a2015..33678f5a64b1f3 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -11,6 +11,13 @@ with a prompt are output from the interpreter. Note that a secondary prompt on a line by itself in an example means you must type a blank line; this is used to end a multi-line command. +.. only:: html + + You can toggle the display of prompts and output by clicking on ``>>>`` + in the upper-right corner of an example box. If you hide the prompts + and output for an example, then you can easily copy and paste the input + lines into your interpreter. + .. index:: single: # (hash); comment Many of the examples in this manual, even those entered at the interactive @@ -73,7 +80,7 @@ operator; to calculate the remainder you can use ``%``:: 5 >>> 17 % 3 # the % operator returns the remainder of the division 2 - >>> 5 * 3 + 2 # result * divisor + remainder + >>> 5 * 3 + 2 # floored quotient * divisor + remainder 17 With Python, it is possible to use the ``**`` operator to calculate powers [#]_:: @@ -269,14 +276,6 @@ to obtain individual characters, *slicing* allows you to obtain substring:: >>> word[2:5] # characters from position 2 (included) to 5 (excluded) 'tho' -Note how the start is always included, and the end always excluded. This -makes sure that ``s[:i] + s[i:]`` is always equal to ``s``:: - - >>> word[:2] + word[2:] - 'Python' - >>> word[:4] + word[4:] - 'Python' - Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced. :: @@ -287,6 +286,14 @@ omitted second index defaults to the size of the string being sliced. :: >>> word[-2:] # characters from the second-last (included) to the end 'on' +Note how the start is always included, and the end always excluded. This +makes sure that ``s[:i] + s[i:]`` is always equal to ``s``:: + + >>> word[:2] + word[2:] + 'Python' + >>> word[:4] + word[4:] + 'Python' + One way to remember how slices work is to think of the indices as pointing *between* characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of *n* characters has diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index af595e5ca04d7e..f1d4957e37eb11 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -191,7 +191,8 @@ named :file:`spam.py` in a list of directories given by the variable file is specified). * :envvar:`PYTHONPATH` (a list of directory names, with the same syntax as the shell variable :envvar:`PATH`). -* The installation-dependent default. +* The installation-dependent default (by convention including a + ``site-packages`` directory, handled by the :mod:`site` module). .. note:: On file systems which support symlinks, the directory containing the input @@ -533,6 +534,8 @@ importing module needs to use submodules with the same name from different packages. +.. _intra-package-references: + Intra-package References ------------------------ diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index f33265cd2b0eb4..ac16160b234394 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -178,13 +178,13 @@ protocols. Two of the simplest are :mod:`urllib.request` for retrieving data from URLs and :mod:`smtplib` for sending mail:: >>> from urllib.request import urlopen - >>> with urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') as response: + >>> with urlopen('http://worldtimeapi.org/api/timezone/etc/UTC.txt') as response: ... for line in response: - ... line = line.decode('utf-8') # Decoding the binary data to text. - ... if 'EST' in line or 'EDT' in line: # look for Eastern Time - ... print(line) - -
    Nov. 25, 09:43:32 PM EST + ... line = line.decode() # Convert bytes to a str + ... if line.startswith('datetime'): + ... print(line.rstrip()) # Remove trailing newline + ... + datetime: 2022-01-01T01:36:47.689215+00:00 >>> import smtplib >>> server = smtplib.SMTP('localhost') diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 3208201312b871..18805da90e5001 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -30,8 +30,8 @@ the set are: More Python resources: -* https://www.python.org: The major Python Web site. It contains code, - documentation, and pointers to Python-related pages around the Web. This Web +* https://www.python.org: The major Python web site. It contains code, + documentation, and pointers to Python-related pages around the web. This web site is mirrored in various places around the world, such as Europe, Japan, and Australia; a mirror may be faster than the main site, depending on your geographical location. diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 25e05d413de877..c4f65eb6194fb5 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -322,7 +322,7 @@ Miscellaneous options Hash randomization is intended to provide protection against a denial-of-service caused by carefully-chosen inputs that exploit the worst - case performance of a dict construction, O(n^2) complexity. See + case performance of a dict construction, O(n\ :sup:`2`) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details. :envvar:`PYTHONHASHSEED` allows you to set a fixed value for the hash @@ -638,7 +638,7 @@ conflict. .. envvar:: PYTHONCASEOK If this is set, Python ignores case in :keyword:`import` statements. This - only works on Windows and OS X. + only works on Windows and macOS. .. envvar:: PYTHONDONTWRITEBYTECODE @@ -721,7 +721,7 @@ conflict. If this environment variable is set, ``sys.argv[0]`` will be set to its value instead of the value got through the C runtime. Only works on - Mac OS X. + macOS. .. envvar:: PYTHONWARNINGS @@ -942,10 +942,12 @@ Debug-mode variables .. envvar:: PYTHONTHREADDEBUG - If set, Python will print threading debug info. + If set, Python will print threading debug info into stdout. Need a :ref:`debug build of Python `. + .. deprecated-removed:: 3.10 3.12 + .. envvar:: PYTHONDUMPREFS diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index c37540c7e031d6..14ffdd760f0120 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -175,8 +175,8 @@ recommended for best performance. Enable Link Time Optimization (LTO) in any build (disabled by default). - The C compiler Clang requires ``llvm-ar`` for LTO, as well as an LTO-aware - linker (``ld.gold`` or ``lld``). + The C compiler Clang requires ``llvm-ar`` for LTO (``ar`` on macOS), as well + as an LTO-aware linker (``ld.gold`` or ``lld``). .. versionadded:: 3.6 @@ -550,7 +550,7 @@ Built-in modules have no ``__file__`` attribute:: File "", line 1, in AttributeError: module 'sys' has no attribute '__file__' -Other C extensins are built as dynamic libraires, like the ``_asyncio`` module. +Other C extensins are built as dynamic libraries, like the ``_asyncio`` module. They are built with the ``Py_BUILD_CORE_MODULE`` macro defined. Example on Linux x86-64:: diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index ead71e1b079b3b..2f132a96bef082 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -1,14 +1,14 @@ .. _using-on-mac: -*************************** -Using Python on a Macintosh -*************************** +********************* +Using Python on a Mac +********************* :Author: Bob Savage -Python on a Macintosh running Mac OS X is in principle very similar to Python on +Python on a Mac running macOS is in principle very similar to Python on any other Unix platform, but there are a number of additional features such as the IDE and the Package Manager that are worth pointing out. @@ -17,7 +17,7 @@ the IDE and the Package Manager that are worth pointing out. Getting and Installing MacPython ================================ -Mac OS X 10.8 comes with Python 2.7 pre-installed by Apple. If you wish, you +macOS since version 10.8 comes with Python 2.7 pre-installed by Apple. If you wish, you are invited to install the most recent version of Python 3 from the Python website (https://www.python.org). A current "universal binary" build of Python, which runs natively on the Mac's new Intel and legacy PPC CPU's, is available @@ -54,12 +54,12 @@ section on running Python scripts from the Unix shell. How to run a Python script -------------------------- -Your best way to get started with Python on Mac OS X is through the IDLE +Your best way to get started with Python on macOS is through the IDLE integrated development environment, see section :ref:`ide` and use the Help menu when the IDE is running. If you want to run Python scripts from the Terminal window command line or from -the Finder you first need an editor to create your script. Mac OS X comes with a +the Finder you first need an editor to create your script. macOS comes with a number of standard Unix command line editors, :program:`vim` and :program:`emacs` among them. If you want a more Mac-like editor, :program:`BBEdit` or :program:`TextWrangler` from Bare Bones Software (see @@ -87,7 +87,7 @@ To run your script from the Finder you have two options: Running scripts with a GUI -------------------------- -With older versions of Python, there is one Mac OS X quirk that you need to be +With older versions of Python, there is one macOS quirk that you need to be aware of: programs that talk to the Aqua window manager (in other words, anything that has a GUI) need to be run in a special way. Use :program:`pythonw` instead of :program:`python` to start such scripts. @@ -98,7 +98,7 @@ With Python 3.9, you can use either :program:`python` or :program:`pythonw`. Configuration ------------- -Python on OS X honors all standard Unix environment variables such as +Python on macOS honors all standard Unix environment variables such as :envvar:`PYTHONPATH`, but setting these variables for programs started from the Finder is non-standard as the Finder does not read your :file:`.profile` or :file:`.cshrc` at startup. You need to create a file @@ -148,10 +148,10 @@ X by Apple, and the latest version can be downloaded and installed from https://www.activestate.com; it can also be built from source. *wxPython* is another popular cross-platform GUI toolkit that runs natively on -Mac OS X. Packages and documentation are available from https://www.wxpython.org. +macOS. Packages and documentation are available from https://www.wxpython.org. -*PyQt* is another popular cross-platform GUI toolkit that runs natively on Mac -OS X. More information can be found at +*PyQt* is another popular cross-platform GUI toolkit that runs natively on +macOS. More information can be found at https://riverbankcomputing.com/software/pyqt/intro. diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index 1d1fa8bd85d7ed..0a1834453a0ee8 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -162,6 +162,7 @@ Custom OpenSSL $ pushd openssl-VERSION $ ./config \ --prefix=/usr/local/custom-openssl \ + --libdir=lib \ --openssldir=/etc/ssl $ make -j1 depend $ make -j8 diff --git a/Doc/whatsnew/2.0.rst b/Doc/whatsnew/2.0.rst index ace396b9d846ab..0e1cf1fd0ce46c 100644 --- a/Doc/whatsnew/2.0.rst +++ b/Doc/whatsnew/2.0.rst @@ -108,7 +108,7 @@ usually easy compared to the earlier task of coming up with a good design. Discussions of new features can often explode into lengthy mailing list threads, making the discussion hard to follow, and no one can read every posting to python-dev. Therefore, a relatively formal process has been set up to write -Python Enhancement Proposals (PEPs), modelled on the Internet RFC process. PEPs +Python Enhancement Proposals (PEPs), modelled on the internet RFC process. PEPs are draft documents that describe a proposed new feature, and are continually revised until the community reaches a consensus, either accepting or rejecting the proposal. Quoting from the introduction to :pep:`1`, "PEP Purpose and @@ -768,7 +768,7 @@ Vladimir Marangozov's long-awaited malloc restructuring was completed, to make it easy to have the Python interpreter use a custom allocator instead of C's standard :func:`malloc`. For documentation, read the comments in :file:`Include/pymem.h` and :file:`Include/objimpl.h`. For the lengthy -discussions during which the interface was hammered out, see the Web archives of +discussions during which the interface was hammered out, see the web archives of the 'patches' and 'python-dev' lists at python.org. Recent versions of the GUSI development environment for MacOS support POSIX @@ -791,7 +791,7 @@ Previously the Python virtual machine used 16-bit numbers in its bytecode, limiting the size of source files. In particular, this affected the maximum size of literal lists and dictionaries in Python source; occasionally people who are generating Python code would run into this limit. A patch by Charles G. -Waldman raises the limit from ``2^16`` to ``2^{32}``. +Waldman raises the limit from ``2**16`` to ``2**32``. Three new convenience functions intended for adding constants to a module's dictionary at module initialization time were added: :func:`PyModule_AddObject`, @@ -1002,7 +1002,7 @@ Relationship to PyXML --------------------- The XML Special Interest Group has been working on XML-related Python code for a -while. Its code distribution, called PyXML, is available from the SIG's Web +while. Its code distribution, called PyXML, is available from the SIG's web pages at https://www.python.org/community/sigs/current/xml-sig. The PyXML distribution also used the package name ``xml``. If you've written programs that used PyXML, you're probably wondering about its compatibility with the 2.0 :mod:`xml` package. @@ -1109,7 +1109,7 @@ module. Prescod.) * :mod:`robotparser`: Parse a :file:`robots.txt` file, which is used for writing - Web spiders that politely avoid certain areas of a Web site. The parser accepts + web spiders that politely avoid certain areas of a web site. The parser accepts the contents of a :file:`robots.txt` file, builds a set of rules from it, and can then answer questions about the fetchability of a given URL. (Contributed by Skip Montanaro.) diff --git a/Doc/whatsnew/2.1.rst b/Doc/whatsnew/2.1.rst index 8b1eac968e2bc0..b690f90cf6636b 100644 --- a/Doc/whatsnew/2.1.rst +++ b/Doc/whatsnew/2.1.rst @@ -425,7 +425,7 @@ PEP 232: Function Attributes In Python 2.1, functions can now have arbitrary information attached to them. People were often using docstrings to hold information about functions and methods, because the ``__doc__`` attribute was the only way of attaching any -information to a function. For example, in the Zope Web application server, +information to a function. For example, in the Zope web application server, functions are marked as safe for public access by having a docstring, and in John Aycock's SPARK parsing framework, docstrings hold parts of the BNF grammar to be parsed. This overloading is unfortunate, since docstrings are really diff --git a/Doc/whatsnew/2.2.rst b/Doc/whatsnew/2.2.rst index b4cd4341f4be43..9355c1badaa215 100644 --- a/Doc/whatsnew/2.2.rst +++ b/Doc/whatsnew/2.2.rst @@ -49,7 +49,7 @@ amazing new capabilities. Before beginning this, the longest and most complicated section of this article, I'll provide an overview of the changes and offer some comments. -A long time ago I wrote a Web page listing flaws in Python's design. One of the +A long time ago I wrote a web page listing flaws in Python's design. One of the most significant flaws was that it's impossible to subclass Python types implemented in C. In particular, it's not possible to subclass built-in types, so you can't just subclass, say, lists in order to add a single useful method to diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index dac0e63649288a..cf5552064cf4a6 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -1650,7 +1650,7 @@ complete list of changes, or look through the CVS logs for all the details. * The new :mod:`DocXMLRPCServer` module allows writing self-documenting XML-RPC servers. Run it in demo mode (as a program) to see it in action. Pointing the - Web browser to the RPC server produces pydoc-style documentation; pointing + web browser to the RPC server produces pydoc-style documentation; pointing xmlrpclib to the server allows invoking the actual methods. (Contributed by Brian Quinlan.) diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index d19c8e01ad8a00..abb65222ddd3d0 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -953,12 +953,12 @@ Several performance enhancements have been added: considered and traversed by the collector. (Contributed by Antoine Pitrou; :issue:`4688`.) -* Long integers are now stored internally either in base 2**15 or in base - 2**30, the base being determined at build time. Previously, they - were always stored in base 2**15. Using base 2**30 gives +* Long integers are now stored internally either in base ``2**15`` or in base + ``2**30``, the base being determined at build time. Previously, they + were always stored in base ``2**15``. Using base ``2**30`` gives significant performance improvements on 64-bit machines, but benchmark results on 32-bit machines have been mixed. Therefore, - the default is to use base 2**30 on 64-bit machines and base 2**15 + the default is to use base ``2**30`` on 64-bit machines and base ``2**15`` on 32-bit machines; on Unix, there's a new configure option :option:`!--enable-big-digits` that can be used to override this default. diff --git a/Doc/whatsnew/3.1.rst b/Doc/whatsnew/3.1.rst index 919fbeeb2ad857..f1e6d0c4f3dd68 100644 --- a/Doc/whatsnew/3.1.rst +++ b/Doc/whatsnew/3.1.rst @@ -474,12 +474,12 @@ Build and C API Changes Changes to Python's build process and to the C API include: -* Integers are now stored internally either in base 2**15 or in base - 2**30, the base being determined at build time. Previously, they - were always stored in base 2**15. Using base 2**30 gives +* Integers are now stored internally either in base ``2**15`` or in base + ``2**30``, the base being determined at build time. Previously, they + were always stored in base ``2**15``. Using base ``2**30`` gives significant performance improvements on 64-bit machines, but benchmark results on 32-bit machines have been mixed. Therefore, - the default is to use base 2**30 on 64-bit machines and base 2**15 + the default is to use base ``2**30`` on 64-bit machines and base ``2**15`` on 32-bit machines; on Unix, there's a new configure option ``--enable-big-digits`` that can be used to override this default. diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index eb452b07f55f61..c07523c49163bf 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -4,6 +4,7 @@ :Release: |release| :Date: |today| +:Editor: Pablo Galindo Salgado .. Rules for maintenance: @@ -42,20 +43,13 @@ module. (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the Mercurial log + This saves the maintainer the effort of going through the git log when researching a change. This article explains the new features in Python 3.10, compared to 3.9. For full details, see the :ref:`changelog `. -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.10 moves towards release, - so it's worth checking back even after reading earlier versions. - - Summary -- Release highlights ============================= @@ -65,7 +59,34 @@ Summary -- Release highlights .. PEP-sized items next. -* :pep:`644`, require OpenSSL 1.1.1 or newer +New syntax features: + +* :pep:`634`, Structural Pattern Matching: Specification +* :pep:`635`, Structural Pattern Matching: Motivation and Rationale +* :pep:`636`, Structural Pattern Matching: Tutorial +* :issue:`12782`, Parenthesized context managers are now officially allowed. + +New features in the standard library: + +* :pep:`618`, Add Optional Length-Checking To zip. + +Interpreter improvements: + +* :pep:`626`, Precise line numbers for debugging and other tools. + +New typing features: + +* :pep:`604`, Allow writing union types as X | Y +* :pep:`613`, Explicit Type Aliases +* :pep:`612`, Parameter Specification Variables + +Important deprecations, removals or restrictions: + +* :pep:`644`, Require OpenSSL 1.1.1 or newer +* :pep:`632`, Deprecate distutils module. +* :pep:`623`, Deprecate and prepare for the removal of the wstr member in PyUnicodeObject. +* :pep:`624`, Remove Py_UNICODE encoder APIs +* :pep:`597`, Add optional EncodingWarning New Features @@ -143,7 +164,7 @@ For instance, consider the following code (notice the unclosed '{'): 38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6, some_other_code = foo() -previous versions of the interpreter reported confusing places as the location of +Previous versions of the interpreter reported confusing places as the location of the syntax error: .. code-block:: python @@ -153,7 +174,7 @@ the syntax error: ^ SyntaxError: invalid syntax -but in Python3.10 a more informative error is emitted: +but in Python 3.10 a more informative error is emitted: .. code-block:: python @@ -171,8 +192,8 @@ These improvements are inspired by previous work in the PyPy interpreter. (Contributed by Pablo Galindo in :issue:`42864` and Batuhan Taskaya in :issue:`40176`.) -:exc:`SyntaxError` exceptions raised by the intepreter will now highlight the -full error range of the expression that consistutes the syntax error itself, +:exc:`SyntaxError` exceptions raised by the interpreter will now highlight the +full error range of the expression that constitutes the syntax error itself, instead of just where the problem is detected. In this way, instead of displaying (before Python 3.10): @@ -194,10 +215,10 @@ now Python 3.10 will display the exception as: ^^^^^^^^^^^^^^^^^^^^ SyntaxError: Generator expression must be parenthesized -This improvement has been contributed by Pablo Galindo in :issue:`43914`. +This improvement was contributed by Pablo Galindo in :issue:`43914`. A considerable amount of new specialized messages for :exc:`SyntaxError` exceptions -have been incorporated. Some of the most notable ones: +have been incorporated. Some of the most notable ones are as follows: * Missing ``:`` before blocks: @@ -215,9 +236,9 @@ have been incorporated. Some of the most notable ones: .. code-block:: python - >>> {x,y for x,y in range(100)} + >>> {x,y for x,y in zip('abcd', '1234')} File "", line 1 - {x,y for x,y in range(100)} + {x,y for x,y in zip('abcd', '1234')} ^ SyntaxError: did you forget parentheses around the comprehension target? @@ -238,7 +259,7 @@ have been incorporated. Some of the most notable ones: (Contributed by Pablo Galindo in :issue:`43822`) -* Exception groups without parentheses: +* Multiple Exception types without parentheses: .. code-block:: python @@ -248,7 +269,7 @@ have been incorporated. Some of the most notable ones: File "", line 3 except NotEnoughScienceError, NotEnoughResourcesError: ^ - SyntaxError: exception group must be parenthesized + SyntaxError: multiple exception types must be parenthesized (Contributed by Pablo Galindo in :issue:`43149`) @@ -274,6 +295,20 @@ have been incorporated. Some of the most notable ones: (Contributed by Pablo Galindo in :issue:`43823`) +* ``try`` blocks without ``except`` or ``finally`` blocks: + + .. code-block:: python + + >>> try: + ... x = 2 + ... something = 3 + File "", line 3 + something = 3 + ^^^^^^^^^ + SyntaxError: expected 'except' or 'finally' block + + (Contributed by Pablo Galindo in :issue:`44305`) + * Usage of ``=`` instead of ``==`` in comparisons: .. code-block:: python @@ -331,6 +366,11 @@ raised from: (Contributed by Pablo Galindo in :issue:`38530`.) + .. warning:: + Notice this won't work if :c:func:`PyErr_Display` is not called to display the error + which can happen if some other custom error display function is used. This is a common + scenario in some REPLs like IPython. + NameErrors ~~~~~~~~~~ @@ -348,6 +388,12 @@ was raised from: (Contributed by Pablo Galindo in :issue:`38530`.) + .. warning:: + Notice this won't work if :c:func:`PyErr_Display` is not called to display the error, + which can happen if some other custom error display function is used. This is a common + scenario in some REPLs like IPython. + + PEP 626: Precise line numbers for debugging and other tools ----------------------------------------------------------- @@ -408,7 +454,7 @@ in C, Java or JavaScript (and many other languages). Often the switch statement is used for comparison of an object/expression with case statements containing literals. -More powerful examples of pattern matching can be found in languages, such as +More powerful examples of pattern matching can be found in languages such as Scala and Elixir. With structural pattern matching, the approach is "declarative" and explicitly states the conditions (the patterns) for data to match. @@ -438,11 +484,11 @@ The associated action to the case is executed after a match:: case 418: return "I'm a teapot" case _: - return "Something's wrong with the Internet" + return "Something's wrong with the internet" If the above function is passed a ``status`` of 418, "I'm a teapot" is returned. If the above function is passed a ``status`` of 500, the case statement with -``_`` will match as a wildcard, and "Something's wrong with the Internet" is +``_`` will match as a wildcard, and "Something's wrong with the internet" is returned. Note the last block: the variable name, ``_``, acts as a *wildcard* and insures the subject will always match. The use of ``_`` is optional. @@ -589,7 +635,7 @@ Several other key features: - Like unpacking assignments, tuple and list patterns have exactly the same meaning and actually match arbitrary sequences. Technically, - the subject must be an instance of ``collections.abc.Sequence``. + the subject must be a sequence. Therefore, an important exception is that patterns don't match iterators. Also, to prevent a common mistake, sequence patterns don't match strings. @@ -649,7 +695,7 @@ platforms, omitting ``encoding`` option when opening UTF-8 files with open("data.json") as f: data = json.load(f) -To find this type of bug, optional ``EncodingWarning`` is added. +To find this type of bug, an optional ``EncodingWarning`` is added. It is emitted when :data:`sys.flags.warn_default_encoding ` is true and locale-specific default encoding is used. @@ -658,6 +704,7 @@ are added to enable the warning. See :ref:`io-text-encoding` for more information. +.. _new-feat-related-type-hints: New Features Related to Type Hints ================================== @@ -694,7 +741,8 @@ and :func:`issubclass`:: See :ref:`types-union` and :pep:`604` for more details. -(Contributed by Maggie Moss and Philippe Prados in :issue:`41428`.) +(Contributed by Maggie Moss and Philippe Prados in :issue:`41428`, +with additions by Yurii Karabas and Serhiy Storchaka in :issue:`44490`.) PEP 612: Parameter Specification Variables @@ -812,6 +860,30 @@ Other Language Changes :ref:`annotations-howto`. (Contributed by Larry Hastings in :issue:`43901`.) +* Annotations consist of ``yield``, ``yield from``, ``await`` or named expressions + are now forbidden under ``from __future__ import annotations`` due to their side + effects. + (Contributed by Batuhan Taskaya in :issue:`42725`.) + +* Usage of unbound variables, ``super()`` and other expressions that might + alter the processing of symbol table as annotations are now rendered + effectless under ``from __future__ import annotations``. + (Contributed by Batuhan Taskaya in :issue:`42725`.) + +* Hashes of NaN values of both :class:`float` type and + :class:`decimal.Decimal` type now depend on object identity. Formerly, they + always hashed to ``0`` even though NaN values are not equal to one another. + This caused potentially quadratic runtime behavior due to excessive hash + collisions when creating dictionaries and sets containing multiple NaNs. + (Contributed by Raymond Hettinger in :issue:`43475`.) + +* A :exc:`SyntaxError` (instead of a :exc:`NameError`) will be raised when deleting + the :const:`__debug__` constant. (Contributed by Dong-hee Na in :issue:`45000`.) + +* :exc:`SyntaxError` exceptions now have ``end_lineno`` and + ``end_offset`` attributes. They will be ``None`` if not determined. + (Contributed by Pablo Galindo in :issue:`43914`.) + New Modules =========== @@ -824,7 +896,7 @@ Improved Modules asyncio ------- -Added missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket` +Add missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket` method. (Contributed by Alex Grönholm in :issue:`41332`.) @@ -841,6 +913,12 @@ The :meth:`~array.array.index` method of :class:`array.array` now has optional *start* and *stop* parameters. (Contributed by Anders Lorentsen and Zackery Spytz in :issue:`31956`.) +asynchat, asyncore, smtpd +------------------------- +These modules have been marked as deprecated in their module documentation +since Python 3.6. An import-time :class:`DeprecationWarning` has now been +added to all three of these modules. + base64 ------ @@ -853,6 +931,12 @@ bdb Add :meth:`~bdb.Breakpoint.clearBreakpoints` to reset all set breakpoints. (Contributed by Irit Katriel in :issue:`24160`.) +bisect +------ + +Added the possibility of providing a *key* function to the APIs in the :mod:`bisect` +module. (Contributed by Raymond Hettinger in :issue:`4356`.) + codecs ------ @@ -904,9 +988,68 @@ they are provided by the underlying curses library. dataclasses ----------- +__slots__ +~~~~~~~~~ + Added ``slots`` parameter in :func:`dataclasses.dataclass` decorator. (Contributed by Yurii Karabas in :issue:`42269`) +Keyword-only fields +~~~~~~~~~~~~~~~~~~~ + +dataclasses now supports fields that are keyword-only in the +generated __init__ method. There are a number of ways of specifying +keyword-only fields. + +You can say that every field is keyword-only: + +.. code-block:: python + + from dataclasses import dataclass + + @dataclass(kw_only=True) + class Birthday: + name: str + birthday: datetime.date + +Both ``name`` and ``birthday`` are keyword-only parameters to the +generated __init__ method. + +You can specify keyword-only on a per-field basis: + +.. code-block:: python + + from dataclasses import dataclass + + @dataclass + class Birthday: + name: str + birthday: datetime.date = field(kw_only=True) + +Here only ``birthday`` is keyword-only. If you set ``kw_only`` on +individual fields, be aware that there are rules about re-ordering +fields due to keyword-only fields needing to follow non-keyword-only +fields. See the full dataclasses documentation for details. + +You can also specify that all fields following a KW_ONLY marker are +keyword-only. This will probably be the most common usage: + +.. code-block:: python + + from dataclasses import dataclass, KW_ONLY + + @dataclass + class Point: + x: float + y: float + _: KW_ONLY + z: float = 0.0 + t: float = 0.0 + +Here, ``z`` and ``t`` are keyword-only parameters, while ``x`` and +``y`` are not. +(Contributed by Eric V. Smith in :issue:`43532`) + .. _distutils-deprecated: distutils @@ -939,21 +1082,10 @@ encodings :func:`encodings.normalize_encoding` now ignores non-ASCII characters. (Contributed by Hai Shi in :issue:`39337`.) -enum ----- - -:class:`Enum` :func:`__repr__` now returns ``enum_name.member_name`` and -:func:`__str__` now returns ``member_name``. Stdlib enums available as -module constants have a :func:`repr` of ``module_name.member_name``. -(Contributed by Ethan Furman in :issue:`40066`.) - -Add :class:`enum.StrEnum` for enums where all members are strings. -(Contributed by Ethan Furman in :issue:`41816`.) - fileinput --------- -Added *encoding* and *errors* parameters in :func:`fileinput.input` and +Add *encoding* and *errors* parameters in :func:`fileinput.input` and :class:`fileinput.FileInput`. (Contributed by Inada Naoki in :issue:`43712`.) @@ -961,16 +1093,23 @@ Added *encoding* and *errors* parameters in :func:`fileinput.input` and when *mode* is "r" and file is compressed, like uncompressed files. (Contributed by Inada Naoki in :issue:`5758`.) +faulthandler +------------ + +The :mod:`faulthandler` module now detects if a fatal error occurs during a +garbage collector collection. +(Contributed by Victor Stinner in :issue:`44466`.) + gc -- -Added audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and +Add audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and :func:`gc.get_referents`. (Contributed by Pablo Galindo in :issue:`43439`.) glob ---- -Added the *root_dir* and *dir_fd* parameters in :func:`~glob.glob` and +Add the *root_dir* and *dir_fd* parameters in :func:`~glob.glob` and :func:`~glob.iglob` which allow to specify the root directory for searching. (Contributed by Serhiy Storchaka in :issue:`38144`.) @@ -1020,14 +1159,23 @@ Terry Jan Reedy in :issue:`37892`.) We expect to backport these shell changes to a future 3.9 maintenance release. +Highlight the new :ref:`soft keywords ` :keyword:`match`, +:keyword:`case `, and :keyword:`_ ` in +pattern-matching statements. However, this highlighting is not perfect +and will be incorrect in some rare cases, including some ``_``-s in +``case`` patterns. (Contributed by Tal Einat in :issue:`44010`.) + importlib.metadata ------------------ -Feature parity with ``importlib_metadata`` 3.7. +Feature parity with ``importlib_metadata`` 4.6 +(`history `_). -:func:`importlib.metadata.entry_points` now provides a nicer experience +:ref:`importlib.metadata entry points ` +now provide a nicer experience for selecting entry points by group and name through a new -:class:`importlib.metadata.EntryPoints` class. +:class:`importlib.metadata.EntryPoints` class. See the Compatibility +Note in the docs for more info on the deprecation and usage. Added :func:`importlib.metadata.packages_distributions` for resolving top-level Python modules and packages to their @@ -1039,7 +1187,7 @@ inspect When a module does not define ``__loader__``, fall back to ``__spec__.loader``. (Contributed by Brett Cannon in :issue:`42133`.) -Added :func:`inspect.get_annotations`, which safely computes the annotations +Add :func:`inspect.get_annotations`, which safely computes the annotations defined on an object. It works around the quirks of accessing the annotations on various types of objects, and makes very few assumptions about the object it examines. :func:`inspect.get_annotations` can also correctly un-stringize @@ -1048,7 +1196,7 @@ best practice for accessing the annotations dict defined on any Python object; for more information on best practices for working with annotations, please see :ref:`annotations-howto`. Relatedly, :func:`inspect.signature`, -:func:`inspect.Signature.from_callable`, and ``inspect.Signature.from_function`` +:func:`inspect.Signature.from_callable`, and :func:`inspect.Signature.from_function` now call :func:`inspect.get_annotations` to retrieve annotations. This means :func:`inspect.signature` and :func:`inspect.Signature.from_callable` can also now un-stringize stringized annotations. @@ -1063,41 +1211,54 @@ When a module does not define ``__loader__``, fall back to ``__spec__.loader``. os -- -Added :func:`os.cpu_count()` support for VxWorks RTOS. +Add :func:`os.cpu_count()` support for VxWorks RTOS. (Contributed by Peixing Xin in :issue:`41440`.) -Added a new function :func:`os.eventfd` and related helpers to wrap the +Add a new function :func:`os.eventfd` and related helpers to wrap the ``eventfd2`` syscall on Linux. (Contributed by Christian Heimes in :issue:`41001`.) -Added :func:`os.splice()` that allows to move data between two file +Add :func:`os.splice()` that allows to move data between two file descriptors without copying between kernel address space and user address space, where one of the file descriptors must refer to a pipe. (Contributed by Pablo Galindo in :issue:`41625`.) -Added :data:`~os.O_EVTONLY`, :data:`~os.O_FSYNC`, :data:`~os.O_SYMLINK` +Add :data:`~os.O_EVTONLY`, :data:`~os.O_FSYNC`, :data:`~os.O_SYMLINK` and :data:`~os.O_NOFOLLOW_ANY` for macOS. (Contributed by Dong-hee Na in :issue:`43106`.) +os.path +------- + +:func:`os.path.realpath` now accepts a *strict* keyword-only argument. When set +to ``True``, :exc:`OSError` is raised if a path doesn't exist or a symlink loop +is encountered. +(Contributed by Barney Gale in :issue:`43757`.) + pathlib ------- -Added slice support to :attr:`PurePath.parents `. +Add slice support to :attr:`PurePath.parents `. (Contributed by Joshua Cannon in :issue:`35498`) -Added negative indexing support to :attr:`PurePath.parents +Add negative indexing support to :attr:`PurePath.parents `. (Contributed by Yaroslav Pankovych in :issue:`21041`) -Added :meth:`Path.hardlink_to ` method that +Add :meth:`Path.hardlink_to ` method that supersedes :meth:`~pathlib.Path.link_to`. The new method has the same argument order as :meth:`~pathlib.Path.symlink_to`. (Contributed by Barney Gale in :issue:`39950`.) +:meth:`pathlib.Path.stat` and :meth:`~pathlib.Path.chmod` now accept a +*follow_symlinks* keyword-only argument for consistency with corresponding +functions in the :mod:`os` module. +(Contributed by Barney Gale in :issue:`39906`.) + platform -------- -Added :func:`platform.freedesktop_os_release()` to retrieve operation system +Add :func:`platform.freedesktop_os_release()` to retrieve operation system identification from `freedesktop.org os-release `_ standard file. (Contributed by Christian Heimes in :issue:`28468`) @@ -1105,19 +1266,22 @@ identification from `freedesktop.org os-release pprint ------ +:func:`pprint.pprint` now accepts a new ``underscore_numbers`` keyword argument. +(Contributed by sblondon in :issue:`42914`.) + :mod:`pprint` can now pretty-print :class:`dataclasses.dataclass` instances. (Contributed by Lewis Gaul in :issue:`43080`.) py_compile ---------- -Added ``--quiet`` option to command-line interface of :mod:`py_compile`. +Add ``--quiet`` option to command-line interface of :mod:`py_compile`. (Contributed by Gregory Schevchenko in :issue:`38731`.) pyclbr ------ -Added an ``end_lineno`` attribute to the ``Function`` and ``Class`` +Add an ``end_lineno`` attribute to the ``Function`` and ``Class`` objects in the tree returned by :func:`pyclbr.readline` and :func:`pyclbr.readline_ex`. It matches the existing (start) ``lineno``. (Contributed by Aviral Srivastava in :issue:`38307`.) @@ -1132,7 +1296,7 @@ instead of :mod:`pickle` protocol ``3`` when creating shelves. statistics ---------- -Added :func:`~statistics.covariance`, Pearson's +Add :func:`~statistics.covariance`, Pearson's :func:`~statistics.correlation`, and simple :func:`~statistics.linear_regression` functions. (Contributed by Tymoteusz Wołodźko in :issue:`38490`.) @@ -1149,9 +1313,12 @@ socket The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. (Contributed by Christian Heimes in :issue:`42413`.) -Added option to create MPTCP sockets with ``IPPROTO_MPTCP`` +Add option to create MPTCP sockets with ``IPPROTO_MPTCP`` (Contributed by Rui Cunha in :issue:`43571`.) +Add ``IP_RECVTOS`` option to receive the type of service (ToS) or DSCP/ECN fields +(Contributed by Georg Sauthoff in :issue:`44077`.) + ssl --- @@ -1165,18 +1332,11 @@ The ssl module has preliminary support for OpenSSL 3.0.0 and new option :issue:`43789`, and :issue:`43811`.) Deprecated function and use of deprecated constants now result in -a :exc:`DeprecationWarning`. The following features have been deprecated -since Python 3.6, Python 3.7, or OpenSSL 1.1.0: -:data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`, -:data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`, -:data:`~ssl.OP_NO_TLSv1_3`, :data:`~ssl.PROTOCOL_SSLv2`, -:data:`~ssl.PROTOCOL_SSLv3`, :data:`~ssl.PROTOCOL_SSLv23`, -:data:`~ssl.PROTOCOL_TLSv1`, :data:`~ssl.PROTOCOL_TLSv1_1`, -:data:`~ssl.PROTOCOL_TLSv1_2`, :data:`~ssl.PROTOCOL_TLS`, -:func:`~ssl.wrap_socket`, :func:`~ssl.match_hostname`, -:func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd`, -:meth:`ssl.SSLSocket.selected_npn_protocol`, -:meth:`ssl.SSLContext.set_npn_protocols`. +a :exc:`DeprecationWarning`. :attr:`ssl.SSLContext.options` has +:data:`~ssl.OP_NO_SSLv2` and :data:`~ssl.OP_NO_SSLv3` set by default and +therefore cannot warn about setting the flag again. The +:ref:`deprecation section ` has a list of deprecated +features. (Contributed by Christian Heimes in :issue:`43880`.) The ssl module now has more secure default settings. Ciphers without forward @@ -1229,7 +1389,7 @@ simulate (the default is still :data:`signal.SIGINT`). threading --------- -Added :func:`threading.gettrace` and :func:`threading.getprofile` to +Add :func:`threading.gettrace` and :func:`threading.getprofile` to retrieve the functions set by :func:`threading.settrace` and :func:`threading.setprofile` respectively. (Contributed by Mario Corchero in :issue:`42251`.) @@ -1251,7 +1411,7 @@ as a positional-only argument. types ----- -Reintroduced the :data:`types.EllipsisType`, :data:`types.NoneType` +Reintroduce the :data:`types.EllipsisType`, :data:`types.NoneType` and :data:`types.NotImplementedType` classes, providing a new set of types readily interpretable by type checkers. (Contributed by Bas van Beek in :issue:`41810`.) @@ -1259,20 +1419,20 @@ of types readily interpretable by type checkers. typing ------ -For major changes, see `New Features Related to Type Hints`_. +For major changes, see :ref:`new-feat-related-type-hints`. The behavior of :class:`typing.Literal` was changed to conform with :pep:`586` and to match the behavior of static type checkers specified in the PEP. 1. ``Literal`` now de-duplicates parameters. 2. Equality comparisons between ``Literal`` objects are now order independent. -3. ``Literal`` comparisons now respects types. For example, +3. ``Literal`` comparisons now respect types. For example, ``Literal[0] == Literal[False]`` previously evaluated to ``True``. It is now ``False``. To support this change, the internally used type cache now supports differentiating types. 4. ``Literal`` objects will now raise a :exc:`TypeError` exception during - equality comparisons if one of their parameters are not :term:`immutable`. - Note that declaring ``Literal`` with mutable parameters will not throw + equality comparisons if any of their parameters are not :term:`hashable`. + Note that declaring ``Literal`` with unhashable parameters will not throw an error:: >>> from typing import Literal @@ -1288,6 +1448,21 @@ Add new function :func:`typing.is_typeddict` to introspect if an annotation is a :class:`typing.TypedDict`. (Contributed by Patrick Reader in :issue:`41792`) +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:`runtime_checkable`. Previously, these checks +passed silently. Users should decorate their +subclasses with the :func:`runtime_checkable` decorator +if they want runtime protocols. +(Contributed by Yurii Karabas in :issue:`38908`) + +Importing from the ``typing.io`` and ``typing.re`` submodules will now emit +:exc:`DeprecationWarning`. These submodules have been deprecated since +Python 3.8 and will be removed in a future version of Python. Anything +belonging to those submodules should be imported directly from +:mod:`typing` instead. +(Contributed by Sebastian Rittau in :issue:`38291`) + unittest -------- @@ -1308,6 +1483,13 @@ functions internally. For more details, please see their respective documentation. (Contributed by Adam Goldschmidt, Senthil Kumaran and Ken Jin in :issue:`42967`.) +The presence of newline or tab characters in parts of a URL allows for some +forms of attacks. Following the WHATWG specification that updates :rfc:`3986`, +ASCII newline ``\n``, ``\r`` and tab ``\t`` characters are stripped from the +URL by the parser in :mod:`urllib.parse` preventing such attacks. The removal +characters are controlled by a new module level variable +``urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE``. (See :issue:`43882`) + xml --- @@ -1355,12 +1537,12 @@ Optimizations * Use a new output buffer management code for :mod:`bz2` / :mod:`lzma` / :mod:`zlib` modules, and add ``.readall()`` function to - ``_compression.DecompressReader`` class. bz2 decompression 1.09x ~ 1.17x + ``_compression.DecompressReader`` class. bz2 decompression is now 1.09x ~ 1.17x faster, lzma decompression 1.20x ~ 1.32x faster, ``GzipFile.read(-1)`` 1.11x ~ 1.18x faster. (Contributed by Ma Lin, reviewed by Gregory P. Smith, in :issue:`41486`) * When using stringized annotations, annotations dicts for functions are no longer - created when the function is created. Instead, they're stored as a tuple of + created when the function is created. Instead, they are stored as a tuple of strings, and the function object lazily converts this into the annotations dict on demand. This optimization cuts the CPU time needed to define an annotated function by half. @@ -1371,22 +1553,35 @@ Optimizations algorithm to avoid quadratic behavior on long strings. (Contributed by Dennis Sweeney in :issue:`41972`) -* Added micro-optimizations to ``_PyType_Lookup()`` to improve type attribute cache lookup +* Add micro-optimizations to ``_PyType_Lookup()`` to improve type attribute cache lookup performance in the common case of cache hits. This makes the interpreter 1.04 times faster - in average (Contributed by Dino Viehland in :issue:`43452`) + on average. (Contributed by Dino Viehland in :issue:`43452`) -* Following built-in functions now support the faster :pep:`590` vectorcall calling convention: +* The following built-in functions now support the faster :pep:`590` vectorcall calling convention: :func:`map`, :func:`filter`, :func:`reversed`, :func:`bool` and :func:`float`. - (Contributed by Dong-hee Na and Jeroen Demeyerin in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`) + (Contributed by Dong-hee Na and Jeroen Demeyer in :issue:`43575`, :issue:`43287`, :issue:`41922`, :issue:`41873` and :issue:`41870`) * :class:`BZ2File` performance is improved by removing internal ``RLock``. This makes :class:`BZ2File` thread unsafe in the face of multiple simultaneous readers or writers, just like its equivalent classes in :mod:`gzip` and :mod:`lzma` have always been. (Contributed by Inada Naoki in :issue:`43785`). +.. _whatsnew310-deprecated: + Deprecated ========== +* Currently Python accepts numeric literals immediately followed by keywords, + for example ``0in x``, ``1or x``, ``0if 1else 2``. It allows confusing + and ambiguous expressions like ``[0x1for x in y]`` (which can be + interpreted as ``[0x1 for x in y]`` or ``[0x1f or x in y]``). Starting in + this release, a deprecation warning is raised if the numeric literal is + immediately followed by one of keywords :keyword:`and`, :keyword:`else`, + :keyword:`for`, :keyword:`if`, :keyword:`in`, :keyword:`is` and :keyword:`or`. + In future releases it will be changed to syntax warning, and finally to + syntax error. + (Contributed by Serhiy Storchaka in :issue:`43833`). + * Starting in this release, there will be a concerted effort to begin cleaning up old import semantics that were kept for Python 2.7 compatibility. Specifically, @@ -1448,13 +1643,12 @@ Deprecated :meth:`importlib.machinery.FrozenImporter.find_module`, :meth:`importlib.machinery.WindowsRegistryFinder.find_module`, :meth:`importlib.machinery.PathFinder.find_module`, - :meth:`importlib.abc.MetaPathFinder.find_module`), + :meth:`importlib.abc.MetaPathFinder.find_module` ), :meth:`importlib.abc.PathEntryFinder.find_module` ( - :meth:`importlib.machinery.FileFinder.find_module`, - ), and + :meth:`importlib.machinery.FileFinder.find_module` ), and :meth:`importlib.abc.PathEntryFinder.find_loader` ( - :meth:`importlib.machinery.FileFinder.find_loader` - ) now raise :exc:`DeprecationWarning` and are slated for removal in + :meth:`importlib.machinery.FileFinder.find_loader` ) + now raise :exc:`DeprecationWarning` and are slated for removal in Python 3.12 (previously they were documented as deprecated in Python 3.4). (Contributed by Brett Cannon in :issue:`42135`.) @@ -1492,11 +1686,11 @@ Deprecated scheduled for removal in Python 3.12. (Contributed by Erlend E. Aasland in :issue:`42264`.) -* :func:`asyncio.get_event_loop` emits now a deprecation warning if there is - no running event loop. In future it will be an alias of +* :func:`asyncio.get_event_loop` now emits a deprecation warning if there is + no running event loop. In the future it will be an alias of :func:`~asyncio.get_running_loop`. - :mod:`asyncio` functions which implicitly create a :class:`~asyncio.Future` - or :class:`~asyncio.Task` objects emit now + :mod:`asyncio` functions which implicitly create :class:`~asyncio.Future` + or :class:`~asyncio.Task` objects now emit a deprecation warning if there is no running event loop and no explicit *loop* argument is passed: :func:`~asyncio.ensure_future`, :func:`~asyncio.wrap_future`, :func:`~asyncio.gather`, @@ -1509,7 +1703,7 @@ Deprecated deprecated, scheduled for removal in Python 3.12. Its use is strongly discouraged by the SQLite3 documentation. See `the SQLite3 docs `_ for more details. - If shared cache must be used, open the database in URI mode using the + If a shared cache must be used, open the database in URI mode using the ``cache=shared`` query parameter. (Contributed by Erlend E. Aasland in :issue:`24464`.) @@ -1538,9 +1732,45 @@ Deprecated Python 3.12. Use :meth:`pathlib.Path.hardlink_to` instead. (Contributed by Barney Gale in :issue:`39950`.) -* ``cgi.log()`` is deprecated and slated for for removal in Python 3.12. +* ``cgi.log()`` is deprecated and slated for removal in Python 3.12. (Contributed by Inada Naoki in :issue:`41139`.) +* The following :mod:`ssl` features have been deprecated since Python 3.6, + Python 3.7, or OpenSSL 1.1.0 and will be removed in 3.11: + + * :data:`~ssl.OP_NO_SSLv2`, :data:`~ssl.OP_NO_SSLv3`, :data:`~ssl.OP_NO_TLSv1`, + :data:`~ssl.OP_NO_TLSv1_1`, :data:`~ssl.OP_NO_TLSv1_2`, and + :data:`~ssl.OP_NO_TLSv1_3` are replaced by + :attr:`sslSSLContext.minimum_version` and + :attr:`sslSSLContext.maximum_version`. + + * :data:`~ssl.PROTOCOL_SSLv2`, :data:`~ssl.PROTOCOL_SSLv3`, + :data:`~ssl.PROTOCOL_SSLv23`, :data:`~ssl.PROTOCOL_TLSv1`, + :data:`~ssl.PROTOCOL_TLSv1_1`, :data:`~ssl.PROTOCOL_TLSv1_2`, and + :data:`~ssl.PROTOCOL_TLS` are deprecated in favor of + :data:`~ssl.PROTOCOL_TLS_CLIENT` and :data:`~ssl.PROTOCOL_TLS_SERVER` + + * :func:`~ssl.wrap_socket` is replaced by :meth:`ssl.SSLContext.wrap_socket` + + * :func:`~ssl.match_hostname` + + * :func:`~ssl.RAND_pseudo_bytes`, :func:`~ssl.RAND_egd` + + * NPN features like :meth:`ssl.SSLSocket.selected_npn_protocol` and + :meth:`ssl.SSLContext.set_npn_protocols` are replaced by ALPN. + +* The threading debug (:envvar:`PYTHONTHREADDEBUG` environment variable) is + deprecated in Python 3.10 and will be removed in Python 3.12. This feature + requires a :ref:`debug build of Python `. + (Contributed by Victor Stinner in :issue:`44584`.) + +* Importing from the ``typing.io`` and ``typing.re`` submodules will now emit + :exc:`DeprecationWarning`. These submodules will be removed in a future version + of Python. Anything belonging to these submodules should be imported directly + from :mod:`typing` instead. + (Contributed by Sebastian Rittau in :issue:`38291`) + +.. _whatsnew310-removed: Removed ======= @@ -1553,7 +1783,7 @@ Removed * The ``ParserBase.error()`` method from the private and undocumented ``_markupbase`` module has been removed. :class:`html.parser.HTMLParser` is the only subclass of - ``ParserBase`` and its ``error()`` implementation has already been removed in + ``ParserBase`` and its ``error()`` implementation was already removed in Python 3.5. (Contributed by Berker Peksag in :issue:`31844`.) @@ -1567,9 +1797,9 @@ Removed that were only being used by the old parser, including ``node.h``, ``parser.h``, ``graminit.h`` and ``grammar.h``. -* Removed the Public C API functions :c:func:`PyParser_SimpleParseStringFlags`, - :c:func:`PyParser_SimpleParseStringFlagsFilename`, - :c:func:`PyParser_SimpleParseFileFlags` and :c:func:`PyNode_Compile` +* Removed the Public C API functions ``PyParser_SimpleParseStringFlags``, + ``PyParser_SimpleParseStringFlagsFilename``, + ``PyParser_SimpleParseFileFlags`` and ``PyNode_Compile`` that were deprecated in 3.9 due to the switch to the new PEG parser. * Removed the ``formatter`` module, which was deprecated in Python 3.4. @@ -1599,7 +1829,7 @@ Removed running in different threads. Note that the low-level API will still accept ``loop``. - See `Changes in the Python API`_ for examples of how to replace existing code. + See :ref:`changes-python-api` for examples of how to replace existing code. (Contributed by Yurii Karabas, Andrew Svetlov, Yury Selivanov and Kyle Stanley in :issue:`42392`.) @@ -1612,6 +1842,19 @@ This section lists previously described changes and other bugfixes that may require changes to your code. +Changes in the Python syntax +---------------------------- + +* Deprecation warning is now emitted when compiling previously valid syntax + if the numeric literal is immediately followed by a keyword (like in ``0in x``). + In future releases it will be changed to syntax warning, and finally to a + syntax error. To get rid of the warning and make the code compatible with + future releases just add a space between the numeric literal and the + following keyword. + (Contributed by Serhiy Storchaka in :issue:`43833`). + +.. _changes-python-api: + Changes in the Python API ------------------------- @@ -1646,7 +1889,7 @@ Changes in the Python API :doc:`high-level API <../library/asyncio-api-index>` following deprecation in Python 3.8. - A coroutine that currently look like this:: + A coroutine that currently looks like this:: async def foo(loop): await asyncio.sleep(1, loop=loop) @@ -1667,10 +1910,52 @@ Changes in the Python API if the *globals* dictionary has no ``"__builtins__"`` key, rather than using ``{"None": None}`` as builtins: same behavior as :func:`eval` and :func:`exec` functions. Defining a function with ``def function(...): ...`` - in Python is not affected, globals cannot be overriden with this syntax: it + in Python is not affected, globals cannot be overridden with this syntax: it also inherits the current builtins. (Contributed by Victor Stinner in :issue:`42990`.) +Changes in the C API +-------------------- + +* The C API functions ``PyParser_SimpleParseStringFlags``, + ``PyParser_SimpleParseStringFlagsFilename``, + ``PyParser_SimpleParseFileFlags``, ``PyNode_Compile`` and the type + used by these functions, ``struct _node``, were removed due to the switch + to the new PEG parser. + + Source should be now be compiled directly to a code object using, for + example, :c:func:`Py_CompileString`. The resulting code object can then be + evaluated using, for example, :c:func:`PyEval_EvalCode`. + + Specifically: + + * A call to ``PyParser_SimpleParseStringFlags`` followed by + ``PyNode_Compile`` can be replaced by calling :c:func:`Py_CompileString`. + + * There is no direct replacement for ``PyParser_SimpleParseFileFlags``. + To compile code from a ``FILE *`` argument, you will need to read + the file in C and pass the resulting buffer to :c:func:`Py_CompileString`. + + * To compile a file given a ``char *`` filename, explicitly open the file, read + it and compile the result. One way to do this is using the :py:mod:`io` + module with :c:func:`PyImport_ImportModule`, :c:func:`PyObject_CallMethod`, + :c:func:`PyBytes_AsString` and :c:func:`Py_CompileString`, + as sketched below. (Declarations and error handling are omitted.) :: + + io_module = Import_ImportModule("io"); + fileobject = PyObject_CallMethod(io_module, "open", "ss", filename, "rb"); + source_bytes_object = PyObject_CallMethod(fileobject, "read", ""); + result = PyObject_CallMethod(fileobject, "close", ""); + source_buf = PyBytes_AsString(source_bytes_object); + code = Py_CompileString(source_buf, filename, Py_file_input); + + * For ``FrameObject`` objects, the ``f_lasti`` member now represents a wordcode + offset instead of a simple offset into the bytecode string. This means that this + number needs to be multiplied by 2 to be used with APIs that expect a byte offset + instead (like :c:func:`PyCode_Addr2Line` for example). Notice as well that the + ``f_lasti`` member of ``FrameObject`` objects is not considered stable: please + use :c:func:`PyFrame_GetLineNumber` instead. + CPython bytecode changes ======================== @@ -1690,12 +1975,12 @@ Build Changes (Contributed by Victor Stinner in :issue:`36020`.) * :mod:`sqlite3` requires SQLite 3.7.15 or higher. (Contributed by Sergey Fedoseev - and Erlend E. Aasland :issue:`40744` and :issue:`40810`.) + and Erlend E. Aasland in :issue:`40744` and :issue:`40810`.) * The :mod:`atexit` module must now always be built as a built-in module. (Contributed by Victor Stinner in :issue:`42639`.) -* Added :option:`--disable-test-modules` option to the ``configure`` script: +* Add :option:`--disable-test-modules` option to the ``configure`` script: don't build nor install test modules. (Contributed by Xavier de Gaye, Thomas Petazzoni and Peixing Xin in :issue:`27640`.) @@ -1733,6 +2018,16 @@ Build Changes C API Changes ============= +PEP 652: Maintaining the Stable ABI +----------------------------------- + +The Stable ABI (Application Binary Interface) for extension modules or +embedding Python is now explicitly defined. +:ref:`stable` describes C API and ABI stability guarantees along with best +practices for using the Stable ABI. + +(Contributed by Petr Viktorin in :pep:`652` and :issue:`43795`.) + New Features ------------ @@ -1759,15 +2054,15 @@ New Features sending value into iterator without raising ``StopIteration`` exception. (Contributed by Vladimir Matveev in :issue:`41756`.) -* Added :c:func:`PyUnicode_AsUTF8AndSize` to the limited C API. +* Add :c:func:`PyUnicode_AsUTF8AndSize` to the limited C API. (Contributed by Alex Gaynor in :issue:`41784`.) -* Added :c:func:`PyModule_AddObjectRef` function: similar to +* Add :c:func:`PyModule_AddObjectRef` function: similar to :c:func:`PyModule_AddObject` but don't steal a reference to the value on success. (Contributed by Victor Stinner in :issue:`1635741`.) -* Added :c:func:`Py_NewRef` and :c:func:`Py_XNewRef` functions to increment the +* Add :c:func:`Py_NewRef` and :c:func:`Py_XNewRef` functions to increment the reference count of an object and return the object. (Contributed by Victor Stinner in :issue:`42262`.) @@ -1787,7 +2082,7 @@ New Features object is an instance of :class:`set` but not an instance of a subtype. (Contributed by Pablo Galindo in :issue:`43277`.) -* Added :c:func:`PyErr_SetInterruptEx` which allows passing a signal number +* Add :c:func:`PyErr_SetInterruptEx` which allows passing a signal number to simulate. (Contributed by Antoine Pitrou in :issue:`43356`.) @@ -1812,7 +2107,7 @@ New Features singleton or the ``False`` singleton. (Contributed by Victor Stinner in :issue:`43753`.) -* Add new functions to quickly control the garbage collector from C code: +* Add new functions to control the garbage collector from C code: :c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, :c:func:`PyGC_IsEnabled()`. @@ -1823,6 +2118,10 @@ New Features creating type instances. (Contributed by Victor Stinner in :issue:`43916`.) +* Add a new :c:data:`Py_TPFLAGS_IMMUTABLETYPE` type flag for creating immutable + type objects: type attributes cannot be set nor deleted. + (Contributed by Victor Stinner and Erlend E. Aasland in :issue:`43908`.) + Porting to Python 3.10 ---------------------- @@ -1880,6 +2179,16 @@ Porting to Python 3.10 been included directly, consider including ``Python.h`` instead. (Contributed by Nicholas Sim in :issue:`35134`) +* Use the :c:data:`Py_TPFLAGS_IMMUTABLETYPE` type flag to create immutable type + objects. Do not rely on :c:data:`Py_TPFLAGS_HEAPTYPE` to decide if a type + object is mutable or not; check if :c:data:`Py_TPFLAGS_IMMUTABLETYPE` is set + instead. + (Contributed by Victor Stinner and Erlend E. Aasland in :issue:`43908`.) + +* The undocumented function ``Py_FrozenMain`` has been removed from the + limited API. The function is mainly useful for custom builds of Python. + (Contributed by Petr Viktorin in :issue:`26241`) + Deprecated ---------- @@ -1891,11 +2200,6 @@ Deprecated Removed ------- -* ``PyObject_AsCharBuffer()``, ``PyObject_AsReadBuffer()``, ``PyObject_CheckReadBuffer()``, - and ``PyObject_AsWriteBuffer()`` are removed. Please migrate to new buffer protocol; - :c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release`. - (Contributed by Inada Naoki in :issue:`41103`.) - * Removed ``Py_UNICODE_str*`` functions manipulating ``Py_UNICODE*`` strings. (Contributed by Inada Naoki in :issue:`41123`.) @@ -1996,3 +2300,6 @@ Removed These functions were undocumented, excluded from the limited C API, and were only used internally by the compiler. (Contributed by Victor Stinner in :issue:`43244`.) + +* The ``PyThreadState.use_tracing`` member has been removed to optimize Python. + (Contributed by Mark Shannon in :issue:`43760`.) diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 06bee9966c0be2..840cb061129b7f 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -1921,7 +1921,7 @@ inspect pydoc ----- -The :mod:`pydoc` module now provides a much-improved Web server interface, as +The :mod:`pydoc` module now provides a much-improved web server interface, as well as a new command-line option ``-b`` to automatically open a browser window to display that server: diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index 99d040840d9fb3..0405f2ba193466 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -490,7 +490,7 @@ environment was declined. :mod:`ensurepip` includes a bundled copy of ``pip``, up-to-date as of the first release candidate of the release of CPython with which it ships (this applies to both maintenance releases and feature releases). ``ensurepip`` does not -access the internet. If the installation has Internet access, after +access the internet. If the installation has internet access, after ``ensurepip`` is run the bundled ``pip`` can be used to upgrade ``pip`` to a more recent release than the bundled one. (Note that such an upgraded version of ``pip`` is considered to be a separately installed package and will not be diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index f1a903624f4c2c..7c293a501895b3 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -2248,3 +2248,16 @@ separator key, with ``&`` as the default. This change also affects functions internally. For more details, please see their respective documentation. (Contributed by Adam Goldschmidt, Senthil Kumaran and Ken Jin in :issue:`42967`.) + +Notable changes in Python 3.8.12 +================================ + +Starting with Python 3.8.12 the :mod:`ipaddress` module no longer accepts +any leading zeros in IPv4 address strings. Leading zeros are ambiguous and +interpreted as octal notation by some libraries. For example the legacy +function :func:`socket.inet_aton` treats leading zeros as octal notation. +glibc implementation of modern :func:`~socket.inet_pton` does not accept +any leading zeros. + +(Originally contributed by Christian Heimes in :issue:`36384`, and backported +to 3.8 by Achraf Merzouki.) diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 772fb5a3fe7458..296c64d737d3ec 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -1378,10 +1378,6 @@ Porting to Python 3.9 becomes an alias to the :c:func:`PyObject_NewVar` macro. They no longer access directly the :c:member:`PyTypeObject.tp_basicsize` member. - * :c:func:`PyType_HasFeature` now always calls :c:func:`PyType_GetFlags`. - Previously, it accessed directly the :c:member:`PyTypeObject.tp_flags` - member when the limited C API was not used. - * :c:func:`PyObject_GET_WEAKREFS_LISTPTR` macro was converted to a function: the macro accessed directly the :c:member:`PyTypeObject.tp_weaklistoffset` member. @@ -1494,7 +1490,7 @@ and to match the behavior of static type checkers specified in the PEP. now ``False``. To support this change, the internally used type cache now supports differentiating types. 4. ``Literal`` objects will now raise a :exc:`TypeError` exception during - equality comparisons if one of their parameters are not :term:`immutable`. + equality comparisons if any of their parameters are not :term:`hashable`. Note that declaring ``Literal`` with mutable parameters will not throw an error:: diff --git a/Grammar/python.gram b/Grammar/python.gram index 2f553c6d390c71..f730658462147f 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -244,6 +244,7 @@ pattern[pattern_ty]: as_pattern[pattern_ty]: | pattern=or_pattern 'as' target=pattern_capture_target { _PyAST_MatchAs(pattern, target->v.Name.id, EXTRA) } + | invalid_as_pattern or_pattern[pattern_ty]: | patterns[asdl_pattern_seq*]='|'.closed_pattern+ { asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _PyAST_MatchOr(patterns, EXTRA) } @@ -379,6 +380,7 @@ class_pattern[pattern_ty]: CHECK(asdl_expr_seq*, _PyPegen_get_pattern_keys(p, keywords)))), CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, keywords)), EXTRA) } + | invalid_class_pattern positional_patterns[asdl_pattern_seq*]: | args[asdl_pattern_seq*]=','.pattern+ { args } keyword_patterns[asdl_seq*]: @@ -509,13 +511,13 @@ star_named_expression[expr_ty]: | '*' a=bitwise_or { _PyAST_Starred(a, Load, EXTRA) } | named_expression -named_expression[expr_ty]: - | a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) } - | invalid_named_expression - | expression !':=' -direct_named_expression[expr_ty]: +assignment_expression[expr_ty]: | a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) } + +named_expression[expr_ty]: + | assignment_expression + | invalid_named_expression | expression !':=' annotated_rhs[expr_ty]: yield_expr | star_expressions @@ -527,6 +529,7 @@ expressions[expr_ty]: | expression expression[expr_ty] (memo): | invalid_expression + | invalid_legacy_expression | a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) } | disjunction | lambdef @@ -664,7 +667,6 @@ await_primary[expr_ty] (memo): | AWAIT a=primary { CHECK_VERSION(expr_ty, 5, "Await expressions are", _PyAST_Await(a, EXTRA)) } | primary primary[expr_ty]: - | invalid_primary # must be before 'primay genexp' because of invalid_genexp | a=primary '.' b=NAME { _PyAST_Attribute(a, b->v.Name.id, Load, EXTRA) } | a=primary b=genexp { _PyAST_Call(a, CHECK(asdl_expr_seq*, (asdl_expr_seq*)_PyPegen_singleton_seq(p, b)), NULL, EXTRA) } | a=primary '(' b=[arguments] ')' { @@ -706,7 +708,7 @@ group[expr_ty]: | '(' a=(yield_expr | named_expression) ')' { a } | invalid_group genexp[expr_ty]: - | '(' a=direct_named_expression b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } + | '(' a=( assignment_expression | expression !':=') b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) } | invalid_comprehension set[expr_ty]: '{' a=star_named_expressions '}' { _PyAST_Set(a, EXTRA) } setcomp[expr_ty]: @@ -745,11 +747,13 @@ arguments[expr_ty] (memo): | a=args [','] &')' { a } | invalid_arguments args[expr_ty]: - | a[asdl_expr_seq*]=','.(starred_expression | direct_named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) } + | a[asdl_expr_seq*]=','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ b=[',' k=kwargs {k}] { + _PyPegen_collect_call_seqs(p, a, b, EXTRA) } | a=kwargs { _PyAST_Call(_PyPegen_dummy_name(p), CHECK_NULL_ALLOWED(asdl_expr_seq*, _PyPegen_seq_extract_starred_exprs(p, a)), CHECK_NULL_ALLOWED(asdl_keyword_seq*, _PyPegen_seq_delete_starred_exprs(p, a)), EXTRA) } + kwargs[asdl_seq*]: | a=','.kwarg_or_starred+ ',' b=','.kwarg_or_double_starred+ { _PyPegen_join_sequences(p, a, b) } | ','.kwarg_or_starred+ @@ -757,15 +761,15 @@ kwargs[asdl_seq*]: starred_expression[expr_ty]: | '*' a=expression { _PyAST_Starred(a, Load, EXTRA) } kwarg_or_starred[KeywordOrStarred*]: + | invalid_kwarg | a=NAME '=' b=expression { _PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(a->v.Name.id, b, EXTRA)), 1) } | a=starred_expression { _PyPegen_keyword_or_starred(p, a, 0) } - | invalid_kwarg kwarg_or_double_starred[KeywordOrStarred*]: + | invalid_kwarg | a=NAME '=' b=expression { _PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(a->v.Name.id, b, EXTRA)), 1) } | '**' a=expression { _PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(NULL, a, EXTRA)), 1) } - | invalid_kwarg # NOTE: star_targets may contain *bitwise_or, targets may not. star_targets[expr_ty]: @@ -809,11 +813,6 @@ del_t_atom[expr_ty]: | '(' a=[del_targets] ')' { _PyAST_Tuple(a, Del, EXTRA) } | '[' a=[del_targets] ']' { _PyAST_List(a, Del, EXTRA) } -targets[asdl_expr_seq*]: a[asdl_expr_seq*]=','.target+ [','] { a } -target[expr_ty] (memo): - | a=t_primary '.' b=NAME !t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Store, EXTRA) } - | a=t_primary '[' b=slices ']' !t_lookahead { _PyAST_Subscript(a, b, Store, EXTRA) } - | t_atom t_primary[expr_ty]: | a=t_primary '.' b=NAME &t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Load, EXTRA) } | a=t_primary '[' b=slices ']' &t_lookahead { _PyAST_Subscript(a, b, Load, EXTRA) } @@ -826,41 +825,52 @@ t_primary[expr_ty]: EXTRA) } | a=atom &t_lookahead { a } t_lookahead: '(' | '[' | '.' -t_atom[expr_ty]: - | a=NAME { _PyPegen_set_expr_context(p, a, Store) } - | '(' a=target ')' { _PyPegen_set_expr_context(p, a, Store) } - | '(' b=[targets] ')' { _PyAST_Tuple(b, Store, EXTRA) } - | '[' b=[targets] ']' { _PyAST_List(b, Store, EXTRA) } - # From here on, there are rules for invalid syntax with specialised error messages invalid_arguments: | a=args ',' '*' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable argument unpacking follows keyword argument unpacking") } | a=expression b=for_if_clauses ',' [args | expression for_if_clauses] { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, PyPegen_last_item(b, comprehension_ty)->target, "Generator expression must be parenthesized") } - | a=args for_if_clauses { _PyPegen_nonparen_genexp_in_call(p, a) } + | a=NAME b='=' expression for_if_clauses { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?")} + | a=args b=for_if_clauses { _PyPegen_nonparen_genexp_in_call(p, a, b) } | args ',' a=expression b=for_if_clauses { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, asdl_seq_GET(b, b->size-1)->target, "Generator expression must be parenthesized") } | a=args ',' args { _PyPegen_arguments_parsing_error(p, a) } invalid_kwarg: - | a=expression b='=' { + | a[Token*]=('True'|'False'|'None') b='=' { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to %s", PyBytes_AS_STRING(a->bytes)) } + | a=NAME b='=' expression for_if_clauses { + RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?")} + | !(NAME '=') a=expression b='=' { RAISE_SYNTAX_ERROR_KNOWN_RANGE( a, b, "expression cannot contain assignment, perhaps you meant \"==\"?") } +expression_without_invalid[expr_ty]: + | a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) } + | disjunction + | lambdef +invalid_legacy_expression: + | a=NAME !'(' b=star_expressions { + _PyPegen_check_legacy_stmt(p, a) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, + "Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL} + invalid_expression: # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME - | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression { + | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { + _PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") } + | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") } invalid_named_expression: | a=expression ':=' expression { RAISE_SYNTAX_ERROR_KNOWN_LOCATION( a, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) } - | a=NAME '=' b=bitwise_or !('='|':='|',') { - RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?") } - | !(list|tuple|genexp|'True'|'None'|'False') a=bitwise_or b='=' bitwise_or !('='|':='|',') { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s here. Maybe you meant '==' instead of '='?", + | a=NAME '=' b=bitwise_or !('='|':=') { + p->in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?") } + | !(list|tuple|genexp|'True'|'None'|'False') a=bitwise_or b='=' bitwise_or !('='|':=') { + p->in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s here. Maybe you meant '==' instead of '='?", _PyPegen_get_expr_name(a)) } invalid_assignment: @@ -892,8 +902,6 @@ invalid_del_stmt: RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) } invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } -invalid_primary: - | primary a='{' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "invalid syntax") } invalid_comprehension: | ('[' | '(' | '{') a=starred_expression for_if_clauses { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") } @@ -939,7 +947,7 @@ invalid_group: | '(' a='**' expression ')' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot use double starred expression here") } invalid_import_from_targets: - | import_from_as_names ',' { + | import_from_as_names ',' NEWLINE { RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") } invalid_with_stmt: @@ -954,9 +962,10 @@ invalid_with_stmt_indent: invalid_try_stmt: | a='try' ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'try' statement on line %d", a->lineno) } + | 'try' ':' block !('except' | 'finally') { RAISE_SYNTAX_ERROR("expected 'except' or 'finally' block") } invalid_except_stmt: | 'except' a=expression ',' expressions ['as' NAME ] ':' { - RAISE_SYNTAX_ERROR_STARTING_FROM(a, "exception group must be parenthesized") } + RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") } | a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } | a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } invalid_finally_stmt: @@ -974,6 +983,16 @@ invalid_case_block: | "case" patterns guard? !':' { RAISE_SYNTAX_ERROR("expected ':'") } | a="case" patterns guard? ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'case' statement on line %d", a->lineno) } +invalid_as_pattern: + | or_pattern 'as' a="_" { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot use '_' as a target") } + | or_pattern 'as' !NAME a=expression { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "invalid pattern target") } +invalid_class_pattern: + | name_or_attr '(' a=invalid_class_argument_pattern { RAISE_SYNTAX_ERROR_KNOWN_RANGE( + PyPegen_first_item(a, pattern_ty), + PyPegen_last_item(a, pattern_ty), + "positional patterns follow keyword patterns") } +invalid_class_argument_pattern[asdl_pattern_seq*]: + | [positional_patterns ','] keyword_patterns ',' a=positional_patterns { a } invalid_if_stmt: | 'if' named_expression NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") } | a='if' a=named_expression ':' NEWLINE !INDENT { diff --git a/Include/Python.h b/Include/Python.h index 4d0335d3c52c36..d3186c32e35500 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -35,19 +35,6 @@ #ifndef MS_WINDOWS #include #endif -#ifdef HAVE_CRYPT_H -#if defined(HAVE_CRYPT_R) && !defined(_GNU_SOURCE) -/* Required for glibc to expose the crypt_r() function prototype. */ -# define _GNU_SOURCE -# define _Py_GNU_SOURCE_FOR_CRYPT -#endif -#include -#ifdef _Py_GNU_SOURCE_FOR_CRYPT -/* Don't leak the _GNU_SOURCE define to other headers. */ -# undef _GNU_SOURCE -# undef _Py_GNU_SOURCE_FOR_CRYPT -#endif -#endif /* For size_t? */ #ifdef HAVE_STDDEF_H @@ -63,13 +50,22 @@ #include "pyport.h" #include "pymacro.h" -/* A convenient way for code to know if clang's memory sanitizer is enabled. */ +/* A convenient way for code to know if sanitizers are enabled. */ #if defined(__has_feature) # if __has_feature(memory_sanitizer) # if !defined(_Py_MEMORY_SANITIZER) # define _Py_MEMORY_SANITIZER # endif # endif +# if __has_feature(address_sanitizer) +# if !defined(_Py_ADDRESS_SANITIZER) +# define _Py_ADDRESS_SANITIZER +# endif +# endif +#elif defined(__GNUC__) +# if defined(__SANITIZE_ADDRESS__) +# define _Py_ADDRESS_SANITIZER +# endif #endif #include "pymath.h" @@ -110,6 +106,7 @@ #include "sliceobject.h" #include "cellobject.h" #include "iterobject.h" +#include "cpython/initconfig.h" #include "genobject.h" #include "descrobject.h" #include "genericaliasobject.h" @@ -122,8 +119,6 @@ #include "codecs.h" #include "pyerrors.h" - -#include "cpython/initconfig.h" #include "pythread.h" #include "pystate.h" #include "context.h" diff --git a/Include/README.rst b/Include/README.rst index d2467ca22fa038..f52e690eac9a91 100644 --- a/Include/README.rst +++ b/Include/README.rst @@ -3,66 +3,10 @@ The Python C API The C API is divided into three sections: -1. ``Include/`` -2. ``Include/cpython/`` -3. ``Include/internal/`` +1. ``Include/``: Limited API +2. ``Include/cpython/``: CPython implementation details +3. ``Include/internal/``: The internal API +Information on changing the C API is available `in the developer guide`_ -Include: Limited API -==================== - -``Include/``, excluding the ``cpython`` and ``internal`` subdirectories, -contains the public Limited API (Application Programming Interface). -The Limited API is a subset of the C API, designed to guarantee ABI -stability across Python 3 versions, and is defined in :pep:`384`. - -Guidelines for expanding the Limited API: - -- Functions *must not* steal references -- Functions *must not* return borrowed references -- Functions returning references *must* return a strong reference -- Macros should not expose implementation details -- Please start a public discussion before expanding the API -- Functions or macros with a ``_Py`` prefix do not belong in ``Include/``. - -It is possible to add a function or macro to the Limited API from a -given Python version. For example, to add a function to the Limited API -from Python 3.10 and onwards, wrap it with -``#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000``. - - -Include/cpython: CPython implementation details -=============================================== - -``Include/cpython/`` contains the public API that is excluded from the -Limited API and the Stable ABI. - -Guidelines for expanding the public API: - -- Functions *must not* steal references -- Functions *must not* return borrowed references -- Functions returning references *must* return a strong reference - - -Include/internal: The internal API -================================== - - -With PyAPI_FUNC or PyAPI_DATA ------------------------------ - -Functions or structures in ``Include/internal/`` defined with -``PyAPI_FUNC`` or ``PyAPI_DATA`` are internal functions which are -exposed only for specific use cases like debuggers and profilers. - - -With the extern keyword ------------------------ - -Functions in ``Include/internal/`` defined with the ``extern`` keyword -*must not and can not* be used outside the CPython code base. Only -built-in stdlib extensions (built with the ``Py_BUILD_CORE_BUILTIN`` -macro defined) can use such functions. - -When in doubt, new internal C functions should be defined in -``Include/internal`` using the ``extern`` keyword. +.. _in the developer guide: https://devguide.python.org/c-api/ diff --git a/Include/abstract.h b/Include/abstract.h index 1af1487deec916..9eaab6b2e054c4 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -309,6 +309,53 @@ PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key); PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key); +/* === Old Buffer API ============================================ */ + +/* FIXME: usage of these should all be replaced in Python itself + but for backwards compatibility we will implement them. + Their usage without a corresponding "unlock" mechanism + may create issues (but they would already be there). */ + +/* Takes an arbitrary object which must support the (character, single segment) + buffer interface and returns a pointer to a read-only memory location + usable as character based input for subsequent processing. + + Return 0 on success. buffer and buffer_len are only set in case no error + occurs. Otherwise, -1 is returned and an exception set. */ +Py_DEPRECATED(3.0) +PyAPI_FUNC(int) PyObject_AsCharBuffer(PyObject *obj, + const char **buffer, + Py_ssize_t *buffer_len); + +/* Checks whether an arbitrary object supports the (character, single segment) + buffer interface. + + Returns 1 on success, 0 on failure. */ +Py_DEPRECATED(3.0) PyAPI_FUNC(int) PyObject_CheckReadBuffer(PyObject *obj); + +/* Same as PyObject_AsCharBuffer() except that this API expects (readable, + single segment) buffer interface and returns a pointer to a read-only memory + location which can contain arbitrary data. + + 0 is returned on success. buffer and buffer_len are only set in case no + error occurs. Otherwise, -1 is returned and an exception set. */ +Py_DEPRECATED(3.0) +PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *obj, + const void **buffer, + Py_ssize_t *buffer_len); + +/* Takes an arbitrary object which must support the (writable, single segment) + buffer interface and returns a pointer to a writable memory location in + buffer of size 'buffer_len'. + + Return 0 on success. buffer and buffer_len are only set in case no error + occurs. Otherwise, -1 is returned and an exception set. */ +Py_DEPRECATED(3.0) +PyAPI_FUNC(int) PyObject_AsWriteBuffer(PyObject *obj, + void **buffer, + Py_ssize_t *buffer_len); + + /* === New Buffer API ============================================ */ /* Takes an arbitrary object and returns the result of calling @@ -327,7 +374,7 @@ PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *); /* Takes an AsyncIterable object and returns an AsyncIterator for it. This is typically a new iterator but if the argument is an AsyncIterator, this returns itself. */ -PyAPI_FUNC(PyObject *) PyObject_GetAiter(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_GetAIter(PyObject *); /* Returns non-zero if the object 'obj' provides iterator protocols, and 0 otherwise. @@ -337,7 +384,7 @@ PyAPI_FUNC(int) PyIter_Check(PyObject *); /* Returns non-zero if the object 'obj' provides AsyncIterator protocols, and 0 otherwise. This function always succeeds. */ -PyAPI_FUNC(int) PyAiter_Check(PyObject *); +PyAPI_FUNC(int) PyAIter_Check(PyObject *); /* Takes an iterator object and calls its tp_iternext slot, returning the next value. diff --git a/Include/cpython/code.h b/Include/cpython/code.h index e810eb4f816f3a..fa6408521cfee2 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -137,8 +137,8 @@ PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int); /* for internal use only */ struct _opaque { int computed_line; - char *lo_next; - char *limit; + const char *lo_next; + const char *limit; }; typedef struct _line_offsets { @@ -175,7 +175,7 @@ PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index, int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds); /** Out of process API for initializing the line number table. */ -void PyLineTable_InitAddressRange(char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range); +void PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range); /** API for traversing the line number table. */ int PyLineTable_NextAddressRange(PyCodeAddressRange *range); diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h index 6822a65cad95e8..641d7bdc48e2ef 100644 --- a/Include/cpython/dictobject.h +++ b/Include/cpython/dictobject.h @@ -22,7 +22,7 @@ typedef struct { /* If ma_values is NULL, the table is "combined": keys and values are stored in ma_keys. - If ma_values is not NULL, the table is splitted: + If ma_values is not NULL, the table is split: keys are stored in ma_keys and values are stored in ma_values */ PyObject **ma_values; } PyDictObject; diff --git a/Include/cpython/import.h b/Include/cpython/import.h index bad68f0e0980d5..dd5bbdbad78cb7 100644 --- a/Include/cpython/import.h +++ b/Include/cpython/import.h @@ -13,6 +13,9 @@ PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module); PyAPI_FUNC(void) _PyImport_AcquireLock(void); PyAPI_FUNC(int) _PyImport_ReleaseLock(void); +/* Obsolete since 3.5, will be removed in 3.11. */ +Py_DEPRECATED(3.10) PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *); + PyAPI_FUNC(int) _PyImport_FixupBuiltin( PyObject *mod, const char *name, /* UTF-8 encoded string */ diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 09f9a2947efef3..583165bee48ccc 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -1,6 +1,9 @@ #ifndef Py_PYCORECONFIG_H #define Py_PYCORECONFIG_H #ifndef Py_LIMITED_API +#ifdef __cplusplus +extern "C" { +#endif /* --- PyStatus ----------------------------------------------- */ @@ -239,5 +242,8 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStringList(PyConfig *config, See also PyConfig.orig_argv. */ PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv); +#ifdef __cplusplus +} +#endif #endif /* !Py_LIMITED_API */ #endif /* !Py_PYCORECONFIG_H */ diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index 5e57129c3b82cf..3f952456679ec9 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -185,6 +185,12 @@ Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_Create( Py_ssize_t end, const char *reason /* UTF-8 encoded string */ ); + +PyAPI_FUNC(PyObject *) _PyErr_ProgramDecodedTextObject( + PyObject *filename, + int lineno, + const char* encoding); + PyAPI_FUNC(PyObject *) _PyUnicodeTranslateError_Create( PyObject *object, Py_ssize_t start, diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 13f7a26ba12d02..5faeb3533b6013 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -2,6 +2,10 @@ # error "this header file must not be included directly" #endif +/* Py_FrozenMain is kept out of the Limited API until documented and present + in all builds of Python */ +PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv); + /* Only used by applications that embed the interpreter and need to * override the standard encoding determination mechanism */ diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index e3ccc543560849..7c995b93074f6e 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -2,8 +2,6 @@ # error "this header file must not be included directly" #endif -#include "cpython/initconfig.h" - PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); @@ -242,7 +240,7 @@ PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy( PyAPI_FUNC(int) _PyInterpreterState_SetConfig( const struct PyConfig *config); -// Get the configuration of the currrent interpreter. +// Get the configuration of the current interpreter. // The caller must hold the GIL. PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void); diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h index 56607d199ed542..754c7f4777f9c2 100644 --- a/Include/cpython/pytime.h +++ b/Include/cpython/pytime.h @@ -88,13 +88,13 @@ PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns); PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t, PyObject *obj); -/* Convert a number of seconds (Python float or int) to a timetamp. +/* Convert a number of seconds (Python float or int) to a timestamp. Raise an exception and return -1 on error, return 0 on success. */ PyAPI_FUNC(int) _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round); -/* Convert a number of milliseconds (Python float or int, 10^-3) to a timetamp. +/* Convert a number of milliseconds (Python float or int, 10^-3) to a timestamp. Raise an exception and return -1 on error, return 0 on success. */ PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 30bf994cda35be..0761f01efb42f8 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -416,7 +416,7 @@ enum PyUnicode_Kind { /* Fast check to determine whether an object is ready. Equivalent to - PyUnicode_IS_COMPACT(op) || ((PyUnicodeObject*)(op))->data.any) */ + PyUnicode_IS_COMPACT(op) || ((PyUnicodeObject*)(op))->data.any */ #define PyUnicode_IS_READY(op) (((PyASCIIObject*)op)->state.ready) @@ -834,12 +834,21 @@ PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF16( /* --- Unicode-Escape Codecs ---------------------------------------------- */ +/* Variant of PyUnicode_DecodeUnicodeEscape that supports partial decoding. */ +PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeStateful( + const char *string, /* Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ +); + /* Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape chars. */ -PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscape( +PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal( const char *string, /* Unicode-Escape encoded string */ Py_ssize_t length, /* size of string */ const char *errors, /* error handling */ + Py_ssize_t *consumed, /* bytes consumed */ const char **first_invalid_escape /* on return, points to first invalid escaped char in string. */ @@ -857,6 +866,14 @@ Py_DEPRECATED(3.3) PyAPI_FUNC(PyObject*) PyUnicode_EncodeRawUnicodeEscape( Py_ssize_t length /* Number of Py_UNICODE chars to encode */ ); +/* Variant of PyUnicode_DecodeRawUnicodeEscape that supports partial decoding. */ +PyAPI_FUNC(PyObject*) _PyUnicode_DecodeRawUnicodeEscapeStateful( + const char *string, /* Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ +); + /* --- Latin-1 Codecs ----------------------------------------------------- */ PyAPI_FUNC(PyObject*) _PyUnicode_AsLatin1String( diff --git a/Include/errcode.h b/Include/errcode.h index f2671d6c9b30b4..2e07fc2c963280 100644 --- a/Include/errcode.h +++ b/Include/errcode.h @@ -28,6 +28,7 @@ extern "C" { #define E_DECODE 22 /* Error in decoding into Unicode */ #define E_LINECONT 25 /* Unexpected characters after a line continuation */ #define E_BADSINGLE 27 /* Ill-formed single statement input */ +#define E_INTERACT_STOP 28 /* Interactive mode stopped tokenization */ #ifdef __cplusplus } diff --git a/Include/internal/pycore_blocks_output_buffer.h b/Include/internal/pycore_blocks_output_buffer.h index 22546e9a32a80b..28cf6fba4eeba2 100644 --- a/Include/internal/pycore_blocks_output_buffer.h +++ b/Include/internal/pycore_blocks_output_buffer.h @@ -57,7 +57,7 @@ static const char unable_allocate_msg[] = "Unable to allocate output buffer."; /* Block size sequence */ #define KB (1024) #define MB (1024*1024) -const Py_ssize_t BUFFER_BLOCK_SIZE[] = +static const Py_ssize_t BUFFER_BLOCK_SIZE[] = { 32*KB, 64*KB, 256*KB, 1*MB, 4*MB, 8*MB, 16*MB, 16*MB, 32*MB, 32*MB, 32*MB, 32*MB, 64*MB, 64*MB, 128*MB, 128*MB, OUTPUT_BUFFER_MAX_BLOCK_SIZE }; diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index f1e89d96b9ebb0..8ff1863dc0015f 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -3,7 +3,7 @@ #ifdef __cplusplus extern "C" { #endif - + typedef struct { PyObject *ptr; /* Cached pointer (borrowed reference) */ uint64_t globals_ver; /* ma_version of global dict */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index bfd082b588256b..4307b61ca36aaf 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -71,15 +71,9 @@ struct _Py_unicode_state { PyObject *latin1[256]; struct _Py_unicode_fs_codec fs_codec; - /* This dictionary holds all interned unicode strings. Note that references - to strings in this dictionary are *not* counted in the string's ob_refcnt. - When the interned string reaches a refcnt of 0 the string deallocation - function will delete the reference from this dictionary. - - Another way to look at this is that to say that the actual reference - count of a string is: s->ob_refcnt + (s->state ? 2 : 0) - */ - PyObject *interned; + // Unused member kept for ABI backward compatibility with Python 3.10.0: + // see bpo-46006. + PyObject *unused_interned; // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() struct _Py_unicode_ids ids; diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 9dfc8c62babadb..90d98134b8919b 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -29,6 +29,8 @@ _PyType_HasFeature(PyTypeObject *type, unsigned long feature) { extern void _PyType_InitCache(PyInterpreterState *interp); +/* Only private in Python 3.10 and 3.9.8+; public in 3.11 */ +extern PyObject *_PyType_GetQualName(PyTypeObject *type); /* Inline functions trading binary compatibility for speed: _PyObject_Init() is the fast version of PyObject_Init(), and @@ -168,7 +170,7 @@ _PyObject_IS_GC(PyObject *obj) // Fast inlined version of PyType_IS_GC() #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC) -// Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL))); +// Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL)); extern int _Py_CheckSlotResult( PyObject *obj, const char *slot_name, diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index e4e35c16ce8eda..49af17146ff1f0 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -42,7 +42,7 @@ PyAPI_FUNC(int) _PyMem_SetDefaultAllocator( fills newly allocated memory with CLEANBYTE (0xCD) and newly freed memory with DEADBYTE (0xDD). Detect also "untouchable bytes" marked with FORBIDDENBYTE (0xFD). */ -static inline int _PyMem_IsPtrFreed(void *ptr) +static inline int _PyMem_IsPtrFreed(const void *ptr) { uintptr_t value = (uintptr_t)ptr; #if SIZEOF_VOID_P == 8 diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index f3505f8949be4b..a2e520b8e25fe0 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -13,6 +13,13 @@ struct _mod; // Type defined in pycore_ast.h typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock } _Py_block_ty; +typedef enum _comprehension_type { + NoComprehension = 0, + ListComprehension = 1, + DictComprehension = 2, + SetComprehension = 3, + GeneratorExpression = 4 } _Py_comprehension_ty; + struct _symtable_entry; struct symtable { @@ -42,14 +49,14 @@ typedef struct _symtable_entry { PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ - _Py_block_ty ste_type; /* module, class, or function */ + _Py_block_ty ste_type; /* module, class or function */ int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, including free refs to globals */ unsigned ste_generator : 1; /* true if namespace is a generator */ unsigned ste_coroutine : 1; /* true if namespace is a coroutine */ - unsigned ste_comprehension : 1; /* true if namespace is a list comprehension */ + _Py_comprehension_ty ste_comprehension; /* Kind of comprehension (if any) */ unsigned ste_varargs : 1; /* true if block has varargs */ unsigned ste_varkeywords : 1; /* true if block has varkeywords */ unsigned ste_returns_value : 1; /* true if namespace uses return with diff --git a/Include/internal/pycore_traceback.h b/Include/internal/pycore_traceback.h index 4d282308769dc8..c01a47639d5e30 100644 --- a/Include/internal/pycore_traceback.h +++ b/Include/internal/pycore_traceback.h @@ -51,7 +51,7 @@ PyAPI_FUNC(void) _Py_DumpTraceback( _PyGILState_GetInterpreterStateUnsafe() in last resort. It is better to pass NULL to interp and current_tstate, the function tries - different options to retrieve these informations. + different options to retrieve this information. This function is signal safe. */ diff --git a/Include/internal/pycore_unionobject.h b/Include/internal/pycore_unionobject.h index 4d82b6fbeae8b5..9962f57610387d 100644 --- a/Include/internal/pycore_unionobject.h +++ b/Include/internal/pycore_unionobject.h @@ -8,9 +8,13 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -PyAPI_FUNC(PyObject *) _Py_Union(PyObject *args); -PyAPI_DATA(PyTypeObject) _Py_UnionType; -PyAPI_FUNC(PyObject *) _Py_union_type_or(PyObject* self, PyObject* param); +extern PyTypeObject _PyUnion_Type; +#define _PyUnion_Check(op) Py_IS_TYPE(op, &_PyUnion_Type) +extern PyObject *_Py_union_type_or(PyObject *, PyObject *); + +#define _PyGenericAlias_Check(op) PyObject_TypeCheck(op, &Py_GenericAliasType) +extern PyObject *_Py_subs_parameters(PyObject *, PyObject *, PyObject *, PyObject *); +extern PyObject *_Py_make_parameters(PyObject *); #ifdef __cplusplus } diff --git a/Include/object.h b/Include/object.h index 4c069998574b4a..61e638c34973c4 100644 --- a/Include/object.h +++ b/Include/object.h @@ -141,7 +141,9 @@ static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { - return Py_TYPE(ob) == type; + // bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const + // object. + return ob->ob_type == type; } #define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) @@ -366,18 +368,12 @@ given type object has a specified feature. /* Objects behave like an unbound method */ #define Py_TPFLAGS_METHOD_DESCRIPTOR (1UL << 17) -/* Objects support type attribute cache */ -#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18) +/* Object has up-to-date type attribute cache */ #define Py_TPFLAGS_VALID_VERSION_TAG (1UL << 19) /* Type is abstract and cannot be instantiated */ #define Py_TPFLAGS_IS_ABSTRACT (1UL << 20) -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000 -/* Type has am_send entry in tp_as_async slot */ -#define Py_TPFLAGS_HAVE_AM_SEND (1UL << 21) -#endif - // This undocumented flag gives certain built-ins their unique pattern-matching // behavior, which allows a single positional subpattern to match against the // subject itself (rather than a mapped attribute on it): @@ -395,19 +391,23 @@ given type object has a specified feature. #define Py_TPFLAGS_DEFAULT ( \ Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \ - Py_TPFLAGS_HAVE_VERSION_TAG | \ 0) -/* NOTE: The following flags reuse lower bits (removed as part of the +/* NOTE: Some of the following flags reuse lower bits (removed as part of the * Python 3.0 transition). */ -/* The following flag is kept for compatibility. Starting with 3.8, - * binary compatibility of C extensions across feature releases of - * Python is not supported anymore, except when using the stable ABI. +/* The following flags are kept for compatibility; in previous + * versions they indicated presence of newer tp_* fields on the + * type struct. + * Starting with 3.8, binary compatibility of C extensions across + * feature releases of Python is not supported anymore (except when + * using the stable ABI, in which all classes are created dynamically, + * using the interpreter's memory layout.) + * Note that older extensions using the stable ABI set these flags, + * so the bits must not be repurposed. */ - -/* Type structure has tp_finalize member (3.4) */ #define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0) +#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18) /* @@ -590,7 +590,7 @@ static inline PyObject* _Py_XNewRef(PyObject *obj) } // Py_NewRef() and Py_XNewRef() are exported as functions for the stable ABI. -// Names overriden with macros by static inline functions for best +// Names overridden with macros by static inline functions for best // performances. #define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) #define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 0a29562e313b3d..8a6fec39f6e2e8 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 10 -#define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 7 +#define PY_MICRO_VERSION 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.10.0a7+" +#define PY_VERSION "3.10.1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 783fcb455eb528..2df7fe6e3c83d6 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -31,9 +31,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN Py_Exit(int); /* Bootstrap __main__ (defined in Modules/main.c) */ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); - -PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv); - PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); /* In pathconfig.c */ diff --git a/LICENSE b/LICENSE index 473861da1be7c5..02a5145f0e3852 100644 --- a/LICENSE +++ b/LICENSE @@ -84,7 +84,7 @@ analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation; +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. @@ -191,9 +191,9 @@ version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the Internet using the following +Python 1.6.1 may be located on the internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the Internet +Agreement may also be obtained from a proxy server on the internet using the following URL: http://hdl.handle.net/1895.22/1013". 3. In the event Licensee prepares a derivative work that is based on diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index d92b848e9436fb..87a9cd2d46de99 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -426,22 +426,16 @@ class _CallableGenericAlias(GenericAlias): __slots__ = () def __new__(cls, origin, args): - return cls.__create_ga(origin, args) - - @classmethod - def __create_ga(cls, origin, args): - if not isinstance(args, tuple) or len(args) != 2: + if not (isinstance(args, tuple) and len(args) == 2): raise TypeError( "Callable must be used as Callable[[arg, ...], result].") t_args, t_result = args - if isinstance(t_args, (list, tuple)): - ga_args = tuple(t_args) + (t_result,) - # This relaxes what t_args can be on purpose to allow things like - # PEP 612 ParamSpec. Responsibility for whether a user is using - # Callable[...] properly is deferred to static type checkers. - else: - ga_args = args - return super().__new__(cls, origin, ga_args) + if isinstance(t_args, list): + args = (*t_args, t_result) + elif not _is_param_expr(t_args): + raise TypeError(f"Expected a list of types, an ellipsis, " + f"ParamSpec, or Concatenate. Got {t_args}") + return super().__new__(cls, origin, args) @property def __parameters__(self): @@ -456,7 +450,7 @@ def __parameters__(self): return tuple(dict.fromkeys(params)) def __repr__(self): - if _has_special_args(self.__args__): + if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]): return super().__repr__() return (f'collections.abc.Callable' f'[[{", ".join([_type_repr(a) for a in self.__args__[:-1]])}], ' @@ -464,7 +458,7 @@ def __repr__(self): def __reduce__(self): args = self.__args__ - if not _has_special_args(args): + if not (len(args) == 2 and _is_param_expr(args[0])): args = list(args[:-1]), args[-1] return _CallableGenericAlias, (Callable, args) @@ -478,12 +472,12 @@ def __getitem__(self, item): # then X[int, str] == X[[int, str]]. param_len = len(self.__parameters__) if param_len == 0: - raise TypeError(f'There are no type or parameter specification' - f'variables left in {self}') - if (param_len == 1 - and isinstance(item, (tuple, list)) - and len(item) > 1) or not isinstance(item, tuple): + raise TypeError(f'{self} is not a generic class') + if not isinstance(item, tuple): item = (item,) + if (param_len == 1 and _is_param_expr(self.__parameters__[0]) + and item and not _is_param_expr(item[0])): + item = (list(item),) item_len = len(item) if item_len != param_len: raise TypeError(f'Too {"many" if item_len > param_len else "few"}' @@ -493,7 +487,13 @@ def __getitem__(self, item): new_args = [] for arg in self.__args__: if _is_typevarlike(arg): - arg = subst[arg] + if _is_param_expr(arg): + arg = subst[arg] + if not _is_param_expr(arg): + raise TypeError(f"Expected a list of types, an ellipsis, " + f"ParamSpec, or Concatenate. Got {arg}") + else: + arg = subst[arg] # Looks like a GenericAlias elif hasattr(arg, '__parameters__') and isinstance(arg.__parameters__, tuple): subparams = arg.__parameters__ @@ -503,32 +503,31 @@ def __getitem__(self, item): new_args.append(arg) # args[0] occurs due to things like Z[[int, str, bool]] from PEP 612 - if not isinstance(new_args[0], (tuple, list)): + if not isinstance(new_args[0], list): t_result = new_args[-1] t_args = new_args[:-1] new_args = (t_args, t_result) return _CallableGenericAlias(Callable, tuple(new_args)) + def _is_typevarlike(arg): obj = type(arg) # looks like a TypeVar/ParamSpec return (obj.__module__ == 'typing' and obj.__name__ in {'ParamSpec', 'TypeVar'}) -def _has_special_args(args): - """Checks if args[0] matches either ``...``, ``ParamSpec`` or +def _is_param_expr(obj): + """Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or ``_ConcatenateGenericAlias`` from typing.py """ - if len(args) != 2: - return False - obj = args[0] if obj is Ellipsis: return True + if isinstance(obj, list): + return True obj = type(obj) names = ('ParamSpec', '_ConcatenateGenericAlias') return obj.__module__ == 'typing' and any(obj.__name__ == name for name in names) - def _type_repr(obj): """Return the repr() of an object, special-casing types (internal helper). @@ -696,6 +695,7 @@ def _hash(self): hx = hash(x) h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 h &= MASK + h ^= (h >> 11) ^ (h >> 25) h = h * 69069 + 907133923 h &= MASK if h > MAX: diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py index b7145ee069fa32..aa66c8b9f4189f 100644 --- a/Lib/_osx_support.py +++ b/Lib/_osx_support.py @@ -428,10 +428,9 @@ def compiler_fixup(compiler_so, cc_args): break if sysroot and not os.path.isdir(sysroot): - from distutils import log - log.warn("Compiling with an SDK that doesn't seem to exist: %s", - sysroot) - log.warn("Please check your Xcode installation") + sys.stderr.write(f"Compiling with an SDK that doesn't seem to exist: {sysroot}\n") + sys.stderr.write("Please check your Xcode installation\n") + sys.stderr.flush() return compiler_so @@ -482,7 +481,7 @@ def customize_compiler(_config_vars): This customization is performed when the first extension module build is requested - in distutils.sysconfig.customize_compiler). + in distutils.sysconfig.customize_compiler. """ # Find a compiler to use for extension module builds diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index ff23322ed5603e..3d6cece9676c93 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -951,7 +951,7 @@ def __hash__(self): if self.is_snan(): raise TypeError('Cannot hash a signaling NaN value.') elif self.is_nan(): - return super().__hash__() + return object.__hash__(self) else: if self._sign: return -_PyHASH_INF diff --git a/Lib/_weakrefset.py b/Lib/_weakrefset.py index b267780f0ced73..2a27684324d80a 100644 --- a/Lib/_weakrefset.py +++ b/Lib/_weakrefset.py @@ -51,10 +51,14 @@ def _remove(item, selfref=ref(self)): self.update(data) def _commit_removals(self): - l = self._pending_removals + pop = self._pending_removals.pop discard = self.data.discard - while l: - discard(l.pop()) + while True: + try: + item = pop() + except IndexError: + return + discard(item) def __iter__(self): with _IterationGuard(self): diff --git a/Lib/abc.py b/Lib/abc.py index 276ef9a2cd4850..3c552cebb4226c 100644 --- a/Lib/abc.py +++ b/Lib/abc.py @@ -28,7 +28,14 @@ def my_abstract_method(self, ...): class abstractclassmethod(classmethod): """A decorator indicating abstract classmethods. - Deprecated, use 'classmethod' with 'abstractmethod' instead. + Deprecated, use 'classmethod' with 'abstractmethod' instead: + + class C(ABC): + @classmethod + @abstractmethod + def my_abstract_classmethod(cls, ...): + ... + """ __isabstractmethod__ = True @@ -41,7 +48,14 @@ def __init__(self, callable): class abstractstaticmethod(staticmethod): """A decorator indicating abstract staticmethods. - Deprecated, use 'staticmethod' with 'abstractmethod' instead. + Deprecated, use 'staticmethod' with 'abstractmethod' instead: + + class C(ABC): + @staticmethod + @abstractmethod + def my_abstract_staticmethod(...): + ... + """ __isabstractmethod__ = True @@ -54,7 +68,14 @@ def __init__(self, callable): class abstractproperty(property): """A decorator indicating abstract properties. - Deprecated, use 'property' with 'abstractmethod' instead. + Deprecated, use 'property' with 'abstractmethod' instead: + + class C(ABC): + @property + @abstractmethod + def my_abstract_property(self): + ... + """ __isabstractmethod__ = True diff --git a/Lib/argparse.py b/Lib/argparse.py index 8a12dea7668799..e177e4fe034d32 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -392,6 +392,9 @@ def _format_actions_usage(self, actions, groups): group_actions = set() inserts = {} for group in groups: + if not group._group_actions: + raise ValueError(f'empty group {group}') + try: start = actions.index(group._group_actions[0]) except ValueError: @@ -526,12 +529,13 @@ def _format_action(self, action): parts = [action_header] # if there was help for the action, add lines of help text - if action.help: + if action.help and action.help.strip(): help_text = self._expand_help(action) - help_lines = self._split_lines(help_text, help_width) - parts.append('%*s%s\n' % (indent_first, '', help_lines[0])) - for line in help_lines[1:]: - parts.append('%*s%s\n' % (help_position, '', line)) + if help_text: + help_lines = self._split_lines(help_text, help_width) + parts.append('%*s%s\n' % (indent_first, '', help_lines[0])) + for line in help_lines[1:]: + parts.append('%*s%s\n' % (help_position, '', line)) # or add a newline if the description doesn't end with one elif not action_header.endswith('\n'): @@ -727,6 +731,8 @@ def _get_action_name(argument): return argument.metavar elif argument.dest not in (None, SUPPRESS): return argument.dest + elif argument.choices: + return '{' + ','.join(argument.choices) + '}' else: return None @@ -873,7 +879,7 @@ def __init__(self, _option_strings.append(option_string) if help is not None and default is not None: - help += f" (default: {default})" + help += " (default: %(default)s)" super().__init__( option_strings=_option_strings, @@ -1666,7 +1672,8 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): """Object for parsing command line strings into Python objects. Keyword Arguments: - - prog -- The name of the program (default: sys.argv[0]) + - prog -- The name of the program (default: + ``os.path.basename(sys.argv[0])``) - usage -- A usage message (default: auto-generated from arguments) - description -- A description of what the program does - epilog -- Text following the argument descriptions diff --git a/Lib/ast.py b/Lib/ast.py index 0c53e5c5712f5e..f4d2f6e42c022b 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -27,7 +27,7 @@ import sys from _ast import * from contextlib import contextmanager, nullcontext -from enum import IntEnum, auto, _simple_enum +from enum import IntEnum, auto def parse(source, filename='', mode='exec', *, @@ -636,8 +636,7 @@ class Param(expr_context): # We unparse those infinities to INFSTR. _INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1) -@_simple_enum(IntEnum) -class _Precedence: +class _Precedence(IntEnum): """Precedence table that originated from python grammar.""" TUPLE = auto() @@ -1455,9 +1454,9 @@ def visit_Call(self, node): def visit_Subscript(self, node): def is_simple_tuple(slice_value): - # when unparsing a non-empty tuple, the parantheses can be safely + # when unparsing a non-empty tuple, the parentheses can be safely # omitted if there aren't any elements that explicitly requires - # parantheses (such as starred expressions). + # parentheses (such as starred expressions). return ( isinstance(slice_value, Tuple) and slice_value.elts diff --git a/Lib/asynchat.py b/Lib/asynchat.py index f4ba361bd4a3ef..de26ffa648ffec 100644 --- a/Lib/asynchat.py +++ b/Lib/asynchat.py @@ -48,6 +48,14 @@ import asyncore from collections import deque +from warnings import warn +warn( + 'The asynchat module is deprecated. ' + 'The recommended replacement is asyncio', + DeprecationWarning, + stacklevel=2) + + class async_chat(asyncore.dispatcher): """This is an abstract class. You must derive from this class, and add diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index f789635e0f893a..f726e91e889b74 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -972,7 +972,7 @@ async def create_connection( happy_eyeballs_delay=None, interleave=None): """Connect to a TCP server. - Create a streaming transport connection to a given Internet host and + 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. diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index b966ad26bf467b..5ab1acc41bf31a 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -258,13 +258,13 @@ def _timer_handle_cancelled(self, handle): """Notification that a TimerHandle has been cancelled.""" raise NotImplementedError - def call_soon(self, callback, *args): - return self.call_later(0, callback, *args) + def call_soon(self, callback, *args, context=None): + return self.call_later(0, callback, *args, context=context) - def call_later(self, delay, callback, *args): + def call_later(self, delay, callback, *args, context=None): raise NotImplementedError - def call_at(self, when, callback, *args): + def call_at(self, when, callback, *args, context=None): raise NotImplementedError def time(self): @@ -280,7 +280,7 @@ def create_task(self, coro, *, name=None): # Methods for interacting with threads. - def call_soon_threadsafe(self, callback, *args): + def call_soon_threadsafe(self, callback, *args, context=None): raise NotImplementedError def run_in_executor(self, executor, func, *args): @@ -479,7 +479,7 @@ async def connect_read_pipe(self, protocol_factory, pipe): # The reason to accept file-like object instead of just file descriptor # is: we need to own pipe and close it at transport finishing # Can got complicated errors if pass f.fileno(), - # close fd in pipe transport then close f and vise versa. + # close fd in pipe transport then close f and vice versa. raise NotImplementedError async def connect_write_pipe(self, protocol_factory, pipe): @@ -492,7 +492,7 @@ async def connect_write_pipe(self, protocol_factory, pipe): # The reason to accept file-like object instead of just file descriptor # is: we need to own pipe and close it at transport finishing # Can got complicated errors if pass f.fileno(), - # close fd in pipe transport then close f and vise versa. + # close fd in pipe transport then close f and vice versa. raise NotImplementedError async def subprocess_shell(self, protocol_factory, cmd, *, diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index a7453fb1c77287..4fef64e3921e17 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -230,8 +230,6 @@ def __init__(self, lock=None, *, loop=mixins._marker): super().__init__(loop=loop) if lock is None: lock = Lock() - elif lock._loop is not self._get_loop(): - raise ValueError("loop argument must agree with lock") self._lock = lock # Export the lock's locked(), acquire() and release() methods. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 9a9d0d6e3cc269..53eef84427be10 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -415,11 +415,9 @@ async def wait_for(fut, timeout): await _cancel_and_wait(fut, loop=loop) try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() waiter = loop.create_future() timeout_handle = loop.call_later(timeout, _release_waiter, waiter) @@ -455,11 +453,9 @@ async def wait_for(fut, timeout): # exception, we should re-raise it # See https://bugs.python.org/issue40607 try: - fut.result() + return fut.result() except exceptions.CancelledError as exc: raise exceptions.TimeoutError() from exc - else: - raise exceptions.TimeoutError() finally: timeout_handle.cancel() diff --git a/Lib/asyncio/threads.py b/Lib/asyncio/threads.py index 34b7513a420902..db048a8231de16 100644 --- a/Lib/asyncio/threads.py +++ b/Lib/asyncio/threads.py @@ -13,7 +13,7 @@ async def to_thread(func, /, *args, **kwargs): """Asynchronously run function *func* in a separate thread. Any *args and **kwargs supplied for this function are directly passed - to *func*. Also, the current :class:`contextvars.Context` is propogated, + to *func*. Also, the current :class:`contextvars.Context` is propagated, allowing context variables from the main thread to be accessed in the separate thread. diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index a55b3a375fa22d..c88b818de62a6f 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -126,7 +126,7 @@ def add_signal_handler(self, sig, callback, *args): logger.info('set_wakeup_fd(-1) failed: %s', nexc) if exc.errno == errno.EINVAL: - raise RuntimeError(f'sig {sig:d} cannot be caught') + raise RuntimeError(f'sig {sig} cannot be caught') else: raise @@ -160,7 +160,7 @@ def remove_signal_handler(self, sig): signal.signal(sig, handler) except OSError as exc: if exc.errno == errno.EINVAL: - raise RuntimeError(f'sig {sig:d} cannot be caught') + raise RuntimeError(f'sig {sig} cannot be caught') else: raise @@ -1379,7 +1379,7 @@ def add_child_handler(self, pid, callback, *args): def remove_child_handler(self, pid): # asyncio never calls remove_child_handler() !!! # The method is no-op but is implemented because - # abstract base classe requires it + # abstract base classes require it. return True def attach_loop(self, loop): diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index 5e7cd795895d65..da81ab435b9a6f 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -1,5 +1,10 @@ """Selector and proactor event loops for Windows.""" +import sys + +if sys.platform != 'win32': # pragma: no cover + raise ImportError('win32 only') + import _overlapped import _winapi import errno diff --git a/Lib/asyncore.py b/Lib/asyncore.py index eeea48888616d7..b1eea4bf652118 100644 --- a/Lib/asyncore.py +++ b/Lib/asyncore.py @@ -57,6 +57,13 @@ ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \ errorcode +warnings.warn( + 'The asyncore module is deprecated. ' + 'The recommended replacement is asyncio', + DeprecationWarning, + stacklevel=2) + + _DISCONNECTED = frozenset({ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE, EBADF}) diff --git a/Lib/bdb.py b/Lib/bdb.py index abb50c092e69bb..75d6113576372e 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -119,7 +119,7 @@ def dispatch_call(self, frame, arg): """Invoke user function and return trace function for call event. If the debugger stops on this function call, invoke - self.user_call(). Raise BbdQuit if self.quitting is set. + self.user_call(). Raise BdbQuit if self.quitting is set. Return self.trace_dispatch to continue tracing in this scope. """ # XXX 'arg' is no longer used diff --git a/Lib/bz2.py b/Lib/bz2.py index a2c588e7487f3d..fabe4f73c8d808 100644 --- a/Lib/bz2.py +++ b/Lib/bz2.py @@ -197,10 +197,6 @@ def readline(self, size=-1): self._check_can_read() return self._buffer.readline(size) - def __iter__(self): - self._check_can_read() - return self._buffer.__iter__() - def readlines(self, size=-1): """Read a list of lines of uncompressed bytes from the file. @@ -219,14 +215,22 @@ def write(self, data): """Write a byte string to the file. Returns the number of uncompressed bytes written, which is - always len(data). Note that due to buffering, the file on disk - may not reflect the data written until close() is called. + always the length of data in bytes. Note that due to buffering, + the file on disk may not reflect the data written until close() + is called. """ self._check_can_write() + if isinstance(data, (bytes, bytearray)): + length = len(data) + else: + # accept any data that supports the buffer protocol + data = memoryview(data) + length = data.nbytes + compressed = self._compressor.compress(data) self._fp.write(compressed) - self._pos += len(data) - return len(data) + self._pos += length + return length def writelines(self, seq): """Write a sequence of byte strings to the file. diff --git a/Lib/cgitb.py b/Lib/cgitb.py index 4f81271be3ca78..17ddda376884df 100644 --- a/Lib/cgitb.py +++ b/Lib/cgitb.py @@ -181,8 +181,8 @@ def reader(lnum=[lnum]): diff --git a/Lib/compileall.py b/Lib/compileall.py index 61b4c5c0af1ad6..3755e76ba813f5 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -221,8 +221,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, if not force: try: mtime = int(os.stat(fullname).st_mtime) - expect = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, - 0, mtime) + expect = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, + 0, mtime & 0xFFFF_FFFF) for cfile in opt_cfiles.values(): with open(cfile, 'rb') as chandle: actual = chandle.read(12) @@ -254,9 +254,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, else: print('*** ', end='') # escape non-printable characters in msg - msg = err.msg.encode(sys.stdout.encoding, - errors='backslashreplace') - msg = msg.decode(sys.stdout.encoding) + encoding = sys.stdout.encoding or sys.getdefaultencoding() + msg = err.msg.encode(encoding, errors='backslashreplace').decode(encoding) print(msg) except (SyntaxError, UnicodeError, OSError) as e: success = False @@ -368,9 +367,9 @@ def main(): 'environment variable is set, and ' '"timestamp" otherwise.')) parser.add_argument('-o', action='append', type=int, dest='opt_levels', - help=('Optimization levels to run compilation with.' - 'Default is -1 which uses optimization level of' - 'Python interpreter itself (specified by -O).')) + help=('Optimization levels to run compilation with. ' + 'Default is -1 which uses the optimization level ' + 'of the Python interpreter itself (see -O).')) parser.add_argument('-e', metavar='DIR', dest='limit_sl_dest', help='Ignore symlinks pointing outsite of the DIR') parser.add_argument('--hardlink-dupes', action='store_true', diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 6095026cb278b9..5c00f2edbe5482 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -284,13 +284,14 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): A named 2-tuple of sets. The first set, named 'done', contains the futures that completed (is finished or cancelled) before the wait completed. The second set, named 'not_done', contains uncompleted - futures. + futures. Duplicate futures given to *fs* are removed and will be + returned only once. """ + fs = set(fs) with _AcquireFutures(fs): - done = set(f for f in fs - if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]) - not_done = set(fs) - done - + done = {f for f in fs + if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]} + not_done = fs - done if (return_when == FIRST_COMPLETED) and done: return DoneAndNotDoneFutures(done, not_done) elif (return_when == FIRST_EXCEPTION) and done: @@ -309,7 +310,7 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): f._waiters.remove(waiter) done.update(waiter.finished_futures) - return DoneAndNotDoneFutures(done, set(fs) - done) + return DoneAndNotDoneFutures(done, fs - done) class Future(object): """Represents the result of an asynchronous computation.""" diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 764719859f7cea..6ee2ce626e4567 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -373,7 +373,7 @@ def wait_result_broken_or_wakeup(self): assert not self.thread_wakeup._closed wakeup_reader = self.thread_wakeup._reader readers = [result_reader, wakeup_reader] - worker_sentinels = [p.sentinel for p in self.processes.values()] + worker_sentinels = [p.sentinel for p in list(self.processes.values())] ready = mp.connection.wait(readers + worker_sentinels) cause = None diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index b7a2cac7f57015..51c942f51abd37 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -36,6 +36,12 @@ def _python_exit(): # See bpo-39812 for context. threading._register_atexit(_python_exit) +# At fork, reinitialize the `_global_shutdown_lock` lock in the child process +if hasattr(os, 'register_at_fork'): + os.register_at_fork(before=_global_shutdown_lock.acquire, + after_in_child=_global_shutdown_lock._at_fork_reinit, + after_in_parent=_global_shutdown_lock.release) + class _WorkItem(object): def __init__(self, future, fn, args, kwargs): diff --git a/Lib/configparser.py b/Lib/configparser.py index 3b4cb5e6b2407f..042a5c74b696fb 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -563,7 +563,7 @@ class RawConfigParser(MutableMapping): # Regular expressions for parsing section headers and options _SECT_TMPL = r""" \[ # [ - (?P
    [^]]+) # very permissive! + (?P
    .+) # very permissive! \] # ] """ _OPT_TMPL = r""" @@ -908,6 +908,9 @@ def write(self, fp, space_around_delimiters=True): If `space_around_delimiters' is True (the default), delimiters between keys and values are surrounded by spaces. + + Please note that comments in the original configuration file are not + preserved when writing the configuration back. """ if space_around_delimiters: d = " {} ".format(self._delimiters[0]) @@ -1006,7 +1009,7 @@ def _read(self, fp, fpname): Configuration files may include comments, prefixed by specific characters (`#' and `;' by default). Comments may appear on their own in an otherwise empty line or may be entered in lines holding values or - section names. + section names. Please note that comments get stripped off when reading configuration files. """ elements_added = set() cursect = None # None, or a dictionary diff --git a/Lib/contextlib.py b/Lib/contextlib.py index eb5946145b47ee..c63a8492e2d3d5 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -113,18 +113,20 @@ def __init__(self, func, args, kwds): # for the class instead. # See http://bugs.python.org/issue19404 for more details. - -class _GeneratorContextManager(_GeneratorContextManagerBase, - AbstractContextManager, - ContextDecorator): - """Helper for @contextmanager decorator.""" - def _recreate_cm(self): - # _GCM instances are one-shot context managers, so the + # _GCMB instances are one-shot context managers, so the # CM must be recreated each time a decorated function is # called return self.__class__(self.func, self.args, self.kwds) + +class _GeneratorContextManager( + _GeneratorContextManagerBase, + AbstractContextManager, + ContextDecorator, +): + """Helper for @contextmanager decorator.""" + def __enter__(self): # do not keep args and kwds alive unnecessarily # they are only needed for recreation, which is not possible anymore @@ -134,8 +136,8 @@ def __enter__(self): except StopIteration: raise RuntimeError("generator didn't yield") from None - def __exit__(self, type, value, traceback): - if type is None: + def __exit__(self, typ, value, traceback): + if typ is None: try: next(self.gen) except StopIteration: @@ -146,9 +148,9 @@ def __exit__(self, type, value, traceback): if value is None: # Need to force instantiation so we can reliably # tell if we get the same exception back - value = type() + value = typ() try: - self.gen.throw(type, value, traceback) + self.gen.throw(typ, value, traceback) except StopIteration as exc: # Suppress StopIteration *unless* it's the same exception that # was passed to throw(). This prevents a StopIteration @@ -158,81 +160,93 @@ def __exit__(self, type, value, traceback): # Don't re-raise the passed in exception. (issue27122) if exc is value: return False - # Likewise, avoid suppressing if a StopIteration exception + # Avoid suppressing if a StopIteration exception # was passed to throw() and later wrapped into a RuntimeError - # (see PEP 479). - if type is StopIteration and exc.__cause__ is value: + # (see PEP 479 for sync generators; async generators also + # have this behavior). But do this only if the exception wrapped + # by the RuntimeError is actually Stop(Async)Iteration (see + # issue29692). + if ( + isinstance(value, StopIteration) + and exc.__cause__ is value + ): return False raise - except: + except BaseException as exc: # only re-raise if it's *not* the exception that was # passed to throw(), because __exit__() must not raise # an exception unless __exit__() itself failed. But throw() # has to raise the exception to signal propagation, so this # fixes the impedance mismatch between the throw() protocol # and the __exit__() protocol. - # - # This cannot use 'except BaseException as exc' (as in the - # async implementation) to maintain compatibility with - # Python 2, where old-style class exceptions are not caught - # by 'except BaseException'. - if sys.exc_info()[1] is value: - return False - raise + if exc is not value: + raise + return False raise RuntimeError("generator didn't stop after throw()") - -class _AsyncGeneratorContextManager(_GeneratorContextManagerBase, - AbstractAsyncContextManager, - AsyncContextDecorator): - """Helper for @asynccontextmanager.""" - - def _recreate_cm(self): - # _AGCM instances are one-shot context managers, so the - # ACM must be recreated each time a decorated function is - # called - return self.__class__(self.func, self.args, self.kwds) +class _AsyncGeneratorContextManager( + _GeneratorContextManagerBase, + AbstractAsyncContextManager, + AsyncContextDecorator, +): + """Helper for @asynccontextmanager decorator.""" async def __aenter__(self): + # do not keep args and kwds alive unnecessarily + # they are only needed for recreation, which is not possible anymore + del self.args, self.kwds, self.func try: - return await self.gen.__anext__() + return await anext(self.gen) except StopAsyncIteration: raise RuntimeError("generator didn't yield") from None async def __aexit__(self, typ, value, traceback): if typ is None: try: - await self.gen.__anext__() + await anext(self.gen) except StopAsyncIteration: - return + return False else: raise RuntimeError("generator didn't stop") else: if value is None: + # Need to force instantiation so we can reliably + # tell if we get the same exception back value = typ() - # See _GeneratorContextManager.__exit__ for comments on subtleties - # in this implementation try: await self.gen.athrow(typ, value, traceback) - raise RuntimeError("generator didn't stop after athrow()") except StopAsyncIteration as exc: + # Suppress StopIteration *unless* it's the same exception that + # was passed to throw(). This prevents a StopIteration + # raised inside the "with" statement from being suppressed. return exc is not value except RuntimeError as exc: + # Don't re-raise the passed in exception. (issue27122) if exc is value: return False - # Avoid suppressing if a StopIteration exception - # was passed to throw() and later wrapped into a RuntimeError + # Avoid suppressing if a Stop(Async)Iteration exception + # was passed to athrow() and later wrapped into a RuntimeError # (see PEP 479 for sync generators; async generators also # have this behavior). But do this only if the exception wrapped # by the RuntimeError is actully Stop(Async)Iteration (see # issue29692). - if isinstance(value, (StopIteration, StopAsyncIteration)): - if exc.__cause__ is value: - return False + if ( + isinstance(value, (StopIteration, StopAsyncIteration)) + and exc.__cause__ is value + ): + return False raise except BaseException as exc: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise + # an exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so this + # fixes the impedance mismatch between the throw() protocol + # and the __exit__() protocol. if exc is not value: raise + return False + raise RuntimeError("generator didn't stop after athrow()") def contextmanager(func): @@ -526,10 +540,10 @@ def _fix_exception_context(new_exc, old_exc): # Context may not be correct, so find the end of the chain while 1: exc_context = new_exc.__context__ - if exc_context is old_exc: + if exc_context is None or exc_context is old_exc: # Context is already set correctly (see issue 20317) return - if exc_context is None or exc_context is frame_exc: + if exc_context is frame_exc: break new_exc = exc_context # Change the end of the chain to point to the exception @@ -660,10 +674,10 @@ def _fix_exception_context(new_exc, old_exc): # Context may not be correct, so find the end of the chain while 1: exc_context = new_exc.__context__ - if exc_context is old_exc: + if exc_context is None or exc_context is old_exc: # Context is already set correctly (see issue 20317) return - if exc_context is None or exc_context is frame_exc: + if exc_context is frame_exc: break new_exc = exc_context # Change the end of the chain to point to the exception diff --git a/Lib/copy.py b/Lib/copy.py index dd41c54dffe1d7..69bac980be2054 100644 --- a/Lib/copy.py +++ b/Lib/copy.py @@ -39,8 +39,8 @@ class instances). set of components copied This version does not copy types like module, class, function, method, -nor stack trace, stack frame, nor file, socket, window, nor array, nor -any similar types. +nor stack trace, stack frame, nor file, socket, window, nor any +similar types. Classes can use the same interfaces to control copying that they use to control pickling: they can define methods called __getinitargs__(), diff --git a/Lib/copyreg.py b/Lib/copyreg.py index 7ab8c128eb0445..356db6f083e39c 100644 --- a/Lib/copyreg.py +++ b/Lib/copyreg.py @@ -36,6 +36,12 @@ def pickle_complex(c): pickle(complex, pickle_complex, complex) +def pickle_union(obj): + import functools, operator + return functools.reduce, (operator.or_, obj.__args__) + +pickle(type(int | str), pickle_union) + # Support for pickling new-style objects def _reconstructor(cls, base, state): diff --git a/Lib/csv.py b/Lib/csv.py index dc85077f3ec663..bb3ee269ae7931 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -409,14 +409,10 @@ def has_header(self, sample): continue # skip rows that have irregular number of columns for col in list(columnTypes.keys()): - - for thisType in [int, float, complex]: - try: - thisType(row[col]) - break - except (ValueError, OverflowError): - pass - else: + thisType = complex + try: + thisType(row[col]) + except (ValueError, OverflowError): # fallback to length of string thisType = len(row[col]) diff --git a/Lib/ctypes/_aix.py b/Lib/ctypes/_aix.py index 190cac6507edef..fc3e95cbcc88a5 100644 --- a/Lib/ctypes/_aix.py +++ b/Lib/ctypes/_aix.py @@ -163,7 +163,7 @@ def get_legacy(members): return member else: # 32-bit legacy names - both shr.o and shr4.o exist. - # shr.o is the preffered name so we look for shr.o first + # shr.o is the preferred name so we look for shr.o first # i.e., shr4.o is returned only when shr.o does not exist for name in ['shr.o', 'shr4.o']: member = get_one_match(re.escape(name), members) @@ -282,7 +282,7 @@ def find_shared(paths, name): if path.exists(archive): members = get_shared(get_ld_headers(archive)) member = get_member(re.escape(name), members) - if member != None: + if member is not None: return (base, member) else: return (None, None) @@ -307,7 +307,7 @@ def find_library(name): libpaths = get_libpaths() (base, member) = find_shared(libpaths, name) - if base != None: + if base is not None: return f"{base}({member})" # To get here, a member in an archive has not been found diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py index 68b618a05f436b..992b8c4da3a776 100644 --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -233,69 +233,6 @@ class X(Structure): else: self.assertEqual(sizeof(X), sizeof(c_int) * 2) - @unittest.skipIf(os.name == 'nt', reason='Posix only') - def test_packed_posix(self): - test_cases = { - ( - ("a", c_uint8, 4), - ("b", c_uint8, 4), - ): 1, - ( - ("a", c_uint8, 1), - ("b", c_uint16, 1), - ("c", c_uint32, 1), - ("d", c_uint64, 1), - ): 1, - ( - ("a", c_uint8, 8), - ("b", c_uint16, 1), - ("c", c_uint32, 1), - ("d", c_uint64, 1), - ): 2, - ( - ("a", c_uint32, 9), - ("b", c_uint16, 10), - ("c", c_uint32, 25), - ("d", c_uint64, 1), - ): 6, - ( - ("a", c_uint32, 9), - ("b", c_uint16, 10), - ("c", c_uint32, 25), - ("d", c_uint64, 5), - ): 7, - ( - ("a", c_uint16), - ("b", c_uint16, 9), - ("c", c_uint16, 1), - ("d", c_uint16, 1), - ("e", c_uint16, 1), - ("f", c_uint16, 1), - ("g", c_uint16, 3), - ("h", c_uint32, 10), - ("i", c_uint32, 20), - ("j", c_uint32, 2), - ): 8, - ( - ("a", c_uint16, 9), - ("b", c_uint16, 10), - ("d", c_uint16), - ("c", c_uint8, 8), - ): 6, - ( - ("a", c_uint32, 9), - ("b", c_uint32), - ("c", c_uint32, 8), - ): 7, - } - - for fields, size in test_cases.items(): - with self.subTest(fields=fields): - class X(Structure): - _pack_ = 1 - _fields_ = list(fields) - self.assertEqual(sizeof(X), size) - def test_anon_bitfields(self): # anonymous bit-fields gave a strange error message class X(Structure): diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py index 75628924206bce..bdb044e594a2cf 100644 --- a/Lib/ctypes/test/test_functions.py +++ b/Lib/ctypes/test/test_functions.py @@ -35,34 +35,24 @@ def test_mro(self): # wasn't checked, and it even crashed Python. # Found by Greg Chapman. - try: + with self.assertRaises(TypeError): class X(object, Array): _length_ = 5 _type_ = "i" - except TypeError: - pass - from _ctypes import _Pointer - try: + with self.assertRaises(TypeError): class X(object, _Pointer): pass - except TypeError: - pass from _ctypes import _SimpleCData - try: + with self.assertRaises(TypeError): class X(object, _SimpleCData): _type_ = "i" - except TypeError: - pass - try: + with self.assertRaises(TypeError): class X(object, Structure): _fields_ = [] - except TypeError: - pass - @need_symbol('c_wchar') def test_wchar_parm(self): @@ -389,7 +379,7 @@ class S8I(Structure): (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) def test_sf1651235(self): - # see http://www.python.org/sf/1651235 + # see https://www.python.org/sf/1651235 proto = CFUNCTYPE(c_int, RECT, POINT) def callback(*args): diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 7b930f92c70cfb..ea892277c4eae9 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -93,7 +93,7 @@ def test_1703286_A(self): # NOT fit into a 32-bit integer. FreeLibrary must be able # to accept this address. - # These are tests for http://www.python.org/sf/1703286 + # These are tests for https://www.python.org/sf/1703286 handle = LoadLibrary("advapi32") FreeLibrary(handle) diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index 245cd94c5cdd9e..97ad2b8ed8a50d 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -443,7 +443,7 @@ def __del__(self): s = Test(1, 2, 3) # Test the StructUnionType_paramfunc() code path which copies the - # structure: if the stucture is larger than sizeof(void*). + # structure: if the structure is larger than sizeof(void*). self.assertGreater(sizeof(s), sizeof(c_void_p)) dll = CDLL(_ctypes_test.__file__) @@ -451,7 +451,7 @@ def __del__(self): func.argtypes = (Test,) func.restype = None func(s) - # bpo-37140: Passing the structure by refrence must not call + # bpo-37140: Passing the structure by reference must not call # its finalizer! self.assertEqual(finalizer_calls, []) self.assertEqual(s.first, 1) diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index cbba320e01a54d..105a95b95540eb 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -229,7 +229,7 @@ def __init__(self, type): self.type = type def __repr__(self): - if isinstance(self.type, type): + if isinstance(self.type, type) and not isinstance(self.type, GenericAlias): type_name = self.type.__name__ else: # typing objects, e.g. List[int] @@ -447,7 +447,7 @@ def _field_assign(frozen, name, value, self_name): return f'{self_name}.{name}={value}' -def _field_init(f, frozen, globals, self_name): +def _field_init(f, frozen, globals, self_name, slots): # Return the text of the line in the body of __init__ that will # initialize this field. @@ -487,9 +487,15 @@ def _field_init(f, frozen, globals, self_name): globals[default_name] = f.default value = f.name else: - # This field does not need initialization. Signify that - # to the caller by returning None. - return None + # If the class has slots, then initialize this field. + if slots and f.default is not MISSING: + globals[default_name] = f.default + value = default_name + else: + # This field does not need initialization: reading from it will + # just use the class attribute that contains the default. + # Signify that to the caller by returning None. + return None # Only test this now, so that we can create variables for the # default. However, return None to signify that we're not going @@ -521,7 +527,7 @@ def _init_param(f): def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, - self_name, globals): + self_name, globals, slots): # fields contains both real fields and InitVar pseudo-fields. # Make sure we don't have fields without defaults following fields @@ -548,7 +554,7 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init, body_lines = [] for f in fields: - line = _field_init(f, frozen, locals, self_name) + line = _field_init(f, frozen, locals, self_name, slots) # line is None means that this field doesn't require # initialization (it's a pseudo-field). Just skip it. if line: @@ -1027,6 +1033,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, '__dataclass_self__' if 'self' in fields else 'self', globals, + slots, )) # Get the fields as a list, and include only real fields. This is @@ -1038,7 +1045,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, _set_new_attribute(cls, '__repr__', _repr_fn(flds, globals)) if eq: - # Create _eq__ method. There's no need for a __ne__ method, + # Create __eq__ method. There's no need for a __ne__ method, # since python will call __eq__ and negate it. flds = [f for f in field_list if f.compare] self_tuple = _tuple_str('self', flds) @@ -1204,7 +1211,7 @@ def _is_dataclass_instance(obj): def is_dataclass(obj): """Returns True if obj is a dataclass or an instance of a dataclass.""" - cls = obj if isinstance(obj, type) else type(obj) + cls = obj if isinstance(obj, type) and not isinstance(obj, GenericAlias) else type(obj) return hasattr(cls, _FIELDS) @@ -1326,7 +1333,7 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, - frozen=False, match_args=True, slots=False): + frozen=False, match_args=True, kw_only=False, slots=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -1387,13 +1394,13 @@ def exec_body_callback(ns): ns['__annotations__'] = annotations # We use `types.new_class()` instead of simply `type()` to allow dynamic creation - # of generic dataclassses. + # of generic dataclasses. cls = types.new_class(cls_name, bases, {}, exec_body_callback) # Apply the normal decorator. return dataclass(cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen, - match_args=match_args, slots=slots) + match_args=match_args, kw_only=kw_only, slots=slots) def replace(obj, /, **changes): diff --git a/Lib/difflib.py b/Lib/difflib.py index 0dda80d3875739..afd8a0c7c5b61e 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -62,7 +62,7 @@ class SequenceMatcher: notion, pairing up elements that appear uniquely in each sequence. That, and the method here, appear to yield more intuitive difference reports than does diff. This method appears to be the least vulnerable - to synching up on blocks of "junk lines", though (like blank lines in + to syncing up on blocks of "junk lines", though (like blank lines in ordinary text files, or maybe "

    " lines in HTML files). That may be because this is the only method of the 3 that has a *concept* of "junk" . @@ -115,38 +115,6 @@ class SequenceMatcher: case. SequenceMatcher is quadratic time for the worst case and has expected-case behavior dependent in a complicated way on how many elements the sequences have in common; best case time is linear. - - Methods: - - __init__(isjunk=None, a='', b='') - Construct a SequenceMatcher. - - set_seqs(a, b) - Set the two sequences to be compared. - - set_seq1(a) - Set the first sequence to be compared. - - set_seq2(b) - Set the second sequence to be compared. - - find_longest_match(alo=0, ahi=None, blo=0, bhi=None) - Find longest matching block in a[alo:ahi] and b[blo:bhi]. - - get_matching_blocks() - Return list of triples describing matching subsequences. - - get_opcodes() - Return list of 5-tuples describing how to turn a into b. - - ratio() - Return a measure of the sequences' similarity (float in [0,1]). - - quick_ratio() - Return an upper bound on .ratio() relatively quickly. - - real_quick_ratio() - Return an upper bound on ratio() very quickly. """ def __init__(self, isjunk=None, a='', b='', autojunk=True): @@ -837,14 +805,6 @@ class Differ: + 4. Complicated is better than complex. ? ++++ ^ ^ + 5. Flat is better than nested. - - Methods: - - __init__(linejunk=None, charjunk=None) - Construct a text differencer, with optional filters. - - compare(a, b) - Compare two sequences of lines; generate the resulting delta. """ def __init__(self, linejunk=None, charjunk=None): diff --git a/Lib/dis.py b/Lib/dis.py index 3fee1ce27725cd..fe5d24e88058f7 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -428,6 +428,7 @@ def _unpack_opargs(code): extended_arg = (arg << 8) if op == EXTENDED_ARG else 0 else: arg = None + extended_arg = 0 yield (i, op, arg) def findlabels(code): diff --git a/Lib/distutils/README b/Lib/distutils/README index 23f488506f8508..73bd25187c0270 100644 --- a/Lib/distutils/README +++ b/Lib/distutils/README @@ -2,10 +2,10 @@ This directory contains the Distutils package. There's a full documentation available at: - http://docs.python.org/distutils/ + https://docs.python.org/distutils/ The Distutils-SIG web page is also a good starting point: - http://www.python.org/sigs/distutils-sig/ + https://www.python.org/sigs/distutils-sig/ $Id$ diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index b5ef143e72c564..4c47f2ed245d4f 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -392,7 +392,7 @@ def _fix_compile_args(self, output_dir, macros, include_dirs): return output_dir, macros, include_dirs def _prep_compile(self, sources, output_dir, depends=None): - """Decide which souce files must be recompiled. + """Decide which source files must be recompiled. Determine the list of object files corresponding to 'sources', and figure out which ones really need to be recompiled. diff --git a/Lib/distutils/command/check.py b/Lib/distutils/command/check.py index ada250064678ee..73a30f3afd84a3 100644 --- a/Lib/distutils/command/check.py +++ b/Lib/distutils/command/check.py @@ -83,7 +83,7 @@ def check_metadata(self): name, version, URL Recommended fields: - (author and author_email) or (maintainer and maintainer_email)) + (author and author_email) or (maintainer and maintainer_email) Warns if any are missing. """ diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py index d33a889afe4a81..01d5331a63069b 100644 --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -31,18 +31,25 @@ # while making the sysconfig module the single point of truth. # This makes it easier for OS distributions where they need to # alter locations for packages installations in a single place. -# Note that this module is depracated (PEP 632); all consumers +# Note that this module is deprecated (PEP 632); all consumers # of this information should switch to using sysconfig directly. INSTALL_SCHEMES = {"unix_prefix": {}, "unix_home": {}, "nt": {}} # Copy from sysconfig._INSTALL_SCHEMES for key in SCHEME_KEYS: - sys_key = key - if key == "headers": - sys_key = "include" - INSTALL_SCHEMES["unix_prefix"][key] = sysconfig._INSTALL_SCHEMES["posix_prefix"][sys_key] - INSTALL_SCHEMES["unix_home"][key] = sysconfig._INSTALL_SCHEMES["posix_home"][sys_key] - INSTALL_SCHEMES["nt"][key] = sysconfig._INSTALL_SCHEMES["nt"][sys_key] + for distutils_scheme_name, sys_scheme_name in ( + ("unix_prefix", "posix_prefix"), ("unix_home", "posix_home"), + ("nt", "nt")): + sys_key = key + sys_scheme = sysconfig._INSTALL_SCHEMES[sys_scheme_name] + if key == "headers" and key not in sys_scheme: + # On POSIX-y platforms, Python will: + # - Build from .h files in 'headers' (only there when + # building CPython) + # - Install .h files to 'include' + # When 'headers' is missing, fall back to 'include' + sys_key = 'include' + INSTALL_SCHEMES[distutils_scheme_name][key] = sys_scheme[sys_key] # Transformation to different template format for main_key in INSTALL_SCHEMES: @@ -316,6 +323,9 @@ def finalize_options(self): self.config_vars['userbase'] = self.install_userbase self.config_vars['usersite'] = self.install_usersite + if sysconfig.is_python_build(True): + self.config_vars['srcdir'] = sysconfig.get_config_var('srcdir') + self.expand_basedirs() self.dump_dirs("post-expand_basedirs()") diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index 95e9fda186fc8f..e0ecb655b93faf 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -9,7 +9,8 @@ import io import hashlib from base64 import standard_b64encode -from urllib.request import urlopen, Request, HTTPError +from urllib.error import HTTPError +from urllib.request import urlopen, Request from urllib.parse import urlparse from distutils.errors import DistutilsError, DistutilsOptionError from distutils.core import PyPIRCCommand diff --git a/Lib/distutils/msvc9compiler.py b/Lib/distutils/msvc9compiler.py index 6934e964abd69b..a7976fbe3ed924 100644 --- a/Lib/distutils/msvc9compiler.py +++ b/Lib/distutils/msvc9compiler.py @@ -673,7 +673,7 @@ def manifest_get_embed_info(self, target_desc, ld_args): # If a manifest should be embedded, return a tuple of # (manifest_filename, resource_id). Returns None if no manifest # should be embedded. See http://bugs.python.org/issue7833 for why - # we want to avoid any manifest for extension modules if we can) + # we want to avoid any manifest for extension modules if we can. for arg in ld_args: if arg.startswith("/MANIFESTFILE:"): temp_manifest = arg.split(":", 1)[1] diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index aa63093a3f0e6e..3414a761e76b99 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -28,7 +28,6 @@ _PYTHON_BUILD as python_build, _init_posix as sysconfig_init_posix, parse_config_h as sysconfig_parse_config_h, - _parse_makefile as sysconfig_parse_makefile, _init_non_posix, _is_python_source_dir, @@ -68,14 +67,118 @@ def parse_config_h(fp, g=None): return sysconfig_parse_config_h(fp, vars=g) -def parse_makefile(fn, g=None): - return sysconfig_parse_makefile(fn, vars=g, keep_unresolved=False) - _python_build = partial(is_python_build, check_home=True) _init_posix = partial(sysconfig_init_posix, _config_vars) _init_nt = partial(_init_non_posix, _config_vars) +# Similar function is also implemented in sysconfig as _parse_makefile +# but without the parsing capabilities of distutils.text_file.TextFile. +def parse_makefile(fn, g=None): + """Parse a Makefile-style file. + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + from distutils.text_file import TextFile + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape") + + if g is None: + g = {} + done = {} + notdone = {} + + while True: + line = fp.readline() + if line is None: # eof + break + m = re.match(_variable_rx, line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + # do variable interpolation here + while notdone: + for name in list(notdone): + value = notdone[name] + m = re.search(_findvar1_rx, value) or re.search(_findvar2_rx, value) + if m: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if name.startswith('PY_') and name[3:] in renamed_variables: + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + else: + done[n] = item = "" + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + del notdone[name] + + if name.startswith('PY_') \ + and name[3:] in renamed_variables: + + name = name[3:] + if name not in done: + done[name] = value + else: + # bogus variable reference; just drop it since we can't deal + del notdone[name] + + fp.close() + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + g.update(done) + return g + + # Following functions are deprecated together with this module and they # have no direct replacement diff --git a/Lib/distutils/tests/test_bdist.py b/Lib/distutils/tests/test_bdist.py index 09ad076799b420..55fa3930dd92f2 100644 --- a/Lib/distutils/tests/test_bdist.py +++ b/Lib/distutils/tests/test_bdist.py @@ -3,8 +3,11 @@ import unittest from test.support import run_unittest -from distutils.command.bdist import bdist -from distutils.tests import support +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + from distutils.command.bdist import bdist + from distutils.tests import support class BuildTestCase(support.TempdirManager, diff --git a/Lib/distutils/tests/test_bdist_rpm.py b/Lib/distutils/tests/test_bdist_rpm.py index 6453a02b88f600..ba4382fb3a2fa1 100644 --- a/Lib/distutils/tests/test_bdist_rpm.py +++ b/Lib/distutils/tests/test_bdist_rpm.py @@ -44,7 +44,7 @@ def tearDown(self): # spurious sdtout/stderr output under Mac OS X @unittest.skipUnless(sys.platform.startswith('linux'), 'spurious sdtout/stderr output under Mac OS X') - @requires_zlib + @requires_zlib() @unittest.skipIf(find_executable('rpm') is None, 'the rpm command is not found') @unittest.skipIf(find_executable('rpmbuild') is None, @@ -87,7 +87,7 @@ def test_quiet(self): # spurious sdtout/stderr output under Mac OS X @unittest.skipUnless(sys.platform.startswith('linux'), 'spurious sdtout/stderr output under Mac OS X') - @requires_zlib + @requires_zlib() # http://bugs.python.org/issue1533164 @unittest.skipIf(find_executable('rpm') is None, 'the rpm command is not found') diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py index bca5516d2f74f6..74f0bc0a67131b 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -2,7 +2,7 @@ import os import unittest import unittest.mock as mock -from urllib.request import HTTPError +from urllib.error import HTTPError from test.support import run_unittest diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py index f0792de74a1a48..d00c48981eb6d6 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py @@ -215,7 +215,8 @@ def library_dir_option(self, dir): return "-L" + dir def _is_gcc(self, compiler_name): - return "gcc" in compiler_name or "g++" in compiler_name + # clang uses same syntax for rpath as gcc + return any(name in compiler_name for name in ("gcc", "g++", "clang")) def runtime_library_dir_option(self, dir): # XXX Hackish, at the very least. See Python bug #445902: diff --git a/Lib/doctest.py b/Lib/doctest.py index e95c333f48aad5..b27cbdfed46ffd 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -973,6 +973,17 @@ def _from_module(self, module, object): else: raise ValueError("object must be a class or function") + def _is_routine(self, obj): + """ + Safely unwrap objects and determine if they are functions. + """ + maybe_routine = obj + try: + maybe_routine = inspect.unwrap(maybe_routine) + except ValueError: + pass + return inspect.isroutine(maybe_routine) + def _find(self, tests, obj, name, module, source_lines, globs, seen): """ Find tests for the given object and any contained objects, and @@ -995,9 +1006,9 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen): if inspect.ismodule(obj) and self._recurse: for valname, val in obj.__dict__.items(): valname = '%s.%s' % (name, valname) + # Recurse to functions & classes. - if ((inspect.isroutine(inspect.unwrap(val)) - or inspect.isclass(val)) and + if ((self._is_routine(val) or inspect.isclass(val)) and self._from_module(module, val)): self._find(tests, val, valname, module, source_lines, globs, seen) @@ -1023,10 +1034,8 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen): if inspect.isclass(obj) and self._recurse: for valname, val in obj.__dict__.items(): # Special handling for staticmethod/classmethod. - if isinstance(val, staticmethod): - val = getattr(obj, valname) - if isinstance(val, classmethod): - val = getattr(obj, valname).__func__ + if isinstance(val, (staticmethod, classmethod)): + val = val.__func__ # Recurse to methods, properties, and nested classes. if ((inspect.isroutine(val) or inspect.isclass(val) or diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py index 4d27f87974b20d..ba5ad5a36d06b7 100644 --- a/Lib/email/_parseaddr.py +++ b/Lib/email/_parseaddr.py @@ -67,6 +67,8 @@ def _parsedate_tz(data): if not data: return None data = data.split() + if not data: # This happens for whitespace-only input. + return None # The FWS after the comma after the day-of-week is optional, so search and # adjust for this. if data[0].endswith(',') or data[0].lower() in _daynames: @@ -126,6 +128,8 @@ def _parsedate_tz(data): tss = 0 elif len(tm) == 3: [thh, tmm, tss] = tm + else: + return None else: return None try: diff --git a/Lib/email/contentmanager.py b/Lib/email/contentmanager.py index b91fb0e5bca7a8..fcf278dbccbac9 100644 --- a/Lib/email/contentmanager.py +++ b/Lib/email/contentmanager.py @@ -144,7 +144,7 @@ def _encode_text(string, charset, cte, policy): linesep = policy.linesep.encode('ascii') def embedded_body(lines): return linesep.join(lines) + linesep def normal_body(lines): return b'\n'.join(lines) + b'\n' - if cte==None: + if cte is None: # Use heuristics to decide on the "best" encoding. if max((len(x) for x in lines), default=0) <= policy.max_line_length: try: @@ -238,9 +238,7 @@ def set_bytes_content(msg, data, maintype, subtype, cte='base64', data = binascii.b2a_qp(data, istext=False, header=False, quotetabs=True) data = data.decode('ascii') elif cte == '7bit': - # Make sure it really is only ASCII. The early warning here seems - # worth the overhead...if you care write your own content manager :). - data.encode('ascii') + data = data.decode('ascii') elif cte in ('8bit', 'binary'): data = data.decode('ascii', 'surrogateescape') msg.set_payload(data) diff --git a/Lib/email/errors.py b/Lib/email/errors.py index 1d258c34fc9d4a..3ad00565549968 100644 --- a/Lib/email/errors.py +++ b/Lib/email/errors.py @@ -110,4 +110,4 @@ class NonASCIILocalPartDefect(HeaderDefect): # parsing messages decoded from binary. class InvalidDateDefect(HeaderDefect): - """Header has unparseable or invalid date""" + """Header has unparsable or invalid date""" diff --git a/Lib/email/message.py b/Lib/email/message.py index 3701b305532b4c..6752ce0fa13825 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -948,7 +948,7 @@ def __init__(self, policy=None): if policy is None: from email.policy import default policy = default - Message.__init__(self, policy) + super().__init__(policy) def as_string(self, unixfrom=False, maxheaderlen=None, policy=None): @@ -965,7 +965,7 @@ def as_string(self, unixfrom=False, maxheaderlen=None, policy=None): policy = self.policy if policy is None else policy if maxheaderlen is None: maxheaderlen = policy.max_line_length - return super().as_string(maxheaderlen=maxheaderlen, policy=policy) + return super().as_string(unixfrom, maxheaderlen, policy) def __str__(self): return self.as_string(policy=self.policy.clone(utf8=True)) @@ -982,7 +982,7 @@ def _find_body(self, part, preferencelist): if subtype in preferencelist: yield (preferencelist.index(subtype), part) return - if maintype != 'multipart': + if maintype != 'multipart' or not self.is_multipart(): return if subtype != 'related': for subpart in part.iter_parts(): @@ -1087,7 +1087,7 @@ def iter_parts(self): Return an empty iterator for a non-multipart. """ - if self.get_content_maintype() == 'multipart': + if self.is_multipart(): yield from self.get_payload() def get_content(self, *args, content_manager=None, **kw): diff --git a/Lib/email/utils.py b/Lib/email/utils.py index a8e46a761bf922..cfdfeb3f1a86e4 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -109,7 +109,7 @@ def formataddr(pair, charset='utf-8'): def getaddresses(fieldvalues): """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" - all = COMMASPACE.join(fieldvalues) + all = COMMASPACE.join(str(v) for v in fieldvalues) a = _AddressList(all) return a.addresslist diff --git a/Lib/encodings/raw_unicode_escape.py b/Lib/encodings/raw_unicode_escape.py index 2b919b40d3788a..46c8e070dd192e 100644 --- a/Lib/encodings/raw_unicode_escape.py +++ b/Lib/encodings/raw_unicode_escape.py @@ -21,15 +21,16 @@ class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input, final=False): return codecs.raw_unicode_escape_encode(input, self.errors)[0] -class IncrementalDecoder(codecs.IncrementalDecoder): - def decode(self, input, final=False): - return codecs.raw_unicode_escape_decode(input, self.errors)[0] +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, input, errors, final): + return codecs.raw_unicode_escape_decode(input, errors, final) class StreamWriter(Codec,codecs.StreamWriter): pass class StreamReader(Codec,codecs.StreamReader): - pass + def decode(self, input, errors='strict'): + return codecs.raw_unicode_escape_decode(input, errors, False) ### encodings module API diff --git a/Lib/encodings/unicode_escape.py b/Lib/encodings/unicode_escape.py index 817f93265a4634..9b1ce99b339ae0 100644 --- a/Lib/encodings/unicode_escape.py +++ b/Lib/encodings/unicode_escape.py @@ -21,15 +21,16 @@ class IncrementalEncoder(codecs.IncrementalEncoder): def encode(self, input, final=False): return codecs.unicode_escape_encode(input, self.errors)[0] -class IncrementalDecoder(codecs.IncrementalDecoder): - def decode(self, input, final=False): - return codecs.unicode_escape_decode(input, self.errors)[0] +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, input, errors, final): + return codecs.unicode_escape_decode(input, errors, final) class StreamWriter(Codec,codecs.StreamWriter): pass class StreamReader(Codec,codecs.StreamReader): - pass + def decode(self, input, errors='strict'): + return codecs.unicode_escape_decode(input, errors, False) ### encodings module API diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 4c606b9f2a89b8..0a5730c00c3596 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -11,8 +11,8 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('setuptools', 'pip') -_SETUPTOOLS_VERSION = "56.0.0" -_PIP_VERSION = "21.1.1" +_SETUPTOOLS_VERSION = "58.1.0" +_PIP_VERSION = "21.2.4" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), ("pip", _PIP_VERSION, "py3"), @@ -42,7 +42,7 @@ def _find_packages(path): # comparison since this case should not happen. filenames = sorted(filenames) for filename in filenames: - # filename is like 'pip-20.2.3-py2.py3-none-any.whl' + # filename is like 'pip-21.2.4-py3-none-any.whl' if not filename.endswith(".whl"): continue for name in _PACKAGE_NAMES: @@ -52,7 +52,7 @@ def _find_packages(path): else: continue - # Extract '20.2.2' from 'pip-20.2.2-py2.py3-none-any.whl' + # Extract '21.2.4' from 'pip-21.2.4-py3-none-any.whl' version = filename.removeprefix(prefix).partition('-')[0] wheel_path = os.path.join(path, filename) packages[name] = _Package(version, None, wheel_path) diff --git a/Lib/ensurepip/_bundled/pip-21.1.1-py3-none-any.whl b/Lib/ensurepip/_bundled/pip-21.2.4-py3-none-any.whl similarity index 56% rename from Lib/ensurepip/_bundled/pip-21.1.1-py3-none-any.whl rename to Lib/ensurepip/_bundled/pip-21.2.4-py3-none-any.whl index 291cc296fa7b48..46d3012c59b174 100644 Binary files a/Lib/ensurepip/_bundled/pip-21.1.1-py3-none-any.whl and b/Lib/ensurepip/_bundled/pip-21.2.4-py3-none-any.whl differ diff --git a/Lib/ensurepip/_bundled/setuptools-56.0.0-py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl similarity index 63% rename from Lib/ensurepip/_bundled/setuptools-56.0.0-py3-none-any.whl rename to Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl index 264ef10e826679..18c8c22958f1f1 100644 Binary files a/Lib/ensurepip/_bundled/setuptools-56.0.0-py3-none-any.whl and b/Lib/ensurepip/_bundled/setuptools-58.1.0-py3-none-any.whl differ diff --git a/Lib/enum.py b/Lib/enum.py index 01f431001a9bf0..f5657a6eba29c1 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1,23 +1,14 @@ import sys from types import MappingProxyType, DynamicClassAttribute -from builtins import property as _bltin_property, bin as _bltin_bin __all__ = [ - 'EnumType', 'EnumMeta', - 'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag', + 'EnumMeta', + 'Enum', 'IntEnum', 'Flag', 'IntFlag', 'auto', 'unique', - 'property', - 'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP', - 'global_flag_repr', 'global_enum_repr', 'global_enum', ] -# Dummy value for Enum and Flag as there are explicit checks for them -# before they have been created. -# This is also why there are checks in EnumType like `if Enum is not None` -Enum = Flag = EJECT = None - def _is_descriptor(obj): """ Returns True if obj is a descriptor, False otherwise. @@ -64,60 +55,14 @@ def _is_private(cls_name, name): else: return False -def _is_single_bit(num): - """ - True if only one bit set in num (should be an int) - """ - if num == 0: - return False - num &= num - 1 - return num == 0 - -def _make_class_unpicklable(obj): +def _make_class_unpicklable(cls): """ - Make the given obj un-picklable. - - obj should be either a dictionary, on an Enum + Make the given class un-picklable. """ def _break_on_call_reduce(self, proto): raise TypeError('%r cannot be pickled' % self) - if isinstance(obj, dict): - obj['__reduce_ex__'] = _break_on_call_reduce - obj['__module__'] = '' - else: - setattr(obj, '__reduce_ex__', _break_on_call_reduce) - setattr(obj, '__module__', '') - -def _iter_bits_lsb(num): - while num: - b = num & (~num + 1) - yield b - num ^= b - -def bin(num, max_bits=None): - """ - Like built-in bin(), except negative values are represented in - twos-compliment, and the leading bit always indicates sign - (0=positive, 1=negative). - - >>> bin(10) - '0b0 1010' - >>> bin(~10) # ~10 is -11 - '0b1 0101' - """ - - ceiling = 2 ** (num).bit_length() - if num >= 0: - s = _bltin_bin(num + ceiling).replace('1', '0', 1) - else: - s = _bltin_bin(~num ^ (ceiling - 1) + ceiling) - sign = s[:3] - digits = s[3:] - if max_bits is not None: - if len(digits) < max_bits: - digits = (sign[-1] * max_bits + digits)[-max_bits:] - return "%s %s" % (sign, digits) - + cls.__reduce_ex__ = _break_on_call_reduce + cls.__module__ = '' _auto_null = object() class auto: @@ -126,169 +71,12 @@ class auto: """ value = _auto_null -class property(DynamicClassAttribute): - """ - This is a descriptor, used to define attributes that act differently - when accessed through an enum member and through an enum class. - Instance access is the same as property(), but access to an attribute - through the enum class will instead look in the class' _member_map_ for - a corresponding enum member. - """ - - def __get__(self, instance, ownerclass=None): - if instance is None: - try: - return ownerclass._member_map_[self.name] - except KeyError: - raise AttributeError( - '%s: no class attribute %r' % (ownerclass.__name__, self.name) - ) - else: - if self.fget is None: - # check for member - if self.name in ownerclass._member_map_: - import warnings - warnings.warn( - "accessing one member from another is not supported, " - " and will be disabled in 3.12", - DeprecationWarning, - stacklevel=2, - ) - return ownerclass._member_map_[self.name] - raise AttributeError( - '%s: no instance attribute %r' % (ownerclass.__name__, self.name) - ) - else: - return self.fget(instance) - - def __set__(self, instance, value): - if self.fset is None: - raise AttributeError( - "%s: cannot set instance attribute %r" % (self.clsname, self.name) - ) - else: - return self.fset(instance, value) - - def __delete__(self, instance): - if self.fdel is None: - raise AttributeError( - "%s: cannot delete instance attribute %r" % (self.clsname, self.name) - ) - else: - return self.fdel(instance) - - def __set_name__(self, ownerclass, name): - self.name = name - self.clsname = ownerclass.__name__ - - -class _proto_member: - """ - intermediate step for enum members between class execution and final creation - """ - - def __init__(self, value): - self.value = value - - def __set_name__(self, enum_class, member_name): - """ - convert each quasi-member into an instance of the new enum class - """ - # first step: remove ourself from enum_class - delattr(enum_class, member_name) - # second step: create member based on enum_class - value = self.value - if not isinstance(value, tuple): - args = (value, ) - else: - args = value - if enum_class._member_type_ is tuple: # special case for tuple enums - args = (args, ) # wrap it one more time - if not enum_class._use_args_: - enum_member = enum_class._new_member_(enum_class) - if not hasattr(enum_member, '_value_'): - enum_member._value_ = value - else: - enum_member = enum_class._new_member_(enum_class, *args) - if not hasattr(enum_member, '_value_'): - if enum_class._member_type_ is object: - enum_member._value_ = value - else: - try: - enum_member._value_ = enum_class._member_type_(*args) - except Exception as exc: - raise TypeError( - '_value_ not set in __new__, unable to create it' - ) from None - value = enum_member._value_ - enum_member._name_ = member_name - enum_member.__objclass__ = enum_class - enum_member.__init__(*args) - enum_member._sort_order_ = len(enum_class._member_names_) - # If another member with the same value was already defined, the - # new member becomes an alias to the existing one. - for name, canonical_member in enum_class._member_map_.items(): - if canonical_member._value_ == enum_member._value_: - enum_member = canonical_member - break - else: - # this could still be an alias if the value is multi-bit and the - # class is a flag class - if ( - Flag is None - or not issubclass(enum_class, Flag) - ): - # no other instances found, record this member in _member_names_ - enum_class._member_names_.append(member_name) - elif ( - Flag is not None - and issubclass(enum_class, Flag) - and _is_single_bit(value) - ): - # no other instances found, record this member in _member_names_ - enum_class._member_names_.append(member_name) - # get redirect in place before adding to _member_map_ - # but check for other instances in parent classes first - need_override = False - descriptor = None - for base in enum_class.__mro__[1:]: - descriptor = base.__dict__.get(member_name) - if descriptor is not None: - if isinstance(descriptor, (property, DynamicClassAttribute)): - break - else: - need_override = True - # keep looking for an enum.property - if descriptor and not need_override: - # previous enum.property found, no further action needed - pass - else: - redirect = property() - redirect.__set_name__(enum_class, member_name) - if descriptor and need_override: - # previous enum.property found, but some other inherited attribute - # is in the way; copy fget, fset, fdel to this one - redirect.fget = descriptor.fget - redirect.fset = descriptor.fset - redirect.fdel = descriptor.fdel - setattr(enum_class, member_name, redirect) - # now add to _member_map_ (even aliases) - enum_class._member_map_[member_name] = enum_member - try: - # This may fail if value is not hashable. We can't add the value - # to the map, and by-value lookups for this value will be - # linear. - enum_class._value2member_map_.setdefault(value, enum_member) - except TypeError: - # keep track of the value in a list so containment checks are quick - enum_class._unhashable_values_.append(value) - class _EnumDict(dict): """ Track enum member order and ensure member names are not reused. - EnumType will use the names found in self._member_names as the + EnumMeta will use the names found in self._member_names as the enumeration member names. """ def __init__(self): @@ -308,24 +96,24 @@ def __setitem__(self, key, value): Single underscore (sunder) names are reserved. """ if _is_private(self._cls_name, key): - # do nothing, name will be a normal attribute - pass - elif _is_sunder(key): + import warnings + warnings.warn( + "private variables, such as %r, will be normal attributes in 3.11" + % (key, ), + DeprecationWarning, + stacklevel=2, + ) + if _is_sunder(key): if key not in ( - '_order_', + '_order_', '_create_pseudo_member_', '_generate_next_value_', '_missing_', '_ignore_', - '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_', ): - raise ValueError( - '_sunder_ names, such as %r, are reserved for future Enum use' - % (key, ) - ) + raise ValueError('_names_ are reserved for future Enum use') if key == '_generate_next_value_': # check if members already defined as auto() if self._auto_called: raise TypeError("_generate_next_value_ must be defined before members") - _gnv = value.__func__ if isinstance(value, staticmethod) else value - setattr(self, '_generate_next_value', _gnv) + setattr(self, '_generate_next_value', value) elif key == '_ignore_': if isinstance(value, str): value = value.replace(',',' ').split() @@ -343,7 +131,7 @@ def __setitem__(self, key, value): key = '_order_' elif key in self._member_names: # descriptor overwriting an enum? - raise TypeError('%r already defined as: %r' % (key, self[key])) + raise TypeError('Attempted to reuse key: %r' % key) elif key in self._ignore: pass elif not _is_descriptor(value): @@ -353,7 +141,10 @@ def __setitem__(self, key, value): if isinstance(value, auto): if value.value == _auto_null: value.value = self._generate_next_value( - key, 1, len(self._member_names), self._last_values[:], + key, + 1, + len(self._member_names), + self._last_values[:], ) self._auto_called = True value = value.value @@ -361,22 +152,16 @@ def __setitem__(self, key, value): self._last_values.append(value) super().__setitem__(key, value) - def update(self, members, **more_members): - try: - for name in members.keys(): - self[name] = members[name] - except AttributeError: - for name, value in members: - self[name] = value - for name, value in more_members.items(): - self[name] = value +# Dummy value for Enum as EnumMeta explicitly checks for it, but of course +# until EnumMeta finishes running the first time the Enum class doesn't exist. +# This is also why there are checks in EnumMeta like `if Enum is not None` +Enum = None -class EnumType(type): +class EnumMeta(type): """ Metaclass for Enum """ - @classmethod def __prepare__(metacls, cls, bases, **kwds): # check that previous enum members do not exist @@ -392,67 +177,57 @@ def __prepare__(metacls, cls, bases, **kwds): ) return enum_dict - def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **kwds): + def __new__(metacls, cls, bases, classdict, **kwds): # an Enum class is final once enumeration items have been defined; it # cannot be mixed with other types (int, float, etc.) if it has an # inherited __new__ unless a new __new__ is defined (or the resulting # class will fail). # # remove any keys listed in _ignore_ - if _simple: - return super().__new__(metacls, cls, bases, classdict, **kwds) classdict.setdefault('_ignore_', []).append('_ignore_') ignore = classdict['_ignore_'] for key in ignore: classdict.pop(key, None) - # - # grab member names - member_names = classdict._member_names - # - # check for illegal enum names (any others?) - invalid_names = set(member_names) & {'mro', ''} - if invalid_names: - raise ValueError('Invalid enum member name: {0}'.format( - ','.join(invalid_names))) - # - # adjust the sunders - _order_ = classdict.pop('_order_', None) - # convert to normal dict - classdict = dict(classdict.items()) - # - # data type of member and the controlling Enum class member_type, first_enum = metacls._get_mixins_(cls, bases) __new__, save_new, use_args = metacls._find_new_( classdict, member_type, first_enum, ) - classdict['_new_member_'] = __new__ - classdict['_use_args_'] = use_args - # - # convert future enum members into temporary _proto_members - # and record integer values in case this will be a Flag - flag_mask = 0 - for name in member_names: - value = classdict[name] - if isinstance(value, int): - flag_mask |= value - classdict[name] = _proto_member(value) - # - # house-keeping structures - classdict['_member_names_'] = [] - classdict['_member_map_'] = {} - classdict['_value2member_map_'] = {} - classdict['_unhashable_values_'] = [] - classdict['_member_type_'] = member_type - # - # Flag structures (will be removed if final class is not a Flag - classdict['_boundary_'] = ( - boundary - or getattr(first_enum, '_boundary_', None) - ) - classdict['_flag_mask_'] = flag_mask - classdict['_all_bits_'] = 2 ** ((flag_mask).bit_length()) - 1 - classdict['_inverted_'] = None - # + + # save enum items into separate mapping so they don't get baked into + # the new class + enum_members = {k: classdict[k] for k in classdict._member_names} + for name in classdict._member_names: + del classdict[name] + + # adjust the sunders + _order_ = classdict.pop('_order_', None) + + # check for illegal enum names (any others?) + invalid_names = set(enum_members) & {'mro', ''} + if invalid_names: + raise ValueError('Invalid enum member name: {0}'.format( + ','.join(invalid_names))) + + # create a default docstring if one has not been provided + if '__doc__' not in classdict: + classdict['__doc__'] = 'An enumeration.' + + enum_class = super().__new__(metacls, cls, bases, classdict, **kwds) + enum_class._member_names_ = [] # names in definition order + enum_class._member_map_ = {} # name->value map + enum_class._member_type_ = member_type + + # save DynamicClassAttribute attributes from super classes so we know + # if we can take the shortcut of storing members in the class dict + dynamic_attributes = { + k for c in enum_class.mro() + for k, v in c.__dict__.items() + if isinstance(v, DynamicClassAttribute) + } + + # Reverse value->name map for hashable values. + enum_class._value2member_map_ = {} + # If a custom type is mixed into the Enum, and it does not know how # to pickle itself, pickle.dumps will succeed but pickle.loads will # fail. Rather than have the error show up later and possibly far @@ -468,21 +243,82 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k methods = ('__getnewargs_ex__', '__getnewargs__', '__reduce_ex__', '__reduce__') if not any(m in member_type.__dict__ for m in methods): - _make_class_unpicklable(classdict) - # - # create a default docstring if one has not been provided - if '__doc__' not in classdict: - classdict['__doc__'] = 'An enumeration.' - try: - exc = None - enum_class = super().__new__(metacls, cls, bases, classdict, **kwds) - except RuntimeError as e: - # any exceptions raised by member.__new__ will get converted to a - # RuntimeError, so get that original exception back and raise it instead - exc = e.__cause__ or e - if exc is not None: - raise exc - # + if '__new__' in classdict: + # too late, sabotage + _make_class_unpicklable(enum_class) + else: + # final attempt to verify that pickling would work: + # travel mro until __new__ is found, checking for + # __reduce__ and friends along the way -- if any of them + # are found before/when __new__ is found, pickling should + # work + sabotage = None + for chain in bases: + for base in chain.__mro__: + if base is object: + continue + elif any(m in base.__dict__ for m in methods): + # found one, we're good + sabotage = False + break + elif '__new__' in base.__dict__: + # not good + sabotage = True + break + if sabotage is not None: + break + if sabotage: + _make_class_unpicklable(enum_class) + # instantiate them, checking for duplicates as we go + # we instantiate first instead of checking for duplicates first in case + # a custom __new__ is doing something funky with the values -- such as + # auto-numbering ;) + for member_name in classdict._member_names: + value = enum_members[member_name] + if not isinstance(value, tuple): + args = (value, ) + else: + args = value + if member_type is tuple: # special case for tuple enums + args = (args, ) # wrap it one more time + if not use_args: + enum_member = __new__(enum_class) + if not hasattr(enum_member, '_value_'): + enum_member._value_ = value + else: + enum_member = __new__(enum_class, *args) + if not hasattr(enum_member, '_value_'): + if member_type is object: + enum_member._value_ = value + else: + enum_member._value_ = member_type(*args) + value = enum_member._value_ + enum_member._name_ = member_name + enum_member.__objclass__ = enum_class + enum_member.__init__(*args) + # If another member with the same value was already defined, the + # new member becomes an alias to the existing one. + for name, canonical_member in enum_class._member_map_.items(): + if canonical_member._value_ == enum_member._value_: + enum_member = canonical_member + break + else: + # Aliases don't appear in member names (only in __members__). + enum_class._member_names_.append(member_name) + # performance boost for any member that would not shadow + # a DynamicClassAttribute + if member_name not in dynamic_attributes: + setattr(enum_class, member_name, enum_member) + # now add to _member_map_ + enum_class._member_map_[member_name] = enum_member + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + enum_class._value2member_map_[value] = enum_member + except TypeError: + pass + # double check that repr and friends are not the mixin's or various # things break (such as pickle) # however, if the method is defined in the Enum itself, don't replace @@ -495,7 +331,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k enum_method = getattr(first_enum, name, None) if obj_method is not None and obj_method is class_method: setattr(enum_class, name, enum_method) - # + # replace any other __new__ with our own (as long as Enum is not None, # anyway) -- again, this is to support pickle if Enum is not None: @@ -504,78 +340,14 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k if save_new: enum_class.__new_member__ = __new__ enum_class.__new__ = Enum.__new__ - # + # py3 support for definition order (helps keep py2/py3 code in sync) - # - # _order_ checking is spread out into three/four steps - # - if enum_class is a Flag: - # - remove any non-single-bit flags from _order_ - # - remove any aliases from _order_ - # - check that _order_ and _member_names_ match - # - # step 1: ensure we have a list if _order_ is not None: if isinstance(_order_, str): _order_ = _order_.replace(',', ' ').split() - # - # remove Flag structures if final class is not a Flag - if ( - Flag is None and cls != 'Flag' - or Flag is not None and not issubclass(enum_class, Flag) - ): - delattr(enum_class, '_boundary_') - delattr(enum_class, '_flag_mask_') - delattr(enum_class, '_all_bits_') - delattr(enum_class, '_inverted_') - elif Flag is not None and issubclass(enum_class, Flag): - # ensure _all_bits_ is correct and there are no missing flags - single_bit_total = 0 - multi_bit_total = 0 - for flag in enum_class._member_map_.values(): - flag_value = flag._value_ - if _is_single_bit(flag_value): - single_bit_total |= flag_value - else: - # multi-bit flags are considered aliases - multi_bit_total |= flag_value - if enum_class._boundary_ is not KEEP: - missed = list(_iter_bits_lsb(multi_bit_total & ~single_bit_total)) - if missed: - raise TypeError( - 'invalid Flag %r -- missing values: %s' - % (cls, ', '.join((str(i) for i in missed))) - ) - enum_class._flag_mask_ = single_bit_total - # - # set correct __iter__ - member_list = [m._value_ for m in enum_class] - if member_list != sorted(member_list): - enum_class._iter_member_ = enum_class._iter_member_by_def_ - if _order_: - # _order_ step 2: remove any items from _order_ that are not single-bit - _order_ = [ - o - for o in _order_ - if o not in enum_class._member_map_ or _is_single_bit(enum_class[o]._value_) - ] - # - if _order_: - # _order_ step 3: remove aliases from _order_ - _order_ = [ - o - for o in _order_ - if ( - o not in enum_class._member_map_ - or - (o in enum_class._member_map_ and o in enum_class._member_names_) - )] - # _order_ step 4: verify that _order_ and _member_names_ match if _order_ != enum_class._member_names_: - raise TypeError( - 'member order does not match _order_:\n%r\n%r' - % (enum_class._member_names_, _order_) - ) - # + raise TypeError('member order does not match _order_') + return enum_class def __bool__(self): @@ -584,7 +356,7 @@ def __bool__(self): """ return True - def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None): + def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): """ Either returns an existing member, or creates a new enum class. @@ -619,28 +391,27 @@ def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, s qualname=qualname, type=type, start=start, - boundary=boundary, ) - def __contains__(cls, member): - if not isinstance(member, Enum): + def __contains__(cls, obj): + if not isinstance(obj, Enum): import warnings warnings.warn( - "in 3.12 __contains__ will no longer raise TypeError, but will return True or\n" - "False depending on whether the value is a member or the value of a member", + "in 3.12 __contains__ will no longer raise TypeError, but will return True if\n" + "obj is a member or a member's value", DeprecationWarning, stacklevel=2, ) raise TypeError( "unsupported operand type(s) for 'in': '%s' and '%s'" % ( - type(member).__qualname__, cls.__class__.__qualname__)) - return isinstance(member, cls) and member._name_ in cls._member_map_ + type(obj).__qualname__, cls.__class__.__qualname__)) + return isinstance(obj, cls) and obj._name_ in cls._member_map_ def __delattr__(cls, attr): # nicer error message when someone tries to delete an attribute # (see issue19025). if attr in cls._member_map_: - raise AttributeError("%s: cannot delete Enum member %r." % (cls.__name__, attr)) + raise AttributeError("%s: cannot delete Enum member." % cls.__name__) super().__delattr__(attr) def __dir__(self): @@ -677,7 +448,7 @@ def __iter__(cls): def __len__(cls): return len(cls._member_names_) - @_bltin_property + @property def __members__(cls): """ Returns a mapping of member name->value. @@ -706,10 +477,10 @@ def __setattr__(cls, name, value): """ member_map = cls.__dict__.get('_member_map_', {}) if name in member_map: - raise AttributeError('Cannot reassign member %r.' % (name, )) + raise AttributeError('Cannot reassign members.') super().__setattr__(name, value) - def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1, boundary=None): + def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): """ Convenience method to create a new Enum class. @@ -744,6 +515,7 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s else: member_name, member_value = item classdict[member_name] = member_value + enum_class = metacls.__new__(metacls, class_name, bases, classdict) # TODO: replace the frame hack if a blessed way to know the calling # module is ever developed @@ -753,16 +525,15 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s except (AttributeError, ValueError, KeyError): pass if module is None: - _make_class_unpicklable(classdict) + _make_class_unpicklable(enum_class) else: - classdict['__module__'] = module + enum_class.__module__ = module if qualname is not None: - classdict['__qualname__'] = qualname + enum_class.__qualname__ = qualname - return metacls.__new__(metacls, class_name, bases, classdict, boundary=boundary) - - def _convert_(cls, name, module, filter, source=None, *, boundary=None): + return enum_class + def _convert_(cls, name, module, filter, source=None): """ Create a new Enum subclass that replaces a collection of global constants """ @@ -771,9 +542,9 @@ def _convert_(cls, name, module, filter, source=None, *, boundary=None): # module; # also, replace the __reduce_ex__ method so unpickling works in # previous Python versions - module_globals = sys.modules[module].__dict__ + module_globals = vars(sys.modules[module]) if source: - source = source.__dict__ + source = vars(source) else: source = module_globals # _value2member_map_ is populated in the same order every time @@ -789,12 +560,9 @@ def _convert_(cls, name, module, filter, source=None, *, boundary=None): except TypeError: # unless some values aren't comparable, in which case sort by name members.sort(key=lambda t: t[0]) - body = {t[0]: t[1] for t in members} - body['__module__'] = module - tmp_cls = type(name, (object, ), body) - cls = _simple_enum(etype=cls, boundary=boundary or KEEP)(tmp_cls) + cls = cls(name, members, module=module) cls.__reduce_ex__ = _reduce_ex_by_name - global_enum(cls) + module_globals.update(cls.__members__) module_globals[name] = cls return cls @@ -820,7 +588,7 @@ def _get_mixins_(class_name, bases): return object, Enum def _find_data_type(bases): - data_types = [] + data_types = set() for chain in bases: candidate = None for base in chain.__mro__: @@ -828,19 +596,19 @@ def _find_data_type(bases): continue elif issubclass(base, Enum): if base._member_type_ is not object: - data_types.append(base._member_type_) + data_types.add(base._member_type_) break elif '__new__' in base.__dict__: if issubclass(base, Enum): continue - data_types.append(candidate or base) + data_types.add(candidate or base) break else: - candidate = base + candidate = candidate or base if len(data_types) > 1: raise TypeError('%r: too many data types: %r' % (class_name, data_types)) elif data_types: - return data_types[0] + return data_types.pop() else: return None @@ -870,7 +638,7 @@ def _find_new_(classdict, member_type, first_enum): __new__ = classdict.get('__new__', None) # should __new__ be saved as __new_member__ later? - save_new = first_enum is not None and __new__ is not None + save_new = __new__ is not None if __new__ is None: # check all possibles for __new_member__ before falling back to @@ -894,21 +662,19 @@ def _find_new_(classdict, member_type, first_enum): # if a non-object.__new__ is used then whatever value/tuple was # assigned to the enum member name will be passed to __new__ and to the # new enum member's __init__ - if first_enum is None or __new__ in (Enum.__new__, object.__new__): + if __new__ is object.__new__: use_args = False else: use_args = True return __new__, save_new, use_args -EnumMeta = EnumType -class Enum(metaclass=EnumType): +class Enum(metaclass=EnumMeta): """ Generic enumeration. Derive from this class to define new enumerations. """ - def __new__(cls, value): # all enum instances are actually created during class construction # without calling this method; this method is called by the metaclass' @@ -938,11 +704,6 @@ def __new__(cls, value): try: if isinstance(result, cls): return result - elif ( - Flag is not None and issubclass(cls, Flag) - and cls._boundary_ is EJECT and isinstance(result, int) - ): - return result else: ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__)) if result is None and exc is None: @@ -982,10 +743,11 @@ def _missing_(cls, value): return None def __repr__(self): - return "%s.%s" % ( self.__class__.__name__, self._name_) + return "<%s.%s: %r>" % ( + self.__class__.__name__, self._name_, self._value_) def __str__(self): - return "%s" % (self._name_, ) + return "%s.%s" % (self.__class__.__name__, self._name_) def __dir__(self): """ @@ -1014,15 +776,6 @@ def __format__(self, format_spec): val = str(self) # mix-in branch else: - if not format_spec or format_spec in ('{}','{:}'): - import warnings - warnings.warn( - "in 3.12 format() will use the enum member, not the enum member's value;\n" - "use a format specifier, such as :d for an IntEnum member, to maintain " - "the current display", - DeprecationWarning, - stacklevel=2, - ) cls = self._member_type_ val = self._value_ return cls.__format__(val, format_spec) @@ -1033,84 +786,32 @@ def __hash__(self): def __reduce_ex__(self, proto): return self.__class__, (self._value_, ) - # enum.property is used to provide access to the `name` and - # `value` attributes of enum members while keeping some measure of + # DynamicClassAttribute is used to provide access to the `name` and + # `value` properties of enum members while keeping some measure of # protection from modification, while still allowing for an enumeration # to have members named `name` and `value`. This works because enumeration - # members are not set directly on the enum class; they are kept in a - # separate structure, _member_map_, which is where enum.property looks for - # them + # members are not set directly on the enum class -- __getattr__ is + # used to look them up. - @property + @DynamicClassAttribute def name(self): """The name of the Enum member.""" return self._name_ - @property + @DynamicClassAttribute def value(self): """The value of the Enum member.""" return self._value_ class IntEnum(int, Enum): - """ - Enum where members are also (and must be) ints - """ - - -class StrEnum(str, Enum): - """ - Enum where members are also (and must be) strings - """ - - def __new__(cls, *values): - if len(values) > 3: - raise TypeError('too many arguments for str(): %r' % (values, )) - if len(values) == 1: - # it must be a string - if not isinstance(values[0], str): - raise TypeError('%r is not a string' % (values[0], )) - if len(values) >= 2: - # check that encoding argument is a string - if not isinstance(values[1], str): - raise TypeError('encoding must be a string, not %r' % (values[1], )) - if len(values) == 3: - # check that errors argument is a string - if not isinstance(values[2], str): - raise TypeError('errors must be a string, not %r' % (values[2])) - value = str(*values) - member = str.__new__(cls, value) - member._value_ = value - return member - - __str__ = str.__str__ - - def _generate_next_value_(name, start, count, last_values): - """ - Return the lower-cased version of the member name. - """ - return name.lower() + """Enum where members are also (and must be) ints""" def _reduce_ex_by_name(self, proto): return self.name -class FlagBoundary(StrEnum): - """ - control how out of range values are handled - "strict" -> error is raised [default for Flag] - "conform" -> extra bits are discarded - "eject" -> lose flag status [default for IntFlag] - "keep" -> keep flag status and all bits - """ - STRICT = auto() - CONFORM = auto() - EJECT = auto() - KEEP = auto() -STRICT, CONFORM, EJECT, KEEP = FlagBoundary - - -class Flag(Enum, boundary=STRICT): +class Flag(Enum): """ Support for flags """ @@ -1126,110 +827,45 @@ def _generate_next_value_(name, start, count, last_values): """ if not count: return start if start is not None else 1 - last_value = max(last_values) - try: - high_bit = _high_bit(last_value) - except Exception: - raise TypeError('Invalid Flag value: %r' % last_value) from None + for last_value in reversed(last_values): + try: + high_bit = _high_bit(last_value) + break + except Exception: + raise TypeError('Invalid Flag value: %r' % last_value) from None return 2 ** (high_bit+1) @classmethod - def _iter_member_by_value_(cls, value): - """ - Extract all members from the value in definition (i.e. increasing value) order. - """ - for val in _iter_bits_lsb(value & cls._flag_mask_): - yield cls._value2member_map_.get(val) - - _iter_member_ = _iter_member_by_value_ - - @classmethod - def _iter_member_by_def_(cls, value): + def _missing_(cls, value): """ - Extract all members from the value in definition order. + Returns member (possibly creating it) if one can be found for value. """ - yield from sorted( - cls._iter_member_by_value_(value), - key=lambda m: m._sort_order_, - ) + original_value = value + if value < 0: + value = ~value + possible_member = cls._create_pseudo_member_(value) + if original_value < 0: + possible_member = ~possible_member + return possible_member @classmethod - def _missing_(cls, value): + def _create_pseudo_member_(cls, value): """ - Create a composite member containing all canonical members present in `value`. - - If non-member values are present, result depends on `_boundary_` setting. + Create a composite member iff value contains only members. """ - if not isinstance(value, int): - raise ValueError( - "%r is not a valid %s" % (value, cls.__qualname__) - ) - # check boundaries - # - value must be in range (e.g. -16 <-> +15, i.e. ~15 <-> 15) - # - value must not include any skipped flags (e.g. if bit 2 is not - # defined, then 0d10 is invalid) - flag_mask = cls._flag_mask_ - all_bits = cls._all_bits_ - neg_value = None - if ( - not ~all_bits <= value <= all_bits - or value & (all_bits ^ flag_mask) - ): - if cls._boundary_ is STRICT: - max_bits = max(value.bit_length(), flag_mask.bit_length()) - raise ValueError( - "%s: invalid value: %r\n given %s\n allowed %s" % ( - cls.__name__, value, bin(value, max_bits), bin(flag_mask, max_bits), - )) - elif cls._boundary_ is CONFORM: - value = value & flag_mask - elif cls._boundary_ is EJECT: - return value - elif cls._boundary_ is KEEP: - if value < 0: - value = ( - max(all_bits+1, 2**(value.bit_length())) - + value - ) - else: - raise ValueError( - 'unknown flag boundary: %r' % (cls._boundary_, ) - ) - if value < 0: - neg_value = value - value = all_bits + 1 + value - # get members and unknown - unknown = value & ~flag_mask - member_value = value & flag_mask - if unknown and cls._boundary_ is not KEEP: - raise ValueError( - '%s(%r) --> unknown values %r [%s]' - % (cls.__name__, value, unknown, bin(unknown)) - ) - # normal Flag? - __new__ = getattr(cls, '__new_member__', None) - if cls._member_type_ is object and not __new__: + pseudo_member = cls._value2member_map_.get(value, None) + if pseudo_member is None: + # verify all bits are accounted for + _, extra_flags = _decompose(cls, value) + if extra_flags: + raise ValueError("%r is not a valid %s" % (value, cls.__qualname__)) # construct a singleton enum pseudo-member pseudo_member = object.__new__(cls) - else: - pseudo_member = (__new__ or cls._member_type_.__new__)(cls, value) - if not hasattr(pseudo_member, '_value_'): - pseudo_member._value_ = value - if member_value: - pseudo_member._name_ = '|'.join([ - m._name_ for m in cls._iter_member_(member_value) - ]) - if unknown: - pseudo_member._name_ += '|0x%x' % unknown - else: pseudo_member._name_ = None - # use setdefault in case another thread already created a composite - # with this value, but only if all members are known - # note: zero is a special case -- add it - if not unknown: + pseudo_member._value_ = value + # use setdefault in case another thread already created a composite + # with this value pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) - if neg_value is not None: - cls._value2member_map_[neg_value] = pseudo_member return pseudo_member def __contains__(self, other): @@ -1240,42 +876,31 @@ def __contains__(self, other): raise TypeError( "unsupported operand type(s) for 'in': '%s' and '%s'" % ( type(other).__qualname__, self.__class__.__qualname__)) - if other._value_ == 0 or self._value_ == 0: - return False return other._value_ & self._value_ == other._value_ - def __iter__(self): - """ - Returns flags in definition order. - """ - yield from self._iter_member_(self._value_) - - def __len__(self): - return self._value_.bit_count() - def __repr__(self): - cls_name = self.__class__.__name__ - if self._name_ is None: - return "0x%x" % (self._value_, ) - if _is_single_bit(self._value_): - return '%s.%s' % (cls_name, self._name_) - if self._boundary_ is not FlagBoundary.KEEP: - return '%s.' % cls_name + ('|%s.' % cls_name).join(self.name.split('|')) - else: - name = [] - for n in self._name_.split('|'): - if n.startswith('0'): - name.append(n) - else: - name.append('%s.%s' % (cls_name, n)) - return '|'.join(name) + cls = self.__class__ + if self._name_ is not None: + return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_) + members, uncovered = _decompose(cls, self._value_) + return '<%s.%s: %r>' % ( + cls.__name__, + '|'.join([str(m._name_ or m._value_) for m in members]), + self._value_, + ) def __str__(self): cls = self.__class__ - if self._name_ is None: - return '%s(%x)' % (cls.__name__, self._value_) + if self._name_ is not None: + return '%s.%s' % (cls.__name__, self._name_) + members, uncovered = _decompose(cls, self._value_) + if len(members) == 1 and members[0]._name_ is None: + return '%s.%r' % (cls.__name__, members[0]._value_) else: - return self._name_ + return '%s.%s' % ( + cls.__name__, + '|'.join([str(m._name_ or m._value_) for m in members]), + ) def __bool__(self): return bool(self._value_) @@ -1296,56 +921,86 @@ def __xor__(self, other): return self.__class__(self._value_ ^ other._value_) def __invert__(self): - if self._inverted_ is None: - if self._boundary_ is KEEP: - # use all bits - self._inverted_ = self.__class__(~self._value_) - else: - # calculate flags not in this member - self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_) - self._inverted_._inverted_ = self - return self._inverted_ + members, uncovered = _decompose(self.__class__, self._value_) + inverted = self.__class__(0) + for m in self.__class__: + if m not in members and not (m._value_ & self._value_): + inverted = inverted | m + return self.__class__(inverted) -class IntFlag(int, Flag, boundary=EJECT): +class IntFlag(int, Flag): """ Support for integer-based Flags """ + @classmethod + def _missing_(cls, value): + """ + Returns member (possibly creating it) if one can be found for value. + """ + if not isinstance(value, int): + raise ValueError("%r is not a valid %s" % (value, cls.__qualname__)) + new_member = cls._create_pseudo_member_(value) + return new_member + + @classmethod + def _create_pseudo_member_(cls, value): + """ + Create a composite member iff value contains only members. + """ + pseudo_member = cls._value2member_map_.get(value, None) + if pseudo_member is None: + need_to_create = [value] + # get unaccounted for bits + _, extra_flags = _decompose(cls, value) + # timer = 10 + while extra_flags: + # timer -= 1 + bit = _high_bit(extra_flags) + flag_value = 2 ** bit + if (flag_value not in cls._value2member_map_ and + flag_value not in need_to_create + ): + need_to_create.append(flag_value) + if extra_flags == -flag_value: + extra_flags = 0 + else: + extra_flags ^= flag_value + for value in reversed(need_to_create): + # construct singleton pseudo-members + pseudo_member = int.__new__(cls, value) + pseudo_member._name_ = None + pseudo_member._value_ = value + # use setdefault in case another thread already created a composite + # with this value + pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) + return pseudo_member + def __or__(self, other): - if isinstance(other, self.__class__): - other = other._value_ - elif isinstance(other, int): - other = other - else: + if not isinstance(other, (self.__class__, int)): return NotImplemented - value = self._value_ - return self.__class__(value | other) + result = self.__class__(self._value_ | self.__class__(other)._value_) + return result def __and__(self, other): - if isinstance(other, self.__class__): - other = other._value_ - elif isinstance(other, int): - other = other - else: + if not isinstance(other, (self.__class__, int)): return NotImplemented - value = self._value_ - return self.__class__(value & other) + return self.__class__(self._value_ & self.__class__(other)._value_) def __xor__(self, other): - if isinstance(other, self.__class__): - other = other._value_ - elif isinstance(other, int): - other = other - else: + if not isinstance(other, (self.__class__, int)): return NotImplemented - value = self._value_ - return self.__class__(value ^ other) + return self.__class__(self._value_ ^ self.__class__(other)._value_) __ror__ = __or__ __rand__ = __and__ __rxor__ = __xor__ - __invert__ = Flag.__invert__ + + def __invert__(self): + result = self.__class__(~self._value_) + return result + def _high_bit(value): """ @@ -1368,348 +1023,31 @@ def unique(enumeration): (enumeration, alias_details)) return enumeration -def _power_of_two(value): - if value < 1: - return False - return value == 2 ** _high_bit(value) - -def global_enum_repr(self): - return '%s.%s' % (self.__class__.__module__, self._name_) - -def global_flag_repr(self): - module = self.__class__.__module__ - cls_name = self.__class__.__name__ - if self._name_ is None: - return "%x" % (module, cls_name, self._value_) - if _is_single_bit(self): - return '%s.%s' % (module, self._name_) - if self._boundary_ is not FlagBoundary.KEEP: - return module + module.join(self.name.split('|')) - else: - name = [] - for n in self._name_.split('|'): - if n.startswith('0'): - name.append(n) - else: - name.append('%s.%s' % (module, n)) - return '|'.join(name) - - -def global_enum(cls): - """ - decorator that makes the repr() of an enum member reference its module - instead of its class; also exports all members to the enum's module's - global namespace - """ - if issubclass(cls, Flag): - cls.__repr__ = global_flag_repr - else: - cls.__repr__ = global_enum_repr - sys.modules[cls.__module__].__dict__.update(cls.__members__) - return cls - -def _simple_enum(etype=Enum, *, boundary=None, use_args=None): +def _decompose(flag, value): """ - Class decorator that converts a normal class into an :class:`Enum`. No - safety checks are done, and some advanced behavior (such as - :func:`__init_subclass__`) is not available. Enum creation can be faster - using :func:`simple_enum`. - - >>> from enum import Enum, _simple_enum - >>> @_simple_enum(Enum) - ... class Color: - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> Color - + Extract all members from the value. """ - def convert_class(cls): - nonlocal use_args - cls_name = cls.__name__ - if use_args is None: - use_args = etype._use_args_ - __new__ = cls.__dict__.get('__new__') - if __new__ is not None: - new_member = __new__.__func__ - else: - new_member = etype._member_type_.__new__ - attrs = {} - body = {} - if __new__ is not None: - body['__new_member__'] = new_member - body['_new_member_'] = new_member - body['_use_args_'] = use_args - body['_generate_next_value_'] = gnv = etype._generate_next_value_ - body['_member_names_'] = member_names = [] - body['_member_map_'] = member_map = {} - body['_value2member_map_'] = value2member_map = {} - body['_unhashable_values_'] = [] - body['_member_type_'] = member_type = etype._member_type_ - if issubclass(etype, Flag): - body['_boundary_'] = boundary or etype._boundary_ - body['_flag_mask_'] = None - body['_all_bits_'] = None - body['_inverted_'] = None - for name, obj in cls.__dict__.items(): - if name in ('__dict__', '__weakref__'): - continue - if _is_dunder(name) or _is_private(cls_name, name) or _is_sunder(name) or _is_descriptor(obj): - body[name] = obj - else: - attrs[name] = obj - if cls.__dict__.get('__doc__') is None: - body['__doc__'] = 'An enumeration.' - # - # double check that repr and friends are not the mixin's or various - # things break (such as pickle) - # however, if the method is defined in the Enum itself, don't replace - # it - enum_class = type(cls_name, (etype, ), body, boundary=boundary, _simple=True) - for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): - if name in body: - continue - class_method = getattr(enum_class, name) - obj_method = getattr(member_type, name, None) - enum_method = getattr(etype, name, None) - if obj_method is not None and obj_method is class_method: - setattr(enum_class, name, enum_method) - gnv_last_values = [] - if issubclass(enum_class, Flag): - # Flag / IntFlag - single_bits = multi_bits = 0 - for name, value in attrs.items(): - if isinstance(value, auto) and auto.value is _auto_null: - value = gnv(name, 1, len(member_names), gnv_last_values) - if value in value2member_map: - # an alias to an existing member - redirect = property() - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = value2member_map[value] - else: - # create the member - if use_args: - if not isinstance(value, tuple): - value = (value, ) - member = new_member(enum_class, *value) - value = value[0] - else: - member = new_member(enum_class) - if __new__ is None: - member._value_ = value - member._name_ = name - member.__objclass__ = enum_class - member.__init__(value) - redirect = property() - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member - member._sort_order_ = len(member_names) - value2member_map[value] = member - if _is_single_bit(value): - # not a multi-bit alias, record in _member_names_ and _flag_mask_ - member_names.append(name) - single_bits |= value - else: - multi_bits |= value - gnv_last_values.append(value) - enum_class._flag_mask_ = single_bits - enum_class._all_bits_ = 2 ** ((single_bits|multi_bits).bit_length()) - 1 - # set correct __iter__ - member_list = [m._value_ for m in enum_class] - if member_list != sorted(member_list): - enum_class._iter_member_ = enum_class._iter_member_by_def_ - else: - # Enum / IntEnum / StrEnum - for name, value in attrs.items(): - if isinstance(value, auto): - if value.value is _auto_null: - value.value = gnv(name, 1, len(member_names), gnv_last_values) - value = value.value - if value in value2member_map: - # an alias to an existing member - redirect = property() - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = value2member_map[value] - else: - # create the member - if use_args: - if not isinstance(value, tuple): - value = (value, ) - member = new_member(enum_class, *value) - value = value[0] - else: - member = new_member(enum_class) - if __new__ is None: - member._value_ = value - member._name_ = name - member.__objclass__ = enum_class - member.__init__(value) - member._sort_order_ = len(member_names) - redirect = property() - redirect.__set_name__(enum_class, name) - setattr(enum_class, name, redirect) - member_map[name] = member - value2member_map[value] = member - member_names.append(name) - gnv_last_values.append(value) - if '__new__' in body: - enum_class.__new_member__ = enum_class.__new__ - enum_class.__new__ = Enum.__new__ - return enum_class - return convert_class - -def _test_simple_enum(checked_enum, simple_enum): - """ - A function that can be used to test an enum created with :func:`_simple_enum` - against the version created by subclassing :class:`Enum`:: - - >>> from enum import Enum, _simple_enum, _test_simple_enum - >>> @_simple_enum(Enum) - ... class Color: - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> class CheckedColor(Enum): - ... RED = auto() - ... GREEN = auto() - ... BLUE = auto() - >>> _test_simple_enum(CheckedColor, Color) - - If differences are found, a :exc:`TypeError` is raised. - """ - failed = [] - if checked_enum.__dict__ != simple_enum.__dict__: - checked_dict = checked_enum.__dict__ - checked_keys = list(checked_dict.keys()) - simple_dict = simple_enum.__dict__ - simple_keys = list(simple_dict.keys()) - member_names = set( - list(checked_enum._member_map_.keys()) - + list(simple_enum._member_map_.keys()) - ) - for key in set(checked_keys + simple_keys): - if key in ('__module__', '_member_map_', '_value2member_map_'): - # keys known to be different - continue - elif key in member_names: - # members are checked below - continue - elif key not in simple_keys: - failed.append("missing key: %r" % (key, )) - elif key not in checked_keys: - failed.append("extra key: %r" % (key, )) - else: - checked_value = checked_dict[key] - simple_value = simple_dict[key] - if callable(checked_value): - continue - if key == '__doc__': - # remove all spaces/tabs - compressed_checked_value = checked_value.replace(' ','').replace('\t','') - compressed_simple_value = simple_value.replace(' ','').replace('\t','') - if compressed_checked_value != compressed_simple_value: - failed.append("%r:\n %s\n %s" % ( - key, - "checked -> %r" % (checked_value, ), - "simple -> %r" % (simple_value, ), - )) - elif checked_value != simple_value: - failed.append("%r:\n %s\n %s" % ( - key, - "checked -> %r" % (checked_value, ), - "simple -> %r" % (simple_value, ), - )) - failed.sort() - for name in member_names: - failed_member = [] - if name not in simple_keys: - failed.append('missing member from simple enum: %r' % name) - elif name not in checked_keys: - failed.append('extra member in simple enum: %r' % name) - else: - checked_member_dict = checked_enum[name].__dict__ - checked_member_keys = list(checked_member_dict.keys()) - simple_member_dict = simple_enum[name].__dict__ - simple_member_keys = list(simple_member_dict.keys()) - for key in set(checked_member_keys + simple_member_keys): - if key in ('__module__', '__objclass__', '_inverted_'): - # keys known to be different or absent - continue - elif key not in simple_member_keys: - failed_member.append("missing key %r not in the simple enum member %r" % (key, name)) - elif key not in checked_member_keys: - failed_member.append("extra key %r in simple enum member %r" % (key, name)) - else: - checked_value = checked_member_dict[key] - simple_value = simple_member_dict[key] - if checked_value != simple_value: - failed_member.append("%r:\n %s\n %s" % ( - key, - "checked member -> %r" % (checked_value, ), - "simple member -> %r" % (simple_value, ), - )) - if failed_member: - failed.append('%r member mismatch:\n %s' % ( - name, '\n '.join(failed_member), - )) - for method in ( - '__str__', '__repr__', '__reduce_ex__', '__format__', - '__getnewargs_ex__', '__getnewargs__', '__reduce_ex__', '__reduce__' - ): - if method in simple_keys and method in checked_keys: - # cannot compare functions, and it exists in both, so we're good - continue - elif method not in simple_keys and method not in checked_keys: - # method is inherited -- check it out - checked_method = getattr(checked_enum, method, None) - simple_method = getattr(simple_enum, method, None) - if hasattr(checked_method, '__func__'): - checked_method = checked_method.__func__ - simple_method = simple_method.__func__ - if checked_method != simple_method: - failed.append("%r: %-30s %s" % ( - method, - "checked -> %r" % (checked_method, ), - "simple -> %r" % (simple_method, ), - )) - else: - # if the method existed in only one of the enums, it will have been caught - # in the first checks above - pass - if failed: - raise TypeError('enum mismatch:\n %s' % '\n '.join(failed)) - -def _old_convert_(etype, name, module, filter, source=None, *, boundary=None): - """ - Create a new Enum subclass that replaces a collection of global constants - """ - # convert all constants from source (or module) that pass filter() to - # a new Enum called name, and export the enum and its members back to - # module; - # also, replace the __reduce_ex__ method so unpickling works in - # previous Python versions - module_globals = sys.modules[module].__dict__ - if source: - source = source.__dict__ - else: - source = module_globals - # _value2member_map_ is populated in the same order every time - # for a consistent reverse mapping of number to name when there - # are multiple names for the same number. - members = [ - (name, value) - for name, value in source.items() - if filter(name)] - try: - # sort by value - members.sort(key=lambda t: (t[1], t[0])) - except TypeError: - # unless some values aren't comparable, in which case sort by name - members.sort(key=lambda t: t[0]) - cls = etype(name, members, module=module, boundary=boundary or KEEP) - cls.__reduce_ex__ = _reduce_ex_by_name - cls.__repr__ = global_enum_repr - return cls + # _decompose is only called if the value is not named + not_covered = value + negative = value < 0 + members = [] + for member in flag: + member_value = member.value + if member_value and member_value & value == member_value: + members.append(member) + not_covered &= ~member_value + if not negative: + tmp = not_covered + while tmp: + flag_value = 2 ** _high_bit(tmp) + if flag_value in flag._value2member_map_: + members.append(flag._value2member_map_[flag_value]) + not_covered &= ~flag_value + tmp &= ~flag_value + if not members and value in flag._value2member_map_: + members.append(flag._value2member_map_[value]) + members.sort(key=lambda m: m._value_, reverse=True) + if len(members) > 1 and members[0].value == value: + # we have the breakdown, don't need the value member itself + members.pop(0) + return members, not_covered diff --git a/Lib/filecmp.py b/Lib/filecmp.py index 7c47eb022cc8c0..70a4b23c982205 100644 --- a/Lib/filecmp.py +++ b/Lib/filecmp.py @@ -36,8 +36,9 @@ def cmp(f1, f2, shallow=True): f2 -- Second file name - shallow -- Just check stat signature (do not read the files). - defaults to True. + shallow -- treat files as identical if their stat signatures (type, size, + mtime) are identical. Otherwise, files are considered different + if their sizes or contents differ. [default: True] Return value: diff --git a/Lib/functools.py b/Lib/functools.py index b1f1fe8d9a6f27..305ceb450a71c4 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -88,84 +88,84 @@ def wraps(wrapped, def _gt_from_lt(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).' - op_result = self.__lt__(other) + op_result = type(self).__lt__(self, other) if op_result is NotImplemented: return op_result return not op_result and self != other def _le_from_lt(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).' - op_result = self.__lt__(other) + op_result = type(self).__lt__(self, other) if op_result is NotImplemented: return op_result return op_result or self == other def _ge_from_lt(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (not a < b).' - op_result = self.__lt__(other) + op_result = type(self).__lt__(self, other) if op_result is NotImplemented: return op_result return not op_result def _ge_from_le(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).' - op_result = self.__le__(other) + op_result = type(self).__le__(self, other) if op_result is NotImplemented: return op_result return not op_result or self == other def _lt_from_le(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).' - op_result = self.__le__(other) + op_result = type(self).__le__(self, other) if op_result is NotImplemented: return op_result return op_result and self != other def _gt_from_le(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (not a <= b).' - op_result = self.__le__(other) + op_result = type(self).__le__(self, other) if op_result is NotImplemented: return op_result return not op_result def _lt_from_gt(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).' - op_result = self.__gt__(other) + op_result = type(self).__gt__(self, other) if op_result is NotImplemented: return op_result return not op_result and self != other def _ge_from_gt(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).' - op_result = self.__gt__(other) + op_result = type(self).__gt__(self, other) if op_result is NotImplemented: return op_result return op_result or self == other def _le_from_gt(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (not a > b).' - op_result = self.__gt__(other) + op_result = type(self).__gt__(self, other) if op_result is NotImplemented: return op_result return not op_result def _le_from_ge(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).' - op_result = self.__ge__(other) + op_result = type(self).__ge__(self, other) if op_result is NotImplemented: return op_result return not op_result or self == other def _gt_from_ge(self, other, NotImplemented=NotImplemented): 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).' - op_result = self.__ge__(other) + op_result = type(self).__ge__(self, other) if op_result is NotImplemented: return op_result return op_result and self != other def _lt_from_ge(self, other, NotImplemented=NotImplemented): 'Return a < b. Computed by @total_ordering from (not a >= b).' - op_result = self.__ge__(other) + op_result = type(self).__ge__(self, other) if op_result is NotImplemented: return op_result return not op_result @@ -492,7 +492,7 @@ def lru_cache(maxsize=128, typed=False): with f.cache_info(). Clear the cache and statistics with f.cache_clear(). Access the underlying function with f.__wrapped__. - See: http://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU) + See: https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU) """ @@ -660,7 +660,7 @@ def cache(user_function, /): def _c3_merge(sequences): """Merges MROs in *sequences* to a single MRO using the C3 algorithm. - Adapted from http://www.python.org/download/releases/2.3/mro/. + Adapted from https://www.python.org/download/releases/2.3/mro/. """ result = [] @@ -740,6 +740,7 @@ def _compose_mro(cls, types): # Remove entries which are already present in the __mro__ or unrelated. def is_related(typ): return (typ not in bases and hasattr(typ, '__mro__') + and not isinstance(typ, GenericAlias) and issubclass(cls, typ)) types = [n for n in types if is_related(n)] # Remove entries which are strict bases of other entries (they will end up @@ -837,6 +838,9 @@ def dispatch(cls): dispatch_cache[cls] = impl return impl + def _is_valid_dispatch_type(cls): + return isinstance(cls, type) and not isinstance(cls, GenericAlias) + def register(cls, func=None): """generic_func.register(cls, func) -> func @@ -844,9 +848,15 @@ def register(cls, func=None): """ nonlocal cache_token - if func is None: - if isinstance(cls, type): + if _is_valid_dispatch_type(cls): + if func is None: return lambda f: register(cls, f) + else: + if func is not None: + raise TypeError( + f"Invalid first argument to `register()`. " + f"{cls!r} is not a class." + ) ann = getattr(cls, '__annotations__', {}) if not ann: raise TypeError( @@ -859,11 +869,12 @@ def register(cls, func=None): # only import typing if annotation parsing is necessary from typing import get_type_hints argname, cls = next(iter(get_type_hints(func).items())) - if not isinstance(cls, type): + if not _is_valid_dispatch_type(cls): raise TypeError( f"Invalid annotation for {argname!r}. " f"{cls!r} is not a class." ) + registry[cls] = func if cache_token is None and hasattr(cls, '__abstractmethods__'): cache_token = get_cache_token() diff --git a/Lib/getpass.py b/Lib/getpass.py index 6911f41d1f2054..6970d8adfbab36 100644 --- a/Lib/getpass.py +++ b/Lib/getpass.py @@ -95,7 +95,7 @@ def unix_getpass(prompt='Password: ', stream=None): def win_getpass(prompt='Password: ', stream=None): - """Prompt for password with echo off, using Windows getch().""" + """Prompt for password with echo off, using Windows getwch().""" if sys.stdin is not sys.__stdin__: return fallback_getpass(prompt, stream) diff --git a/Lib/glob.py b/Lib/glob.py index a6cff873508266..9fc08f45df115a 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -1,5 +1,6 @@ """Filename globbing utility.""" +import contextlib import os import re import fnmatch @@ -90,7 +91,7 @@ def _iglob(pathname, root_dir, dir_fd, recursive, dironly): # takes a literal basename (so it only has to check for its existence). def _glob1(dirname, pattern, dir_fd, dironly): - names = list(_iterdir(dirname, dir_fd, dironly)) + names = _listdir(dirname, dir_fd, dironly) if not _ishidden(pattern): names = (x for x in names if not _ishidden(x)) return fnmatch.filter(names, pattern) @@ -158,9 +159,13 @@ def _iterdir(dirname, dir_fd, dironly): except OSError: return +def _listdir(dirname, dir_fd, dironly): + with contextlib.closing(_iterdir(dirname, dir_fd, dironly)) as it: + return list(it) + # Recursively yields relative pathnames inside a literal directory. def _rlistdir(dirname, dir_fd, dironly): - names = list(_iterdir(dirname, dir_fd, dironly)) + names = _listdir(dirname, dir_fd, dironly) for x in names: if not _ishidden(x): yield x diff --git a/Lib/graphlib.py b/Lib/graphlib.py index d0e7a4814c565d..1c5d9a413c944d 100644 --- a/Lib/graphlib.py +++ b/Lib/graphlib.py @@ -17,7 +17,7 @@ def __init__(self, node): self.npredecessors = 0 # List of successor nodes. The list can contain duplicated elements as - # long as they're all reflected in the successor's npredecessors attribute). + # long as they're all reflected in the successor's npredecessors attribute. self.successors = [] diff --git a/Lib/gzip.py b/Lib/gzip.py index 9a4e0f9c00c580..475ec326c0c982 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -278,7 +278,7 @@ def write(self,data): if self.fileobj is None: raise ValueError("write() on closed GzipFile object") - if isinstance(data, bytes): + if isinstance(data, (bytes, bytearray)): length = len(data) else: # accept any data that supports the buffer protocol @@ -398,10 +398,6 @@ def readline(self, size=-1): self._check_not_closed() return self._buffer.readline(size) - def __iter__(self): - self._check_not_closed() - return self._buffer.__iter__() - class _GzipReader(_compression.DecompressReader): def __init__(self, fp): @@ -521,7 +517,7 @@ def _add_read_data(self, data): def _read_eof(self): # We've read to the end of the file - # We check the that the computed CRC and size of the + # We check that the computed CRC and size of the # uncompressed data matches the stored values. Note that the size # stored is the true file size mod 2**32. crc32, isize = struct.unpack(" # Note: this is not 100% correct, since we might have things like - # , but looking for > after tha name should cover + # , but looking for > after the name should cover # most of the cases and is much simpler gtpos = rawdata.find('>', namematch.end()) self.handle_endtag(tagname) diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index 8b980e24a5603f..bf8d7d6886838c 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -1,10 +1,9 @@ -from enum import IntEnum, _simple_enum +from enum import IntEnum __all__ = ['HTTPStatus'] -@_simple_enum(IntEnum) -class HTTPStatus: +class HTTPStatus(IntEnum): """HTTP status codes and reason phrases Status codes from the following RFCs are all observed: diff --git a/Lib/http/client.py b/Lib/http/client.py index 4b1f692844474f..a6ab135b2c3879 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -70,6 +70,7 @@ import email.parser import email.message +import errno import http import io import re @@ -202,15 +203,11 @@ def getallmatchingheaders(self, name): lst.append(line) return lst -def parse_headers(fp, _class=HTTPMessage): - """Parses only RFC2822 headers from a file pointer. - - email Parser wants to see strings rather than bytes. - But a TextIOWrapper around self.rfile would buffer too many bytes - from the stream, bytes which we later need to read as bytes. - So we read the correct bytes here, as bytes, for email Parser - to parse. +def _read_headers(fp): + """Reads potential header lines into a list from a file pointer. + Length of line is limited by _MAXLINE, and number of + headers is limited by _MAXHEADERS. """ headers = [] while True: @@ -222,6 +219,19 @@ def parse_headers(fp, _class=HTTPMessage): raise HTTPException("got more than %d headers" % _MAXHEADERS) if line in (b'\r\n', b'\n', b''): break + return headers + +def parse_headers(fp, _class=HTTPMessage): + """Parses only RFC2822 headers from a file pointer. + + email Parser wants to see strings rather than bytes. + But a TextIOWrapper around self.rfile would buffer too many bytes + from the stream, bytes which we later need to read as bytes. + So we read the correct bytes here, as bytes, for email Parser + to parse. + + """ + headers = _read_headers(fp) hstring = b''.join(headers).decode('iso-8859-1') return email.parser.Parser(_class=_class).parsestr(hstring) @@ -309,15 +319,10 @@ def begin(self): if status != CONTINUE: break # skip the header from the 100 response - while True: - skip = self.fp.readline(_MAXLINE + 1) - if len(skip) > _MAXLINE: - raise LineTooLong("header line") - skip = skip.strip() - if not skip: - break - if self.debuglevel > 0: - print("header:", skip) + skipped_headers = _read_headers(self.fp) + if self.debuglevel > 0: + print("headers:", skipped_headers) + del skipped_headers self.code = self.status = status self.reason = reason.strip() @@ -935,7 +940,12 @@ def connect(self): sys.audit("http.client.connect", self, self.host, self.port) self.sock = self._create_connection( (self.host,self.port), self.timeout, self.source_address) - self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + # Might fail in OSs that don't implement TCP_NODELAY + try: + self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + except OSError as e: + if e.errno != errno.ENOPROTOOPT: + raise if self._tunnel_host: self._tunnel() diff --git a/Lib/http/server.py b/Lib/http/server.py index 94f730ed3445be..e985dfd5640086 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -689,6 +689,7 @@ def send_head(self): parts[3], parts[4]) new_url = urllib.parse.urlunsplit(new_parts) self.send_header("Location", new_url) + self.send_header("Content-Length", "0") self.end_headers() return None for index in "index.html", "index.htm": diff --git a/Lib/idlelib/ChangeLog b/Lib/idlelib/ChangeLog index d7d7e1efdb1d30..c8960cfa535d03 100644 --- a/Lib/idlelib/ChangeLog +++ b/Lib/idlelib/ChangeLog @@ -1175,7 +1175,7 @@ Wed Mar 10 05:18:02 1999 Guido van Rossum classes in selected module methods of selected class - Sinlge clicking in a directory, module or class item updates the next + Single clicking in a directory, module or class item updates the next column with info about the selected item. Double clicking in a module, class or method item opens the file (and selects the clicked item if it is a class or method). diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index ed1142653d9534..396820e9117b53 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -4,6 +4,9 @@ Released on 2021-10-04? ========================= +bpo-44026: Include interpreter's typo fix suggestions in message line +for NameErrors and AttributeErrors. Patch by E. Paine. + bpo-37903: Add mouse actions to the shell sidebar. Left click and optional drag selects one or more lines of text, as with the editor line number sidebar. Right click after selecting text lines diff --git a/Lib/idlelib/autocomplete.py b/Lib/idlelib/autocomplete.py index bb7ee035c4fefb..032d31225315fb 100644 --- a/Lib/idlelib/autocomplete.py +++ b/Lib/idlelib/autocomplete.py @@ -9,6 +9,12 @@ import string import sys +# Modified keyword list is used in fetch_completions. +completion_kwds = [s for s in keyword.kwlist + if s not in {'True', 'False', 'None'}] # In builtins. +completion_kwds.extend(('match', 'case')) # Context keywords. +completion_kwds.sort() + # Two types of completions; defined here for autocomplete_w import below. ATTRS, FILES = 0, 1 from idlelib import autocomplete_w @@ -177,9 +183,7 @@ def fetch_completions(self, what, mode): namespace = {**__main__.__builtins__.__dict__, **__main__.__dict__} bigl = eval("dir()", namespace) - kwds = (s for s in keyword.kwlist - if s not in {'True', 'False', 'None'}) - bigl.extend(kwds) + bigl.extend(completion_kwds) bigl.sort() if "__all__" in bigl: smalll = sorted(eval("__all__", namespace)) diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index d3d1e6982bfb2e..0f835a9cc1d010 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -206,6 +206,7 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): scrollbar.config(command=listbox.yview) scrollbar.pack(side=RIGHT, fill=Y) listbox.pack(side=LEFT, fill=BOTH, expand=True) + #acw.update_idletasks() # Need for tk8.6.8 on macOS: #40128. acw.lift() # work around bug in Tk 8.5.18+ (issue #24570) # Initialize the listbox selection @@ -242,31 +243,46 @@ def winconfig_event(self, event): self.is_configuring = True if not self.is_active(): return - # Position the completion list window - text = self.widget - text.see(self.startindex) - x, y, cx, cy = text.bbox(self.startindex) - acw = self.autocompletewindow - acw.update() - acw_width, acw_height = acw.winfo_width(), acw.winfo_height() - text_width, text_height = text.winfo_width(), text.winfo_height() - new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) - new_y = text.winfo_rooty() + y - if (text_height - (y + cy) >= acw_height # enough height below - or y < acw_height): # not enough height above - # place acw below current line - new_y += cy - else: - # place acw above current line - new_y -= acw_height - acw.wm_geometry("+%d+%d" % (new_x, new_y)) - acw.update_idletasks() + + # Since the event may occur after the completion window is gone, + # catch potential TclError exceptions when accessing acw. See: bpo-41611. + try: + # Position the completion list window + text = self.widget + text.see(self.startindex) + x, y, cx, cy = text.bbox(self.startindex) + acw = self.autocompletewindow + if platform.system().startswith('Windows'): + # On Windows an update() call is needed for the completion + # list window to be created, so that we can fetch its width + # and height. However, this is not needed on other platforms + # (tested on Ubuntu and macOS) but at one point began + # causing freezes on macOS. See issues 37849 and 41611. + acw.update() + acw_width, acw_height = acw.winfo_width(), acw.winfo_height() + text_width, text_height = text.winfo_width(), text.winfo_height() + new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) + new_y = text.winfo_rooty() + y + if (text_height - (y + cy) >= acw_height # enough height below + or y < acw_height): # not enough height above + # place acw below current line + new_y += cy + else: + # place acw above current line + new_y -= acw_height + acw.wm_geometry("+%d+%d" % (new_x, new_y)) + acw.update_idletasks() + except TclError: + pass if platform.system().startswith('Windows'): - # See issue 15786. When on Windows platform, Tk will misbehave + # See issue 15786. When on Windows platform, Tk will misbehave # to call winconfig_event multiple times, we need to prevent this, # otherwise mouse button double click will not be able to used. - acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + try: + acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + except TclError: + pass self.winconfigid = None self.is_configuring = False diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 3c527409731afa..e9f19c145c8673 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -16,6 +16,32 @@ def any(name, alternates): def make_pat(): kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" + match_softkw = ( + r"^[ \t]*" + # at beginning of line + possible indentation + r"(?Pmatch)\b" + + r"(?![ \t]*(?:" + "|".join([ # not followed by ... + r"[:,;=^&|@~)\]}]", # a character which means it can't be a + # pattern-matching statement + r"\b(?:" + r"|".join(keyword.kwlist) + r")\b", # a keyword + ]) + + r"))" + ) + case_default = ( + r"^[ \t]*" + # at beginning of line + possible indentation + r"(?Pcase)" + + r"[ \t]+(?P_\b)" + ) + case_softkw_and_pattern = ( + r"^[ \t]*" + # at beginning of line + possible indentation + r"(?Pcase)\b" + + r"(?![ \t]*(?:" + "|".join([ # not followed by ... + r"_\b", # a lone underscore + r"[:,;=^&|@~)\]}]", # a character which means it can't be a + # pattern-matching case + r"\b(?:" + r"|".join(keyword.kwlist) + r")\b", # a keyword + ]) + + r"))" + ) builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_') and name not in keyword.kwlist] @@ -27,12 +53,29 @@ def make_pat(): sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) - return (kw + "|" + builtin + "|" + comment + "|" + string + - "|" + any("SYNC", [r"\n"])) + prog = re.compile("|".join([ + builtin, comment, string, kw, + match_softkw, case_default, + case_softkw_and_pattern, + any("SYNC", [r"\n"]), + ]), + re.DOTALL | re.MULTILINE) + return prog -prog = re.compile(make_pat(), re.S) -idprog = re.compile(r"\s+(\w+)", re.S) +prog = make_pat() +idprog = re.compile(r"\s+(\w+)") +prog_group_name_to_tag = { + "MATCH_SOFTKW": "KEYWORD", + "CASE_SOFTKW": "KEYWORD", + "CASE_DEFAULT_UNDERSCORE": "KEYWORD", + "CASE_SOFTKW2": "KEYWORD", +} + + +def matched_named_groups(re_match): + "Get only the non-empty named groups from an re.Match object." + return ((k, v) for (k, v) in re_match.groupdict().items() if v) def color_config(text): @@ -231,14 +274,10 @@ def recolorize(self): def recolorize_main(self): "Evaluate text and apply colorizing tags." next = "1.0" - while True: - item = self.tag_nextrange("TODO", next) - if not item: - break - head, tail = item - self.tag_remove("SYNC", head, tail) - item = self.tag_prevrange("SYNC", head) - head = item[1] if item else "1.0" + while todo_tag_range := self.tag_nextrange("TODO", next): + self.tag_remove("SYNC", todo_tag_range[0], todo_tag_range[1]) + sync_tag_range = self.tag_prevrange("SYNC", todo_tag_range[0]) + head = sync_tag_range[1] if sync_tag_range else "1.0" chars = "" next = head @@ -256,23 +295,8 @@ def recolorize_main(self): return for tag in self.tagdefs: self.tag_remove(tag, mark, next) - chars = chars + line - m = self.prog.search(chars) - while m: - for key, value in m.groupdict().items(): - if value: - a, b = m.span(key) - self.tag_add(key, - head + "+%dc" % a, - head + "+%dc" % b) - if value in ("def", "class"): - m1 = self.idprog.match(chars, b) - if m1: - a, b = m1.span(1) - self.tag_add("DEFINITION", - head + "+%dc" % a, - head + "+%dc" % b) - m = self.prog.search(chars, m.end()) + chars += line + self._add_tags_in_section(chars, head) if "SYNC" in self.tag_names(next + "-1c"): head = next chars = "" @@ -291,6 +315,40 @@ def recolorize_main(self): if DEBUG: print("colorizing stopped") return + def _add_tag(self, start, end, head, matched_group_name): + """Add a tag to a given range in the text widget. + + This is a utility function, receiving the range as `start` and + `end` positions, each of which is a number of characters + relative to the given `head` index in the text widget. + + The tag to add is determined by `matched_group_name`, which is + the name of a regular expression "named group" as matched by + by the relevant highlighting regexps. + """ + tag = prog_group_name_to_tag.get(matched_group_name, + matched_group_name) + self.tag_add(tag, + f"{head}+{start:d}c", + f"{head}+{end:d}c") + + def _add_tags_in_section(self, chars, head): + """Parse and add highlighting tags to a given part of the text. + + `chars` is a string with the text to parse and to which + highlighting is to be applied. + + `head` is the index in the text widget where the text is found. + """ + for m in self.prog.finditer(chars): + for name, matched_text in matched_named_groups(m): + a, b = m.span(name) + self._add_tag(a, b, head, name) + if matched_text in ("def", "class"): + if m1 := self.idprog.match(chars, b): + a, b = m1.span(1) + self._add_tag(a, b, head, "DEFINITION") + def removecolors(self): "Remove all colorizing tags." for tag in self.tagdefs: @@ -299,27 +357,14 @@ def removecolors(self): def _color_delegator(parent): # htest # from tkinter import Toplevel, Text + from idlelib.idle_test.test_colorizer import source from idlelib.percolator import Percolator top = Toplevel(parent) top.title("Test ColorDelegator") x, y = map(int, parent.geometry().split('+')[1:]) - top.geometry("700x250+%d+%d" % (x + 20, y + 175)) - source = ( - "if True: int ('1') # keyword, builtin, string, comment\n" - "elif False: print(0)\n" - "else: float(None)\n" - "if iF + If + IF: 'keyword matching must respect case'\n" - "if'': x or'' # valid keyword-string no-space combinations\n" - "async def f(): await g()\n" - "# All valid prefixes for unicode and byte strings should be colored.\n" - "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" - "r'x', u'x', R'x', U'x', f'x', F'x'\n" - "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" - "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n" - "# Invalid combinations of legal characters should be half colored.\n" - "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" - ) + top.geometry("700x550+%d+%d" % (x + 20, y + 175)) + text = Text(top, background="white") text.pack(expand=1, fill="both") text.insert("insert", source) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index c52a04b503adb4..6d0893680274b3 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -15,9 +15,10 @@ StringVar, BooleanVar, IntVar, TRUE, FALSE, TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE, NONE, BOTH, X, Y, W, E, EW, NS, NSEW, NW, - HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END) + HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END, TclError) from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label, - OptionMenu, Notebook, Radiobutton, Scrollbar, Style) + OptionMenu, Notebook, Radiobutton, Scrollbar, Style, + Spinbox, Combobox) from tkinter import colorchooser import tkinter.font as tkfont from tkinter import messagebox @@ -101,8 +102,9 @@ def create_widgets(self): highpage: HighPage fontpage: FontPage keyspage: KeysPage - genpage: GenPage - extpage: self.create_page_extensions + winpage: WinPage + shedpage: ShedPage + extpage: ExtPage Methods: create_action_buttons @@ -112,15 +114,18 @@ def create_widgets(self): self.frame = frame = Frame(self, padding="5px") self.frame.grid(sticky="nwes") self.note = note = Notebook(frame) - self.highpage = HighPage(note) + self.extpage = ExtPage(note) + self.highpage = HighPage(note, self.extpage) self.fontpage = FontPage(note, self.highpage) - self.keyspage = KeysPage(note) - self.genpage = GenPage(note) - self.extpage = self.create_page_extensions() + self.keyspage = KeysPage(note, self.extpage) + self.winpage = WinPage(note) + self.shedpage = ShedPage(note) + note.add(self.fontpage, text='Fonts/Tabs') note.add(self.highpage, text='Highlights') note.add(self.keyspage, text=' Keys ') - note.add(self.genpage, text=' General ') + note.add(self.winpage, text=' Windows ') + note.add(self.shedpage, text=' Shell/Ed ') note.add(self.extpage, text='Extensions') note.enable_traversal() note.pack(side=TOP, expand=TRUE, fill=BOTH) @@ -167,26 +172,15 @@ def create_action_buttons(self): return outer def ok(self): - """Apply config changes, then dismiss dialog. - - Methods: - apply - destroy: inherited - """ + """Apply config changes, then dismiss dialog.""" self.apply() self.destroy() def apply(self): - """Apply config changes and leave dialog open. - - Methods: - deactivate_current_config - save_all_changed_extensions - activate_config_changes - """ + """Apply config changes and leave dialog open.""" self.deactivate_current_config() changes.save_all() - self.save_all_changed_extensions() + self.extpage.save_all_changed_extensions() self.activate_config_changes() def cancel(self): @@ -244,190 +238,6 @@ def activate_config_changes(self): for klass in reloadables: klass.reload() - def create_page_extensions(self): - """Part of the config dialog used for configuring IDLE extensions. - - This code is generic - it works for any and all IDLE extensions. - - IDLE extensions save their configuration options using idleConf. - This code reads the current configuration using idleConf, supplies a - GUI interface to change the configuration values, and saves the - changes using idleConf. - - Not all changes take effect immediately - some may require restarting IDLE. - This depends on each extension's implementation. - - All values are treated as text, and it is up to the user to supply - reasonable values. The only exception to this are the 'enable*' options, - which are boolean, and can be toggled with a True/False button. - - Methods: - load_extensions: - extension_selected: Handle selection from list. - create_extension_frame: Hold widgets for one extension. - set_extension_value: Set in userCfg['extensions']. - save_all_changed_extensions: Call extension page Save(). - """ - parent = self.parent - frame = Frame(self.note) - self.ext_defaultCfg = idleConf.defaultCfg['extensions'] - self.ext_userCfg = idleConf.userCfg['extensions'] - self.is_int = self.register(is_int) - self.load_extensions() - # Create widgets - a listbox shows all available extensions, with the - # controls for the extension selected in the listbox to the right. - self.extension_names = StringVar(self) - frame.rowconfigure(0, weight=1) - frame.columnconfigure(2, weight=1) - self.extension_list = Listbox(frame, listvariable=self.extension_names, - selectmode='browse') - self.extension_list.bind('<>', self.extension_selected) - scroll = Scrollbar(frame, command=self.extension_list.yview) - self.extension_list.yscrollcommand=scroll.set - self.details_frame = LabelFrame(frame, width=250, height=250) - self.extension_list.grid(column=0, row=0, sticky='nws') - scroll.grid(column=1, row=0, sticky='ns') - self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) - frame.configure(padding=10) - self.config_frame = {} - self.current_extension = None - - self.outerframe = self # TEMPORARY - self.tabbed_page_set = self.extension_list # TEMPORARY - - # Create the frame holding controls for each extension. - ext_names = '' - for ext_name in sorted(self.extensions): - self.create_extension_frame(ext_name) - ext_names = ext_names + '{' + ext_name + '} ' - self.extension_names.set(ext_names) - self.extension_list.selection_set(0) - self.extension_selected(None) - - return frame - - def load_extensions(self): - "Fill self.extensions with data from the default and user configs." - self.extensions = {} - for ext_name in idleConf.GetExtensions(active_only=False): - # Former built-in extensions are already filtered out. - self.extensions[ext_name] = [] - - for ext_name in self.extensions: - opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) - - # Bring 'enable' options to the beginning of the list. - enables = [opt_name for opt_name in opt_list - if opt_name.startswith('enable')] - for opt_name in enables: - opt_list.remove(opt_name) - opt_list = enables + opt_list - - for opt_name in opt_list: - def_str = self.ext_defaultCfg.Get( - ext_name, opt_name, raw=True) - try: - def_obj = {'True':True, 'False':False}[def_str] - opt_type = 'bool' - except KeyError: - try: - def_obj = int(def_str) - opt_type = 'int' - except ValueError: - def_obj = def_str - opt_type = None - try: - value = self.ext_userCfg.Get( - ext_name, opt_name, type=opt_type, raw=True, - default=def_obj) - except ValueError: # Need this until .Get fixed. - value = def_obj # Bad values overwritten by entry. - var = StringVar(self) - var.set(str(value)) - - self.extensions[ext_name].append({'name': opt_name, - 'type': opt_type, - 'default': def_str, - 'value': value, - 'var': var, - }) - - def extension_selected(self, event): - "Handle selection of an extension from the list." - newsel = self.extension_list.curselection() - if newsel: - newsel = self.extension_list.get(newsel) - if newsel is None or newsel != self.current_extension: - if self.current_extension: - self.details_frame.config(text='') - self.config_frame[self.current_extension].grid_forget() - self.current_extension = None - if newsel: - self.details_frame.config(text=newsel) - self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') - self.current_extension = newsel - - def create_extension_frame(self, ext_name): - """Create a frame holding the widgets to configure one extension""" - f = VerticalScrolledFrame(self.details_frame, height=250, width=250) - self.config_frame[ext_name] = f - entry_area = f.interior - # Create an entry for each configuration option. - for row, opt in enumerate(self.extensions[ext_name]): - # Create a row with a label and entry/checkbutton. - label = Label(entry_area, text=opt['name']) - label.grid(row=row, column=0, sticky=NW) - var = opt['var'] - if opt['type'] == 'bool': - Checkbutton(entry_area, variable=var, - onvalue='True', offvalue='False', width=8 - ).grid(row=row, column=1, sticky=W, padx=7) - elif opt['type'] == 'int': - Entry(entry_area, textvariable=var, validate='key', - validatecommand=(self.is_int, '%P'), width=10 - ).grid(row=row, column=1, sticky=NSEW, padx=7) - - else: # type == 'str' - # Limit size to fit non-expanding space with larger font. - Entry(entry_area, textvariable=var, width=15 - ).grid(row=row, column=1, sticky=NSEW, padx=7) - return - - def set_extension_value(self, section, opt): - """Return True if the configuration was added or changed. - - If the value is the same as the default, then remove it - from user config file. - """ - name = opt['name'] - default = opt['default'] - value = opt['var'].get().strip() or default - opt['var'].set(value) - # if self.defaultCfg.has_section(section): - # Currently, always true; if not, indent to return. - if (value == default): - return self.ext_userCfg.RemoveOption(section, name) - # Set the option. - return self.ext_userCfg.SetOption(section, name, value) - - def save_all_changed_extensions(self): - """Save configuration changes to the user config file. - - Attributes accessed: - extensions - - Methods: - set_extension_value - """ - has_changes = False - for ext_name in self.extensions: - options = self.extensions[ext_name] - for opt in options: - if self.set_extension_value(ext_name, opt): - has_changes = True - if has_changes: - self.ext_userCfg.Save() - # class TabPage(Frame): # A template for Page classes. # def __init__(self, master): @@ -480,12 +290,11 @@ class FontPage(Frame): def __init__(self, master, highpage): super().__init__(master) self.highlight_sample = highpage.highlight_sample - self.create_page_font_tab() + self.create_page_font() self.load_font_cfg() - self.load_tab_cfg() - def create_page_font_tab(self): - """Return frame of widgets for Font/Tabs tab. + def create_page_font(self): + """Return frame of widgets for Font tab. Fonts: Enable users to provisionally change font face, size, or boldness and to see the consequence of proposed choices. Each @@ -509,11 +318,6 @@ def create_page_font_tab(self): Set_samples applies a new font constructed from the font vars to font_sample and to highlight_sample on the highlight page. - Tabs: Enable users to change spaces entered for indent tabs. - Changing indent_scale value with the mouse sets Var space_num, - which invokes the default callback to add an entry to - changes. Load_tab_cfg initializes space_num to default. - Widgets for FontPage(Frame): (*) widgets bound to self frame_font: LabelFrame frame_font_name: Frame @@ -526,23 +330,16 @@ def create_page_font_tab(self): (*)bold_toggle: Checkbutton - font_bold frame_sample: LabelFrame (*)font_sample: Label - frame_indent: LabelFrame - indent_title: Label - (*)indent_scale: Scale - space_num """ self.font_name = tracers.add(StringVar(self), self.var_changed_font) self.font_size = tracers.add(StringVar(self), self.var_changed_font) self.font_bold = tracers.add(BooleanVar(self), self.var_changed_font) - self.space_num = tracers.add(IntVar(self), ('main', 'Indent', 'num-spaces')) # Define frames and widgets. - frame_font = LabelFrame( - self, borderwidth=2, relief=GROOVE, text=' Shell/Editor Font ') - frame_sample = LabelFrame( - self, borderwidth=2, relief=GROOVE, - text=' Font Sample (Editable) ') - frame_indent = LabelFrame( - self, borderwidth=2, relief=GROOVE, text=' Indentation Width ') + frame_font = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Shell/Editor Font ') + frame_sample = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Font Sample (Editable) ') # frame_font. frame_font_name = Frame(frame_font) frame_font_param = Frame(frame_font) @@ -566,13 +363,6 @@ def create_page_font_tab(self): self.font_sample = font_sample_frame.text self.font_sample.config(wrap=NONE, width=1, height=1) self.font_sample.insert(END, font_sample_text) - # frame_indent. - indent_title = Label( - frame_indent, justify=LEFT, - text='Python Standard: 4 Spaces!') - self.indent_scale = Scale( - frame_indent, variable=self.space_num, - orient='horizontal', tickinterval=2, from_=2, to=16) # Grid and pack widgets: self.columnconfigure(1, weight=1) @@ -580,7 +370,6 @@ def create_page_font_tab(self): frame_font.grid(row=0, column=0, padx=5, pady=5) frame_sample.grid(row=0, column=1, rowspan=3, padx=5, pady=5, sticky='nsew') - frame_indent.grid(row=1, column=0, padx=5, pady=5, sticky='ew') # frame_font. frame_font_name.pack(side=TOP, padx=5, pady=5, fill=X) frame_font_param.pack(side=TOP, padx=5, pady=5, fill=X) @@ -592,9 +381,6 @@ def create_page_font_tab(self): self.bold_toggle.pack(side=LEFT, anchor=W, padx=20) # frame_sample. font_sample_frame.pack(expand=TRUE, fill=BOTH) - # frame_indent. - indent_title.pack(side=TOP, anchor=W, padx=5) - self.indent_scale.pack(side=TOP, padx=5, fill=X) def load_font_cfg(self): """Load current configuration settings for the font options. @@ -668,34 +454,19 @@ def set_samples(self, event=None): self.font_sample['font'] = new_font self.highlight_sample['font'] = new_font - def load_tab_cfg(self): - """Load current configuration settings for the tab options. - - Attributes updated: - space_num: Set to value from idleConf. - """ - # Set indent sizes. - space_num = idleConf.GetOption( - 'main', 'Indent', 'num-spaces', default=4, type='int') - self.space_num.set(space_num) - - def var_changed_space_num(self, *params): - "Store change to indentation size." - value = self.space_num.get() - changes.add_option('main', 'Indent', 'num-spaces', value) - class HighPage(Frame): - def __init__(self, master): + def __init__(self, master, extpage): super().__init__(master) + self.extpage = extpage self.cd = master.winfo_toplevel() self.style = Style(master) self.create_page_highlight() self.load_theme_cfg() def create_page_highlight(self): - """Return frame of widgets for Highlighting tab. + """Return frame of widgets for Highlights tab. Enable users to provisionally change foreground and background colors applied to textual tags. Color mappings are stored in @@ -1339,15 +1110,16 @@ def delete_custom(self): self.builtin_name.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) # User can't back out of these changes, they must be applied now. changes.save_all() - self.cd.save_all_changed_extensions() + self.extpage.save_all_changed_extensions() self.cd.activate_config_changes() self.set_theme_type() class KeysPage(Frame): - def __init__(self, master): + def __init__(self, master, extpage): super().__init__(master) + self.extpage = extpage self.cd = master.winfo_toplevel() self.create_page_keys() self.load_key_cfg() @@ -1771,19 +1543,19 @@ def delete_custom_keys(self): or idleConf.default_keys()) # User can't back out of these changes, they must be applied now. changes.save_all() - self.cd.save_all_changed_extensions() + self.extpage.save_all_changed_extensions() self.cd.activate_config_changes() self.set_keys_type() -class GenPage(Frame): +class WinPage(Frame): def __init__(self, master): super().__init__(master) self.init_validators() - self.create_page_general() - self.load_general_cfg() + self.create_page_windows() + self.load_windows_cfg() def init_validators(self): digits_or_empty_re = re.compile(r'[0-9]*') @@ -1792,76 +1564,45 @@ def is_digits_or_empty(s): return digits_or_empty_re.fullmatch(s) is not None self.digits_only = (self.register(is_digits_or_empty), '%P',) - def create_page_general(self): - """Return frame of widgets for General tab. - - Enable users to provisionally change general options. Function - load_general_cfg initializes tk variables and helplist using - idleConf. Radiobuttons startup_shell_on and startup_editor_on - set var startup_edit. Radiobuttons save_ask_on and save_auto_on - set var autosave. Entry boxes win_width_int and win_height_int - set var win_width and win_height. Setting var_name invokes the - default callback that adds option to changes. + def create_page_windows(self): + """Return frame of widgets for Windows tab. - Helplist: load_general_cfg loads list user_helplist with - name, position pairs and copies names to listbox helplist. - Clicking a name invokes help_source selected. Clicking - button_helplist_name invokes helplist_item_name, which also - changes user_helplist. These functions all call - set_add_delete_state. All but load call update_help_changes to - rewrite changes['main']['HelpFiles']. + Enable users to provisionally change general window options. + Function load_windows_cfg initializes tk variable idleConf. + Radiobuttons startup_shell_on and startup_editor_on set var + startup_edit. Entry boxes win_width_int and win_height_int set var + win_width and win_height. Setting var_name invokes the default + callback that adds option to changes. - Widgets for GenPage(Frame): (*) widgets bound to self + Widgets for WinPage(Frame): > vars, bound to self frame_window: LabelFrame frame_run: Frame startup_title: Label - (*)startup_editor_on: Radiobutton - startup_edit - (*)startup_shell_on: Radiobutton - startup_edit + startup_editor_on: Radiobutton > startup_edit + startup_shell_on: Radiobutton > startup_edit frame_win_size: Frame win_size_title: Label win_width_title: Label - (*)win_width_int: Entry - win_width + win_width_int: Entry > win_width win_height_title: Label - (*)win_height_int: Entry - win_height - frame_cursor_blink: Frame - cursor_blink_title: Label - (*)cursor_blink_bool: Checkbutton - cursor_blink + win_height_int: Entry > win_height + frame_cursor: Frame + indent_title: Label + indent_chooser: Spinbox (Combobox < 8.5.9) > indent_spaces + blink_on: Checkbutton > cursor_blink frame_autocomplete: Frame auto_wait_title: Label - (*)auto_wait_int: Entry - autocomplete_wait + auto_wait_int: Entry > autocomplete_wait frame_paren1: Frame paren_style_title: Label - (*)paren_style_type: OptionMenu - paren_style + paren_style_type: OptionMenu > paren_style frame_paren2: Frame paren_time_title: Label - (*)paren_flash_time: Entry - flash_delay - (*)bell_on: Checkbutton - paren_bell - frame_editor: LabelFrame - frame_save: Frame - run_save_title: Label - (*)save_ask_on: Radiobutton - autosave - (*)save_auto_on: Radiobutton - autosave + paren_flash_time: Entry > flash_delay + bell_on: Checkbutton > paren_bell frame_format: Frame format_width_title: Label - (*)format_width_int: Entry - format_width - frame_line_numbers_default: Frame - line_numbers_default_title: Label - (*)line_numbers_default_bool: Checkbutton - line_numbers_default - frame_context: Frame - context_title: Label - (*)context_int: Entry - context_lines - frame_shell: LabelFrame - frame_auto_squeeze_min_lines: Frame - auto_squeeze_min_lines_title: Label - (*)auto_squeeze_min_lines_int: Entry - auto_squeeze_min_lines - frame_help: LabelFrame - frame_helplist: Frame - frame_helplist_buttons: Frame - (*)button_helplist_edit - (*)button_helplist_add - (*)button_helplist_remove - (*)helplist: ListBox - scroll_helplist: Scrollbar + format_width_int: Entry > format_width """ # Integer values need StringVar because int('') raises. self.startup_edit = tracers.add( @@ -1870,6 +1611,8 @@ def create_page_general(self): StringVar(self), ('main', 'EditorWindow', 'width')) self.win_height = tracers.add( StringVar(self), ('main', 'EditorWindow', 'height')) + self.indent_spaces = tracers.add( + StringVar(self), ('main', 'Indent', 'num-spaces')) self.cursor_blink = tracers.add( BooleanVar(self), ('main', 'EditorWindow', 'cursor-blink')) self.autocomplete_wait = tracers.add( @@ -1880,31 +1623,13 @@ def create_page_general(self): StringVar(self), ('extensions', 'ParenMatch', 'flash-delay')) self.paren_bell = tracers.add( BooleanVar(self), ('extensions', 'ParenMatch', 'bell')) - - self.auto_squeeze_min_lines = tracers.add( - StringVar(self), ('main', 'PyShell', 'auto-squeeze-min-lines')) - - self.autosave = tracers.add( - IntVar(self), ('main', 'General', 'autosave')) self.format_width = tracers.add( StringVar(self), ('extensions', 'FormatParagraph', 'max-width')) - self.line_numbers_default = tracers.add( - BooleanVar(self), - ('main', 'EditorWindow', 'line-numbers-default')) - self.context_lines = tracers.add( - StringVar(self), ('extensions', 'CodeContext', 'maxlines')) # Create widgets: - # Section frames. frame_window = LabelFrame(self, borderwidth=2, relief=GROOVE, text=' Window Preferences') - frame_editor = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Editor Preferences') - frame_shell = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Shell Preferences') - frame_help = LabelFrame(self, borderwidth=2, relief=GROOVE, - text=' Additional Help Sources ') - # Frame_window. + frame_run = Frame(frame_window, borderwidth=0) startup_title = Label(frame_run, text='At Startup') self.startup_editor_on = Radiobutton( @@ -1928,19 +1653,28 @@ def create_page_general(self): validatecommand=self.digits_only, validate='key', ) - frame_cursor_blink = Frame(frame_window, borderwidth=0) - cursor_blink_title = Label(frame_cursor_blink, text='Cursor Blink') - self.cursor_blink_bool = Checkbutton(frame_cursor_blink, - variable=self.cursor_blink, width=1) + frame_cursor = Frame(frame_window, borderwidth=0) + indent_title = Label(frame_cursor, + text='Indent spaces (4 is standard)') + try: + self.indent_chooser = Spinbox( + frame_cursor, textvariable=self.indent_spaces, + from_=1, to=10, width=2, + validatecommand=self.digits_only, validate='key') + except TclError: + self.indent_chooser = Combobox( + frame_cursor, textvariable=self.indent_spaces, + state="readonly", values=list(range(1,11)), width=3) + cursor_blink_title = Label(frame_cursor, text='Cursor Blink') + self.cursor_blink_bool = Checkbutton(frame_cursor, text="Cursor blink", + variable=self.cursor_blink) frame_autocomplete = Frame(frame_window, borderwidth=0,) auto_wait_title = Label(frame_autocomplete, - text='Completions Popup Wait (milliseconds)') - self.auto_wait_int = Entry(frame_autocomplete, width=6, - textvariable=self.autocomplete_wait, - validatecommand=self.digits_only, - validate='key', - ) + text='Completions Popup Wait (milliseconds)') + self.auto_wait_int = Entry( + frame_autocomplete, textvariable=self.autocomplete_wait, + width=6, validatecommand=self.digits_only, validate='key') frame_paren1 = Frame(frame_window, borderwidth=0) paren_style_title = Label(frame_paren1, text='Paren Match Style') @@ -1952,79 +1686,20 @@ def create_page_general(self): frame_paren2, text='Time Match Displayed (milliseconds)\n' '(0 is until next input)') self.paren_flash_time = Entry( - frame_paren2, textvariable=self.flash_delay, width=6) + frame_paren2, textvariable=self.flash_delay, width=6, + validatecommand=self.digits_only, validate='key') self.bell_on = Checkbutton( frame_paren2, text="Bell on Mismatch", variable=self.paren_bell) - - # Frame_editor. - frame_save = Frame(frame_editor, borderwidth=0) - run_save_title = Label(frame_save, text='At Start of Run (F5) ') - self.save_ask_on = Radiobutton( - frame_save, variable=self.autosave, value=0, - text="Prompt to Save") - self.save_auto_on = Radiobutton( - frame_save, variable=self.autosave, value=1, - text='No Prompt') - - frame_format = Frame(frame_editor, borderwidth=0) + frame_format = Frame(frame_window, borderwidth=0) format_width_title = Label(frame_format, text='Format Paragraph Max Width') self.format_width_int = Entry( frame_format, textvariable=self.format_width, width=4, validatecommand=self.digits_only, validate='key', - ) - - frame_line_numbers_default = Frame(frame_editor, borderwidth=0) - line_numbers_default_title = Label( - frame_line_numbers_default, text='Show line numbers in new windows') - self.line_numbers_default_bool = Checkbutton( - frame_line_numbers_default, - variable=self.line_numbers_default, - width=1) - - frame_context = Frame(frame_editor, borderwidth=0) - context_title = Label(frame_context, text='Max Context Lines :') - self.context_int = Entry( - frame_context, textvariable=self.context_lines, width=3, - validatecommand=self.digits_only, validate='key', - ) - - # Frame_shell. - frame_auto_squeeze_min_lines = Frame(frame_shell, borderwidth=0) - auto_squeeze_min_lines_title = Label(frame_auto_squeeze_min_lines, - text='Auto-Squeeze Min. Lines:') - self.auto_squeeze_min_lines_int = Entry( - frame_auto_squeeze_min_lines, width=4, - textvariable=self.auto_squeeze_min_lines, - validatecommand=self.digits_only, validate='key', - ) - - # frame_help. - frame_helplist = Frame(frame_help) - frame_helplist_buttons = Frame(frame_helplist) - self.helplist = Listbox( - frame_helplist, height=5, takefocus=True, - exportselection=FALSE) - scroll_helplist = Scrollbar(frame_helplist) - scroll_helplist['command'] = self.helplist.yview - self.helplist['yscrollcommand'] = scroll_helplist.set - self.helplist.bind('', self.help_source_selected) - self.button_helplist_edit = Button( - frame_helplist_buttons, text='Edit', state='disabled', - width=8, command=self.helplist_item_edit) - self.button_helplist_add = Button( - frame_helplist_buttons, text='Add', - width=8, command=self.helplist_item_add) - self.button_helplist_remove = Button( - frame_helplist_buttons, text='Remove', state='disabled', - width=8, command=self.helplist_item_remove) + ) # Pack widgets: - # Body. frame_window.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_editor.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_shell.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - frame_help.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) # frame_run. frame_run.pack(side=TOP, padx=5, pady=0, fill=X) startup_title.pack(side=LEFT, anchor=W, padx=5, pady=5) @@ -2037,10 +1712,11 @@ def create_page_general(self): win_height_title.pack(side=RIGHT, anchor=E, pady=5) self.win_width_int.pack(side=RIGHT, anchor=E, padx=10, pady=5) win_width_title.pack(side=RIGHT, anchor=E, pady=5) - # frame_cursor_blink. - frame_cursor_blink.pack(side=TOP, padx=5, pady=0, fill=X) - cursor_blink_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.cursor_blink_bool.pack(side=LEFT, padx=5, pady=5) + # frame_cursor. + frame_cursor.pack(side=TOP, padx=5, pady=0, fill=X) + indent_title.pack(side=LEFT, anchor=W, padx=5) + self.indent_chooser.pack(side=LEFT, anchor=W, padx=10) + self.cursor_blink_bool.pack(side=RIGHT, anchor=E, padx=15, pady=5) # frame_autocomplete. frame_autocomplete.pack(side=TOP, padx=5, pady=0, fill=X) auto_wait_title.pack(side=LEFT, anchor=W, padx=5, pady=5) @@ -2053,41 +1729,12 @@ def create_page_general(self): paren_time_title.pack(side=LEFT, anchor=W, padx=5) self.bell_on.pack(side=RIGHT, anchor=E, padx=15, pady=5) self.paren_flash_time.pack(side=TOP, anchor=W, padx=15, pady=5) - - # frame_save. - frame_save.pack(side=TOP, padx=5, pady=0, fill=X) - run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) - self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) # frame_format. frame_format.pack(side=TOP, padx=5, pady=0, fill=X) format_width_title.pack(side=LEFT, anchor=W, padx=5, pady=5) self.format_width_int.pack(side=TOP, padx=10, pady=5) - # frame_line_numbers_default. - frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X) - line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5) - # frame_context. - frame_context.pack(side=TOP, padx=5, pady=0, fill=X) - context_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.context_int.pack(side=TOP, padx=5, pady=5) - # frame_auto_squeeze_min_lines - frame_auto_squeeze_min_lines.pack(side=TOP, padx=5, pady=0, fill=X) - auto_squeeze_min_lines_title.pack(side=LEFT, anchor=W, padx=5, pady=5) - self.auto_squeeze_min_lines_int.pack(side=TOP, padx=5, pady=5) - - # frame_help. - frame_helplist_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y) - frame_helplist.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) - scroll_helplist.pack(side=RIGHT, anchor=W, fill=Y) - self.helplist.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) - self.button_helplist_edit.pack(side=TOP, anchor=W, pady=5) - self.button_helplist_add.pack(side=TOP, anchor=W) - self.button_helplist_remove.pack(side=TOP, anchor=W, pady=5) - - def load_general_cfg(self): - "Load current configuration settings for the general options." + def load_windows_cfg(self): # Set variables for all windows. self.startup_edit.set(idleConf.GetOption( 'main', 'General', 'editor-on-startup', type='bool')) @@ -2095,6 +1742,8 @@ def load_general_cfg(self): 'main', 'EditorWindow', 'width', type='int')) self.win_height.set(idleConf.GetOption( 'main', 'EditorWindow', 'height', type='int')) + self.indent_spaces.set(idleConf.GetOption( + 'main', 'Indent', 'num-spaces', type='int')) self.cursor_blink.set(idleConf.GetOption( 'main', 'EditorWindow', 'cursor-blink', type='bool')) self.autocomplete_wait.set(idleConf.GetOption( @@ -2105,27 +1754,394 @@ def load_general_cfg(self): 'extensions', 'ParenMatch', 'flash-delay', type='int')) self.paren_bell.set(idleConf.GetOption( 'extensions', 'ParenMatch', 'bell')) + self.format_width.set(idleConf.GetOption( + 'extensions', 'FormatParagraph', 'max-width', type='int')) + + +class ShedPage(Frame): + + def __init__(self, master): + super().__init__(master) + + self.init_validators() + self.create_page_shed() + self.load_shelled_cfg() + + def init_validators(self): + digits_or_empty_re = re.compile(r'[0-9]*') + def is_digits_or_empty(s): + "Return 's is blank or contains only digits'" + return digits_or_empty_re.fullmatch(s) is not None + self.digits_only = (self.register(is_digits_or_empty), '%P',) + + def create_page_shed(self): + """Return frame of widgets for Shell/Ed tab. + + Enable users to provisionally change shell and editor options. + Function load_shed_cfg initializes tk variables using idleConf. + Entry box auto_squeeze_min_lines_int sets + auto_squeeze_min_lines_int. Setting var_name invokes the + default callback that adds option to changes. + + Widgets for ShedPage(Frame): (*) widgets bound to self + frame_shell: LabelFrame + frame_auto_squeeze_min_lines: Frame + auto_squeeze_min_lines_title: Label + (*)auto_squeeze_min_lines_int: Entry - + auto_squeeze_min_lines + frame_editor: LabelFrame + frame_save: Frame + run_save_title: Label + (*)save_ask_on: Radiobutton - autosave + (*)save_auto_on: Radiobutton - autosave + frame_format: Frame + format_width_title: Label + (*)format_width_int: Entry - format_width + frame_line_numbers_default: Frame + line_numbers_default_title: Label + (*)line_numbers_default_bool: Checkbutton - line_numbers_default + frame_context: Frame + context_title: Label + (*)context_int: Entry - context_lines + """ + # Integer values need StringVar because int('') raises. + self.auto_squeeze_min_lines = tracers.add( + StringVar(self), ('main', 'PyShell', 'auto-squeeze-min-lines')) + + self.autosave = tracers.add( + IntVar(self), ('main', 'General', 'autosave')) + self.line_numbers_default = tracers.add( + BooleanVar(self), + ('main', 'EditorWindow', 'line-numbers-default')) + self.context_lines = tracers.add( + StringVar(self), ('extensions', 'CodeContext', 'maxlines')) + # Create widgets: + frame_shell = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Shell Preferences') + frame_editor = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Editor Preferences') + # Frame_shell. + frame_auto_squeeze_min_lines = Frame(frame_shell, borderwidth=0) + auto_squeeze_min_lines_title = Label(frame_auto_squeeze_min_lines, + text='Auto-Squeeze Min. Lines:') + self.auto_squeeze_min_lines_int = Entry( + frame_auto_squeeze_min_lines, width=4, + textvariable=self.auto_squeeze_min_lines, + validatecommand=self.digits_only, validate='key', + ) + # Frame_editor. + frame_save = Frame(frame_editor, borderwidth=0) + run_save_title = Label(frame_save, text='At Start of Run (F5) ') + + self.save_ask_on = Radiobutton( + frame_save, variable=self.autosave, value=0, + text="Prompt to Save") + self.save_auto_on = Radiobutton( + frame_save, variable=self.autosave, value=1, + text='No Prompt') + + frame_line_numbers_default = Frame(frame_editor, borderwidth=0) + line_numbers_default_title = Label( + frame_line_numbers_default, text='Show line numbers in new windows') + self.line_numbers_default_bool = Checkbutton( + frame_line_numbers_default, + variable=self.line_numbers_default, + width=1) + + frame_context = Frame(frame_editor, borderwidth=0) + context_title = Label(frame_context, text='Max Context Lines :') + self.context_int = Entry( + frame_context, textvariable=self.context_lines, width=3, + validatecommand=self.digits_only, validate='key', + ) + + # Pack widgets: + frame_shell.pack(side=TOP, padx=5, pady=5, fill=BOTH) + Label(self).pack() # Spacer -- better solution? + frame_editor.pack(side=TOP, padx=5, pady=5, fill=BOTH) + # frame_auto_squeeze_min_lines + frame_auto_squeeze_min_lines.pack(side=TOP, padx=5, pady=0, fill=X) + auto_squeeze_min_lines_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.auto_squeeze_min_lines_int.pack(side=TOP, padx=5, pady=5) + # frame_save. + frame_save.pack(side=TOP, padx=5, pady=0, fill=X) + run_save_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.save_auto_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) + self.save_ask_on.pack(side=RIGHT, anchor=W, padx=5, pady=5) + # frame_line_numbers_default. + frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X) + line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5) + # frame_context. + frame_context.pack(side=TOP, padx=5, pady=0, fill=X) + context_title.pack(side=LEFT, anchor=W, padx=5, pady=5) + self.context_int.pack(side=TOP, padx=5, pady=5) + + def load_shelled_cfg(self): + # Set variables for shell windows. + self.auto_squeeze_min_lines.set(idleConf.GetOption( + 'main', 'PyShell', 'auto-squeeze-min-lines', type='int')) # Set variables for editor windows. self.autosave.set(idleConf.GetOption( 'main', 'General', 'autosave', default=0, type='bool')) - self.format_width.set(idleConf.GetOption( - 'extensions', 'FormatParagraph', 'max-width', type='int')) self.line_numbers_default.set(idleConf.GetOption( 'main', 'EditorWindow', 'line-numbers-default', type='bool')) self.context_lines.set(idleConf.GetOption( 'extensions', 'CodeContext', 'maxlines', type='int')) - # Set variables for shell windows. - self.auto_squeeze_min_lines.set(idleConf.GetOption( - 'main', 'PyShell', 'auto-squeeze-min-lines', type='int')) - # Set additional help sources. - self.user_helplist = idleConf.GetAllExtraHelpSourcesList() - self.helplist.delete(0, 'end') - for help_item in self.user_helplist: - self.helplist.insert(END, help_item[0]) - self.set_add_delete_state() +class ExtPage(Frame): + def __init__(self, master): + super().__init__(master) + self.ext_defaultCfg = idleConf.defaultCfg['extensions'] + self.ext_userCfg = idleConf.userCfg['extensions'] + self.is_int = self.register(is_int) + self.load_extensions() + self.create_page_extensions() # Requires extension names. + + def create_page_extensions(self): + """Configure IDLE feature extensions and help menu extensions. + + List the feature extensions and a configuration box for the + selected extension. Help menu extensions are in a HelpFrame. + + This code reads the current configuration using idleConf, + supplies a GUI interface to change the configuration values, + and saves the changes using idleConf. + + Some changes may require restarting IDLE. This depends on each + extension's implementation. + + All values are treated as text, and it is up to the user to + supply reasonable values. The only exception to this are the + 'enable*' options, which are boolean, and can be toggled with a + True/False button. + + Methods: + extension_selected: Handle selection from list. + create_extension_frame: Hold widgets for one extension. + set_extension_value: Set in userCfg['extensions']. + save_all_changed_extensions: Call extension page Save(). + """ + self.extension_names = StringVar(self) + + frame_ext = LabelFrame(self, borderwidth=2, relief=GROOVE, + text=' Feature Extensions ') + self.frame_help = HelpFrame(self, borderwidth=2, relief=GROOVE, + text=' Help Menu Extensions ') + + frame_ext.rowconfigure(0, weight=1) + frame_ext.columnconfigure(2, weight=1) + self.extension_list = Listbox(frame_ext, listvariable=self.extension_names, + selectmode='browse') + self.extension_list.bind('<>', self.extension_selected) + scroll = Scrollbar(frame_ext, command=self.extension_list.yview) + self.extension_list.yscrollcommand=scroll.set + self.details_frame = LabelFrame(frame_ext, width=250, height=250) + self.extension_list.grid(column=0, row=0, sticky='nws') + scroll.grid(column=1, row=0, sticky='ns') + self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0]) + frame_ext.configure(padding=10) + self.config_frame = {} + self.current_extension = None + + self.outerframe = self # TEMPORARY + self.tabbed_page_set = self.extension_list # TEMPORARY + + # Create the frame holding controls for each extension. + ext_names = '' + for ext_name in sorted(self.extensions): + self.create_extension_frame(ext_name) + ext_names = ext_names + '{' + ext_name + '} ' + self.extension_names.set(ext_names) + self.extension_list.selection_set(0) + self.extension_selected(None) + + + frame_ext.grid(row=0, column=0, sticky='nsew') + Label(self).grid(row=1, column=0) # Spacer. Replace with config? + self.frame_help.grid(row=2, column=0, sticky='sew') + + def load_extensions(self): + "Fill self.extensions with data from the default and user configs." + self.extensions = {} + for ext_name in idleConf.GetExtensions(active_only=False): + # Former built-in extensions are already filtered out. + self.extensions[ext_name] = [] + + for ext_name in self.extensions: + opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name)) + + # Bring 'enable' options to the beginning of the list. + enables = [opt_name for opt_name in opt_list + if opt_name.startswith('enable')] + for opt_name in enables: + opt_list.remove(opt_name) + opt_list = enables + opt_list + + for opt_name in opt_list: + def_str = self.ext_defaultCfg.Get( + ext_name, opt_name, raw=True) + try: + def_obj = {'True':True, 'False':False}[def_str] + opt_type = 'bool' + except KeyError: + try: + def_obj = int(def_str) + opt_type = 'int' + except ValueError: + def_obj = def_str + opt_type = None + try: + value = self.ext_userCfg.Get( + ext_name, opt_name, type=opt_type, raw=True, + default=def_obj) + except ValueError: # Need this until .Get fixed. + value = def_obj # Bad values overwritten by entry. + var = StringVar(self) + var.set(str(value)) + + self.extensions[ext_name].append({'name': opt_name, + 'type': opt_type, + 'default': def_str, + 'value': value, + 'var': var, + }) + + def extension_selected(self, event): + "Handle selection of an extension from the list." + newsel = self.extension_list.curselection() + if newsel: + newsel = self.extension_list.get(newsel) + if newsel is None or newsel != self.current_extension: + if self.current_extension: + self.details_frame.config(text='') + self.config_frame[self.current_extension].grid_forget() + self.current_extension = None + if newsel: + self.details_frame.config(text=newsel) + self.config_frame[newsel].grid(column=0, row=0, sticky='nsew') + self.current_extension = newsel + + def create_extension_frame(self, ext_name): + """Create a frame holding the widgets to configure one extension""" + f = VerticalScrolledFrame(self.details_frame, height=250, width=250) + self.config_frame[ext_name] = f + entry_area = f.interior + # Create an entry for each configuration option. + for row, opt in enumerate(self.extensions[ext_name]): + # Create a row with a label and entry/checkbutton. + label = Label(entry_area, text=opt['name']) + label.grid(row=row, column=0, sticky=NW) + var = opt['var'] + if opt['type'] == 'bool': + Checkbutton(entry_area, variable=var, + onvalue='True', offvalue='False', width=8 + ).grid(row=row, column=1, sticky=W, padx=7) + elif opt['type'] == 'int': + Entry(entry_area, textvariable=var, validate='key', + validatecommand=(self.is_int, '%P'), width=10 + ).grid(row=row, column=1, sticky=NSEW, padx=7) + + else: # type == 'str' + # Limit size to fit non-expanding space with larger font. + Entry(entry_area, textvariable=var, width=15 + ).grid(row=row, column=1, sticky=NSEW, padx=7) + return + + def set_extension_value(self, section, opt): + """Return True if the configuration was added or changed. + + If the value is the same as the default, then remove it + from user config file. + """ + name = opt['name'] + default = opt['default'] + value = opt['var'].get().strip() or default + opt['var'].set(value) + # if self.defaultCfg.has_section(section): + # Currently, always true; if not, indent to return. + if (value == default): + return self.ext_userCfg.RemoveOption(section, name) + # Set the option. + return self.ext_userCfg.SetOption(section, name, value) + + def save_all_changed_extensions(self): + """Save configuration changes to the user config file. + + Attributes accessed: + extensions + + Methods: + set_extension_value + """ + has_changes = False + for ext_name in self.extensions: + options = self.extensions[ext_name] + for opt in options: + if self.set_extension_value(ext_name, opt): + has_changes = True + if has_changes: + self.ext_userCfg.Save() + + +class HelpFrame(LabelFrame): + + def __init__(self, master, **cfg): + super().__init__(master, **cfg) + self.create_frame_help() + self.load_helplist() + + def create_frame_help(self): + """Create LabelFrame for additional help menu sources. + + load_helplist loads list user_helplist with + name, position pairs and copies names to listbox helplist. + Clicking a name invokes help_source selected. Clicking + button_helplist_name invokes helplist_item_name, which also + changes user_helplist. These functions all call + set_add_delete_state. All but load call update_help_changes to + rewrite changes['main']['HelpFiles']. + + Widgets for HelpFrame(LabelFrame): (*) widgets bound to self + frame_helplist: Frame + (*)helplist: ListBox + scroll_helplist: Scrollbar + frame_buttons: Frame + (*)button_helplist_edit + (*)button_helplist_add + (*)button_helplist_remove + """ + # self = frame_help in dialog (until ExtPage class). + frame_helplist = Frame(self) + self.helplist = Listbox( + frame_helplist, height=5, takefocus=True, + exportselection=FALSE) + scroll_helplist = Scrollbar(frame_helplist) + scroll_helplist['command'] = self.helplist.yview + self.helplist['yscrollcommand'] = scroll_helplist.set + self.helplist.bind('', self.help_source_selected) + + frame_buttons = Frame(self) + self.button_helplist_edit = Button( + frame_buttons, text='Edit', state='disabled', + width=8, command=self.helplist_item_edit) + self.button_helplist_add = Button( + frame_buttons, text='Add', + width=8, command=self.helplist_item_add) + self.button_helplist_remove = Button( + frame_buttons, text='Remove', state='disabled', + width=8, command=self.helplist_item_remove) + + # Pack frame_help. + frame_helplist.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + self.helplist.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) + scroll_helplist.pack(side=RIGHT, anchor=W, fill=Y) + frame_buttons.pack(side=RIGHT, padx=5, pady=5, fill=Y) + self.button_helplist_edit.pack(side=TOP, anchor=W, pady=5) + self.button_helplist_add.pack(side=TOP, anchor=W) + self.button_helplist_remove.pack(side=TOP, anchor=W, pady=5) def help_source_selected(self, event): "Handle event for selecting additional help." @@ -2195,6 +2211,14 @@ def update_help_changes(self): 'main', 'HelpFiles', str(num), ';'.join(self.user_helplist[num-1][:2])) + def load_helplist(self): + # Set additional help sources. + self.user_helplist = idleConf.GetAllExtraHelpSourcesList() + self.helplist.delete(0, 'end') + for help_item in self.user_helplist: + self.helplist.insert(END, help_item[0]) + self.set_add_delete_state() + class VarTrace: """Maintain Tk variables trace state.""" diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index e80384b7775222..2468afa7148b9f 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -5,7 +5,7 @@ - IDLE — Python 3.10.0a6 documentation + IDLE — Python 3.11.0a0 documentation @@ -18,13 +18,13 @@ - + @@ -59,7 +59,7 @@

    Navigation

    modules |
  • - next |
  • Navigation
  • - 3.10.0a6 Documentation » + 3.11.0a0 Documentation »
  • @@ -102,7 +102,7 @@

    Navigation

    @@ -581,6 +581,11 @@

    Text colorsclass and def, strings, and comments. For any text window, these are the cursor (when present), found text (when possible), and selected text.

    +

    IDLE also highlights the soft keywords match, +case, and _ in +pattern-matching statements. However, this highlighting is not perfect and +will be incorrect in some rare cases, including some _-s in case +patterns.

    Text coloring is done in the background, so uncolorized text is occasionally visible. To change the color scheme, use the Configure IDLE dialog Highlighting tab. The marking of debugger breakpoint lines in the editor and @@ -685,7 +690,7 @@

    Running user codesys.modules starts with more entries, -and threading.activeCount() returns 2 instead of 1.

    +and threading.active_count() returns 2 instead of 1.

    By default, IDLE runs user code in a separate OS process rather than in the user interface process that runs the shell and editor. In the execution process, it replaces sys.stdin, sys.stdout, and sys.stderr @@ -798,7 +803,7 @@

    Developing tkinter applications

    By default, IDLE executes user code in a separate subprocess via a socket, which uses the internal loopback interface. This connection is not -externally visible and no data is sent to or received from the Internet. +externally visible and no data is sent to or received from the internet. If firewall software complains anyway, you can ignore it.

    If the attempt to make the socket connection fails, Idle will notify you. Such failures are sometimes transient, but if persistent, the problem @@ -932,14 +937,14 @@

    Previous topic

    tkinter.tix — Extension widgets for Tk

    Next topic

    -

    Other Graphical User Interface Packages

    +

    Development Tools

    This Page

    • Report a Bug
    • - Show Source
    • @@ -959,7 +964,7 @@

      Navigation

      modules |
    • - next |
    • Navigation
    • - 3.10.0a6 Documentation » + 3.11.0a0 Documentation »
    • @@ -1003,7 +1008,7 @@

      Navigation



      - Last updated on Mar 29, 2021. + Last updated on Sep 06, 2021. Found a bug?
      diff --git a/Lib/idlelib/help_about.py b/Lib/idlelib/help_about.py index 64b13ac2abb3b2..019aacbd0faa20 100644 --- a/Lib/idlelib/help_about.py +++ b/Lib/idlelib/help_about.py @@ -10,6 +10,8 @@ from idlelib import textview +version = python_version() + def build_bits(): "Return bits for platform." @@ -42,7 +44,7 @@ def __init__(self, parent, title=None, *, _htest=False, _utest=False): self.create_widgets() self.resizable(height=False, width=False) self.title(title or - f'About IDLE {python_version()} ({build_bits()} bit)') + f'About IDLE {version} ({build_bits()} bit)') self.transient(parent) self.grab_set() self.protocol("WM_DELETE_WINDOW", self.ok) @@ -88,8 +90,8 @@ def create_widgets(self): email = Label(frame_background, text='email: idle-dev@python.org', justify=LEFT, fg=self.fg, bg=self.bg) email.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) - docs = Label(frame_background, text='https://docs.python.org/' + - python_version()[:3] + '/library/idle.html', + docs = Label(frame_background, text="https://docs.python.org/" + f"{version[:version.rindex('.')]}/library/idle.html", justify=LEFT, fg=self.fg, bg=self.bg) docs.grid(row=7, column=0, columnspan=2, sticky=W, padx=10, pady=0) @@ -98,7 +100,7 @@ def create_widgets(self): columnspan=3, padx=5, pady=5) pyver = Label(frame_background, - text='Python version: ' + python_version(), + text='Python version: ' + version, fg=self.fg, bg=self.bg) pyver.grid(row=9, column=0, sticky=W, padx=10, pady=0) tkver = Label(frame_background, text='Tk version: ' + tk_patchlevel, @@ -124,7 +126,7 @@ def create_widgets(self): columnspan=3, padx=5, pady=5) idlever = Label(frame_background, - text='IDLE version: ' + python_version(), + text='IDLE version: ' + version, fg=self.fg, bg=self.bg) idlever.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_buttons = Frame(frame_background, bg=self.bg) diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 1373b7642a6ea9..666ff4cb848510 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -246,7 +246,7 @@ def _wrapper(parent): # htest # _object_browser_spec = { 'file': 'debugobj', 'kwds': {}, - 'msg': "Double click on items upto the lowest level.\n" + 'msg': "Double click on items up to the lowest level.\n" "Attributes of the objects and related information " "will be displayed side-by-side at each level." } @@ -255,7 +255,7 @@ def _wrapper(parent): # htest # 'file': 'pathbrowser', 'kwds': {}, 'msg': "Test for correct display of all paths in sys.path.\n" - "Toggle nested items upto the lowest level.\n" + "Toggle nested items up to the lowest level.\n" "Double clicking on an item prints a traceback\n" "for an exception that is ignored." } @@ -341,7 +341,7 @@ def _wrapper(parent): # htest # 'file': 'tree', 'kwds': {}, 'msg': "The canvas is scrollable.\n" - "Click on folders upto to the lowest level." + "Click on folders up to to the lowest level." } _undo_delegator_spec = { diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py index db583553838fb3..8304734b847a83 100644 --- a/Lib/idlelib/idle_test/mock_tk.py +++ b/Lib/idlelib/idle_test/mock_tk.py @@ -79,7 +79,7 @@ def tearDownClass(cls): --- For 'ask' functions, set func.result return value before calling the method that uses the message function. When messagebox functions are the - only gui alls in a method, this replacement makes the method gui-free, + only GUI calls in a method, this replacement makes the method GUI-free, """ askokcancel = Mbox_func() # True or False askquestion = Mbox_func() # 'yes' or 'no' diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 642bb5db64dc34..a811363c18d04e 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -218,6 +218,11 @@ def make_acw(): return self.dummy_acw() self.assertTrue(acp.open_completions(ac.TAB)) self.text.delete('1.0', 'end') + def test_completion_kwds(self): + self.assertIn('and', ac.completion_kwds) + self.assertIn('case', ac.completion_kwds) + self.assertNotIn('None', ac.completion_kwds) + def test_fetch_completions(self): # Test that fetch_completions returns 2 lists: # For attribute completion, a large list containing all variables, and diff --git a/Lib/idlelib/idle_test/test_colorizer.py b/Lib/idlelib/idle_test/test_colorizer.py index c31c49236ca0b9..308bc389384d33 100644 --- a/Lib/idlelib/idle_test/test_colorizer.py +++ b/Lib/idlelib/idle_test/test_colorizer.py @@ -1,11 +1,12 @@ -"Test colorizer, coverage 93%." - +"Test colorizer, coverage 99%." from idlelib import colorizer from test.support import requires import unittest from unittest import mock +from idlelib.idle_test.tkinter_testing_utils import run_in_tk_mainloop from functools import partial +import textwrap from tkinter import Tk, Text from idlelib import config from idlelib.percolator import Percolator @@ -19,15 +20,38 @@ 'extensions': config.IdleUserConfParser(''), } -source = ( - "if True: int ('1') # keyword, builtin, string, comment\n" - "elif False: print(0) # 'string' in comment\n" - "else: float(None) # if in comment\n" - "if iF + If + IF: 'keyword matching must respect case'\n" - "if'': x or'' # valid string-keyword no-space combinations\n" - "async def f(): await g()\n" - "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" - ) +source = textwrap.dedent("""\ + if True: int ('1') # keyword, builtin, string, comment + elif False: print(0) # 'string' in comment + else: float(None) # if in comment + if iF + If + IF: 'keyword matching must respect case' + if'': x or'' # valid keyword-string no-space combinations + async def f(): await g() + # Strings should be entirely colored, including quotes. + 'x', '''x''', "x", \"""x\""" + 'abc\\ + def' + '''abc\\ + def''' + # All valid prefixes for unicode and byte strings should be colored. + r'x', u'x', R'x', U'x', f'x', F'x' + fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x' + b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x' + # Invalid combinations of legal characters should be half colored. + ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x' + match point: + case (x, 0) as _: + print(f"X={x}") + case [_, [_], "_", + _]: + pass + case _ if ("a" if _ else set()): pass + case _: + raise ValueError("Not a point _") + ''' + case _:''' + "match x:" + """) def setUpModule(): @@ -107,7 +131,7 @@ def setUpClass(cls): requires('gui') root = cls.root = Tk() root.withdraw() - text = cls.text = Text(root) + cls.text = Text(root) @classmethod def tearDownClass(cls): @@ -152,7 +176,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.percolator.redir.close() + cls.percolator.close() del cls.percolator, cls.text cls.root.update_idletasks() cls.root.destroy() @@ -364,8 +388,21 @@ def test_recolorize_main(self, mock_notify): ('4.0', ('KEYWORD',)), ('4.3', ()), ('4.6', ()), ('5.2', ('STRING',)), ('5.8', ('KEYWORD',)), ('5.10', ('STRING',)), ('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()), - ('7.0', ('STRING',)), ('7.4', ()), ('7.5', ('STRING',)), - ('7.12', ()), ('7.14', ('STRING',)), + ('8.0', ('STRING',)), ('8.4', ()), ('8.5', ('STRING',)), + ('8.12', ()), ('8.14', ('STRING',)), + ('19.0', ('KEYWORD',)), + ('20.4', ('KEYWORD',)), ('20.16', ('KEYWORD',)),# ('20.19', ('KEYWORD',)), + #('22.4', ('KEYWORD',)), ('22.10', ('KEYWORD',)), ('22.14', ('KEYWORD',)), ('22.19', ('STRING',)), + #('23.12', ('KEYWORD',)), + ('24.8', ('KEYWORD',)), + ('25.4', ('KEYWORD',)), ('25.9', ('KEYWORD',)), + ('25.11', ('KEYWORD',)), ('25.15', ('STRING',)), + ('25.19', ('KEYWORD',)), ('25.22', ()), + ('25.24', ('KEYWORD',)), ('25.29', ('BUILTIN',)), ('25.37', ('KEYWORD',)), + ('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),# ('26.11', ('KEYWORD',)), ('26.14', (),), + ('27.25', ('STRING',)), ('27.38', ('STRING',)), + ('29.0', ('STRING',)), + ('30.1', ('STRING',)), # SYNC at the end of every line. ('1.55', ('SYNC',)), ('2.50', ('SYNC',)), ('3.34', ('SYNC',)), ) @@ -391,11 +428,173 @@ def test_recolorize_main(self, mock_notify): eq(text.tag_nextrange('COMMENT', '2.0'), ('2.22', '2.43')) eq(text.tag_nextrange('SYNC', '2.0'), ('2.43', '3.0')) eq(text.tag_nextrange('STRING', '2.0'), ('4.17', '4.53')) - eq(text.tag_nextrange('STRING', '7.0'), ('7.0', '7.3')) - eq(text.tag_nextrange('STRING', '7.3'), ('7.5', '7.12')) - eq(text.tag_nextrange('STRING', '7.12'), ('7.14', '7.17')) - eq(text.tag_nextrange('STRING', '7.17'), ('7.19', '7.26')) - eq(text.tag_nextrange('SYNC', '7.0'), ('7.26', '9.0')) + eq(text.tag_nextrange('STRING', '8.0'), ('8.0', '8.3')) + eq(text.tag_nextrange('STRING', '8.3'), ('8.5', '8.12')) + eq(text.tag_nextrange('STRING', '8.12'), ('8.14', '8.17')) + eq(text.tag_nextrange('STRING', '8.17'), ('8.19', '8.26')) + eq(text.tag_nextrange('SYNC', '8.0'), ('8.26', '9.0')) + eq(text.tag_nextrange('SYNC', '30.0'), ('30.10', '32.0')) + + def _assert_highlighting(self, source, tag_ranges): + """Check highlighting of a given piece of code. + + This inserts just this code into the Text widget. It will then + check that the resulting highlighting tag ranges exactly match + those described in the given `tag_ranges` dict. + + Note that the irrelevant tags 'sel', 'TODO' and 'SYNC' are + ignored. + """ + text = self.text + + with mock.patch.object(colorizer.ColorDelegator, 'notify_range'): + text.delete('1.0', 'end-1c') + text.insert('insert', source) + text.tag_add('TODO', '1.0', 'end-1c') + self.color.recolorize_main() + + # Make a dict with highlighting tag ranges in the Text widget. + text_tag_ranges = {} + for tag in set(text.tag_names()) - {'sel', 'TODO', 'SYNC'}: + indexes = [rng.string for rng in text.tag_ranges(tag)] + for index_pair in zip(indexes[::2], indexes[1::2]): + text_tag_ranges.setdefault(tag, []).append(index_pair) + + self.assertEqual(text_tag_ranges, tag_ranges) + + with mock.patch.object(colorizer.ColorDelegator, 'notify_range'): + text.delete('1.0', 'end-1c') + + def test_def_statement(self): + # empty def + self._assert_highlighting('def', {'KEYWORD': [('1.0', '1.3')]}) + + # def followed by identifier + self._assert_highlighting('def foo:', {'KEYWORD': [('1.0', '1.3')], + 'DEFINITION': [('1.4', '1.7')]}) + + # def followed by partial identifier + self._assert_highlighting('def fo', {'KEYWORD': [('1.0', '1.3')], + 'DEFINITION': [('1.4', '1.6')]}) + + # def followed by non-keyword + self._assert_highlighting('def ++', {'KEYWORD': [('1.0', '1.3')]}) + + def test_match_soft_keyword(self): + # empty match + self._assert_highlighting('match', {'KEYWORD': [('1.0', '1.5')]}) + + # match followed by partial identifier + self._assert_highlighting('match fo', {'KEYWORD': [('1.0', '1.5')]}) + + # match followed by identifier and colon + self._assert_highlighting('match foo:', {'KEYWORD': [('1.0', '1.5')]}) + + # match followed by keyword + self._assert_highlighting('match and', {'KEYWORD': [('1.6', '1.9')]}) + + # match followed by builtin with keyword prefix + self._assert_highlighting('match int:', {'KEYWORD': [('1.0', '1.5')], + 'BUILTIN': [('1.6', '1.9')]}) + + # match followed by non-text operator + self._assert_highlighting('match^', {}) + self._assert_highlighting('match @', {}) + + # match followed by colon + self._assert_highlighting('match :', {}) + + # match followed by comma + self._assert_highlighting('match\t,', {}) + + # match followed by a lone underscore + self._assert_highlighting('match _:', {'KEYWORD': [('1.0', '1.5')]}) + + def test_case_soft_keyword(self): + # empty case + self._assert_highlighting('case', {'KEYWORD': [('1.0', '1.4')]}) + + # case followed by partial identifier + self._assert_highlighting('case fo', {'KEYWORD': [('1.0', '1.4')]}) + + # case followed by identifier and colon + self._assert_highlighting('case foo:', {'KEYWORD': [('1.0', '1.4')]}) + + # case followed by keyword + self._assert_highlighting('case and', {'KEYWORD': [('1.5', '1.8')]}) + + # case followed by builtin with keyword prefix + self._assert_highlighting('case int:', {'KEYWORD': [('1.0', '1.4')], + 'BUILTIN': [('1.5', '1.8')]}) + + # case followed by non-text operator + self._assert_highlighting('case^', {}) + self._assert_highlighting('case @', {}) + + # case followed by colon + self._assert_highlighting('case :', {}) + + # case followed by comma + self._assert_highlighting('case\t,', {}) + + # case followed by a lone underscore + self._assert_highlighting('case _:', {'KEYWORD': [('1.0', '1.4'), + ('1.5', '1.6')]}) + + def test_long_multiline_string(self): + source = textwrap.dedent('''\ + """a + b + c + d + e""" + ''') + self._assert_highlighting(source, {'STRING': [('1.0', '5.4')]}) + + @run_in_tk_mainloop(delay=50) + def test_incremental_editing(self): + text = self.text + eq = self.assertEqual + + # Simulate typing 'inte'. During this, the highlighting should + # change from normal to keyword to builtin to normal. + text.insert('insert', 'i') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ()) + eq(text.tag_nextrange('KEYWORD', '1.0'), ()) + + text.insert('insert', 'n') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ()) + eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2')) + + text.insert('insert', 't') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ('1.0', '1.3')) + eq(text.tag_nextrange('KEYWORD', '1.0'), ()) + + text.insert('insert', 'e') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ()) + eq(text.tag_nextrange('KEYWORD', '1.0'), ()) + + # Simulate deleting three characters from the end of 'inte'. + # During this, the highlighting should change from normal to + # builtin to keyword to normal. + text.delete('insert-1c', 'insert') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ('1.0', '1.3')) + eq(text.tag_nextrange('KEYWORD', '1.0'), ()) + + text.delete('insert-1c', 'insert') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ()) + eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2')) + + text.delete('insert-1c', 'insert') + yield + eq(text.tag_nextrange('BUILTIN', '1.0'), ()) + eq(text.tag_nextrange('KEYWORD', '1.0'), ()) @mock.patch.object(colorizer.ColorDelegator, 'recolorize') @mock.patch.object(colorizer.ColorDelegator, 'notify_range') diff --git a/Lib/idlelib/idle_test/test_config_key.py b/Lib/idlelib/idle_test/test_config_key.py index b7fe7fd6b5ec10..bf66cadf57cd3c 100644 --- a/Lib/idlelib/idle_test/test_config_key.py +++ b/Lib/idlelib/idle_test/test_config_key.py @@ -2,7 +2,7 @@ Coverage is effectively 100%. Tkinter dialog is mocked, Mac-only line may be skipped, and dummy function in bind test should not be called. -Not tested: exit with 'self.advanced or self.keys_ok(keys)) ...' False. +Not tested: exit with 'self.advanced or self.keys_ok(keys) ...' False. """ from idlelib import config_key diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 98ddc67afdcc08..3005ce08c9bf43 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -73,13 +73,13 @@ def test_click_ok(self): def test_click_apply(self): d = dialog deactivate = d.deactivate_current_config = mock.Mock() - save_ext = d.save_all_changed_extensions = mock.Mock() + save_ext = d.extpage.save_all_changed_extensions = mock.Mock() activate = d.activate_config_changes = mock.Mock() d.buttons['Apply'].invoke() deactivate.assert_called_once() save_ext.assert_called_once() activate.assert_called_once() - del d.save_all_changed_extensions + del d.extpage.save_all_changed_extensions del d.activate_config_changes, d.deactivate_current_config def test_click_cancel(self): @@ -260,27 +260,6 @@ def test_set_samples(self): d.set_samples = Func() # Re-mask for other tests. -class IndentTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.page = dialog.fontpage - cls.page.update() - - def test_load_tab_cfg(self): - d = self.page - d.space_num.set(16) - d.load_tab_cfg() - self.assertEqual(d.space_num.get(), 4) - - def test_indent_scale(self): - d = self.page - changes.clear() - d.indent_scale.set(20) - self.assertEqual(d.space_num.get(), 16) - self.assertEqual(mainpage, {'Indent': {'num-spaces': '16'}}) - - class HighPageTest(unittest.TestCase): """Test that highlight tab widgets enable users to make changes. @@ -1203,49 +1182,32 @@ def test_delete_custom_keys(self): del d.askyesno -class GenPageTest(unittest.TestCase): +class WinPageTest(unittest.TestCase): """Test that general tab widgets enable users to make changes. Test that widget actions set vars, that var changes add - options to changes and that helplist works correctly. + options to changes. """ @classmethod def setUpClass(cls): - page = cls.page = dialog.genpage + page = cls.page = dialog.winpage dialog.note.select(page) - page.set = page.set_add_delete_state = Func() - page.upc = page.update_help_changes = Func() page.update() - @classmethod - def tearDownClass(cls): - page = cls.page - del page.set, page.set_add_delete_state - del page.upc, page.update_help_changes - page.helplist.delete(0, 'end') - page.user_helplist.clear() - def setUp(self): changes.clear() - def test_load_general_cfg(self): + def test_load_windows_cfg(self): # Set to wrong values, load, check right values. eq = self.assertEqual d = self.page d.startup_edit.set(1) - d.autosave.set(1) d.win_width.set(1) d.win_height.set(1) - d.helplist.insert('end', 'bad') - d.user_helplist = ['bad', 'worse'] - idleConf.SetOption('main', 'HelpFiles', '1', 'name;file') - d.load_general_cfg() + d.load_windows_cfg() eq(d.startup_edit.get(), 0) - eq(d.autosave.get(), 0) eq(d.win_width.get(), '80') eq(d.win_height.get(), '40') - eq(d.helplist.get(0, 'end'), ('name',)) - eq(d.user_helplist, [('name', 'file', '1')]) def test_startup(self): d = self.page @@ -1267,6 +1229,12 @@ def test_editor_size(self): d.win_width_int.insert(0, '11') self.assertEqual(mainpage, {'EditorWindow': {'width': '11'}}) + def test_indent_spaces(self): + d = self.page + d.indent_chooser.set(6) + self.assertEqual(d.indent_spaces.get(), '6') + self.assertEqual(mainpage, {'Indent': {'num-spaces': '6'}}) + def test_cursor_blink(self): self.page.cursor_blink_bool.invoke() self.assertEqual(mainpage, {'EditorWindow': {'cursor-blink': 'False'}}) @@ -1289,6 +1257,35 @@ def test_parenmatch(self): d.bell_on.invoke() eq(extpage, {'ParenMatch': {'bell': 'False'}}) + def test_paragraph(self): + self.page.format_width_int.delete(0, 'end') + self.page.format_width_int.insert(0, '11') + self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}}) + + +class ShedPageTest(unittest.TestCase): + """Test that shed tab widgets enable users to make changes. + + Test that widget actions set vars, that var changes add + options to changes. + """ + @classmethod + def setUpClass(cls): + page = cls.page = dialog.shedpage + dialog.note.select(page) + page.update() + + def setUp(self): + changes.clear() + + def test_load_shelled_cfg(self): + # Set to wrong values, load, check right values. + eq = self.assertEqual + d = self.page + d.autosave.set(1) + d.load_shelled_cfg() + eq(d.autosave.get(), 0) + def test_autosave(self): d = self.page d.save_auto_on.invoke() @@ -1296,21 +1293,58 @@ def test_autosave(self): d.save_ask_on.invoke() self.assertEqual(mainpage, {'General': {'autosave': '0'}}) - def test_paragraph(self): - self.page.format_width_int.delete(0, 'end') - self.page.format_width_int.insert(0, '11') - self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}}) - def test_context(self): self.page.context_int.delete(0, 'end') self.page.context_int.insert(0, '1') self.assertEqual(extpage, {'CodeContext': {'maxlines': '1'}}) + +#unittest.skip("Nothing here yet TODO") +class ExtPageTest(unittest.TestCase): + """Test that the help source list works correctly.""" + @classmethod + def setUpClass(cls): + page = dialog.extpage + dialog.note.select(page) + + +class HelpSourceTest(unittest.TestCase): + """Test that the help source list works correctly.""" + @classmethod + def setUpClass(cls): + page = dialog.extpage + dialog.note.select(page) + frame = cls.frame = page.frame_help + frame.set = frame.set_add_delete_state = Func() + frame.upc = frame.update_help_changes = Func() + frame.update() + + @classmethod + def tearDownClass(cls): + frame = cls.frame + del frame.set, frame.set_add_delete_state + del frame.upc, frame.update_help_changes + frame.helplist.delete(0, 'end') + frame.user_helplist.clear() + + def setUp(self): + changes.clear() + + def test_load_helplist(self): + eq = self.assertEqual + fr = self.frame + fr.helplist.insert('end', 'bad') + fr.user_helplist = ['bad', 'worse'] + idleConf.SetOption('main', 'HelpFiles', '1', 'name;file') + fr.load_helplist() + eq(fr.helplist.get(0, 'end'), ('name',)) + eq(fr.user_helplist, [('name', 'file', '1')]) + def test_source_selected(self): - d = self.page - d.set = d.set_add_delete_state - d.upc = d.update_help_changes - helplist = d.helplist + fr = self.frame + fr.set = fr.set_add_delete_state + fr.upc = fr.update_help_changes + helplist = fr.helplist dex = 'end' helplist.insert(dex, 'source') helplist.activate(dex) @@ -1321,38 +1355,38 @@ def test_source_selected(self): x, y, dx, dy = helplist.bbox(dex) x += dx // 2 y += dy // 2 - d.set.called = d.upc.called = 0 + fr.set.called = fr.upc.called = 0 helplist.event_generate('', x=0, y=0) helplist.event_generate('', x=x, y=y) helplist.event_generate('', x=x, y=y) helplist.event_generate('', x=x, y=y) self.assertEqual(helplist.get('anchor'), 'source') - self.assertTrue(d.set.called) - self.assertFalse(d.upc.called) + self.assertTrue(fr.set.called) + self.assertFalse(fr.upc.called) def test_set_add_delete_state(self): # Call with 0 items, 1 unselected item, 1 selected item. eq = self.assertEqual - d = self.page - del d.set_add_delete_state # Unmask method. - sad = d.set_add_delete_state - h = d.helplist + fr = self.frame + del fr.set_add_delete_state # Unmask method. + sad = fr.set_add_delete_state + h = fr.helplist h.delete(0, 'end') sad() - eq(d.button_helplist_edit.state(), ('disabled',)) - eq(d.button_helplist_remove.state(), ('disabled',)) + eq(fr.button_helplist_edit.state(), ('disabled',)) + eq(fr.button_helplist_remove.state(), ('disabled',)) h.insert(0, 'source') sad() - eq(d.button_helplist_edit.state(), ('disabled',)) - eq(d.button_helplist_remove.state(), ('disabled',)) + eq(fr.button_helplist_edit.state(), ('disabled',)) + eq(fr.button_helplist_remove.state(), ('disabled',)) h.selection_set(0) sad() - eq(d.button_helplist_edit.state(), ()) - eq(d.button_helplist_remove.state(), ()) - d.set_add_delete_state = Func() # Mask method. + eq(fr.button_helplist_edit.state(), ()) + eq(fr.button_helplist_remove.state(), ()) + fr.set_add_delete_state = Func() # Mask method. def test_helplist_item_add(self): # Call without and twice with HelpSource result. @@ -1360,25 +1394,25 @@ def test_helplist_item_add(self): eq = self.assertEqual orig_helpsource = configdialog.HelpSource hs = configdialog.HelpSource = Func(return_self=True) - d = self.page - d.helplist.delete(0, 'end') - d.user_helplist.clear() - d.set.called = d.upc.called = 0 + fr = self.frame + fr.helplist.delete(0, 'end') + fr.user_helplist.clear() + fr.set.called = fr.upc.called = 0 hs.result = '' - d.helplist_item_add() - self.assertTrue(list(d.helplist.get(0, 'end')) == - d.user_helplist == []) - self.assertFalse(d.upc.called) + fr.helplist_item_add() + self.assertTrue(list(fr.helplist.get(0, 'end')) == + fr.user_helplist == []) + self.assertFalse(fr.upc.called) hs.result = ('name1', 'file1') - d.helplist_item_add() + fr.helplist_item_add() hs.result = ('name2', 'file2') - d.helplist_item_add() - eq(d.helplist.get(0, 'end'), ('name1', 'name2')) - eq(d.user_helplist, [('name1', 'file1'), ('name2', 'file2')]) - eq(d.upc.called, 2) - self.assertFalse(d.set.called) + fr.helplist_item_add() + eq(fr.helplist.get(0, 'end'), ('name1', 'name2')) + eq(fr.user_helplist, [('name1', 'file1'), ('name2', 'file2')]) + eq(fr.upc.called, 2) + self.assertFalse(fr.set.called) configdialog.HelpSource = orig_helpsource @@ -1387,58 +1421,58 @@ def test_helplist_item_edit(self): eq = self.assertEqual orig_helpsource = configdialog.HelpSource hs = configdialog.HelpSource = Func(return_self=True) - d = self.page - d.helplist.delete(0, 'end') - d.helplist.insert(0, 'name1') - d.helplist.selection_set(0) - d.helplist.selection_anchor(0) - d.user_helplist.clear() - d.user_helplist.append(('name1', 'file1')) - d.set.called = d.upc.called = 0 + fr = self.frame + fr.helplist.delete(0, 'end') + fr.helplist.insert(0, 'name1') + fr.helplist.selection_set(0) + fr.helplist.selection_anchor(0) + fr.user_helplist.clear() + fr.user_helplist.append(('name1', 'file1')) + fr.set.called = fr.upc.called = 0 hs.result = '' - d.helplist_item_edit() + fr.helplist_item_edit() hs.result = ('name1', 'file1') - d.helplist_item_edit() - eq(d.helplist.get(0, 'end'), ('name1',)) - eq(d.user_helplist, [('name1', 'file1')]) - self.assertFalse(d.upc.called) + fr.helplist_item_edit() + eq(fr.helplist.get(0, 'end'), ('name1',)) + eq(fr.user_helplist, [('name1', 'file1')]) + self.assertFalse(fr.upc.called) hs.result = ('name2', 'file2') - d.helplist_item_edit() - eq(d.helplist.get(0, 'end'), ('name2',)) - eq(d.user_helplist, [('name2', 'file2')]) - self.assertTrue(d.upc.called == d.set.called == 1) + fr.helplist_item_edit() + eq(fr.helplist.get(0, 'end'), ('name2',)) + eq(fr.user_helplist, [('name2', 'file2')]) + self.assertTrue(fr.upc.called == fr.set.called == 1) configdialog.HelpSource = orig_helpsource def test_helplist_item_remove(self): eq = self.assertEqual - d = self.page - d.helplist.delete(0, 'end') - d.helplist.insert(0, 'name1') - d.helplist.selection_set(0) - d.helplist.selection_anchor(0) - d.user_helplist.clear() - d.user_helplist.append(('name1', 'file1')) - d.set.called = d.upc.called = 0 - - d.helplist_item_remove() - eq(d.helplist.get(0, 'end'), ()) - eq(d.user_helplist, []) - self.assertTrue(d.upc.called == d.set.called == 1) + fr = self.frame + fr.helplist.delete(0, 'end') + fr.helplist.insert(0, 'name1') + fr.helplist.selection_set(0) + fr.helplist.selection_anchor(0) + fr.user_helplist.clear() + fr.user_helplist.append(('name1', 'file1')) + fr.set.called = fr.upc.called = 0 + + fr.helplist_item_remove() + eq(fr.helplist.get(0, 'end'), ()) + eq(fr.user_helplist, []) + self.assertTrue(fr.upc.called == fr.set.called == 1) def test_update_help_changes(self): - d = self.page - del d.update_help_changes - d.user_helplist.clear() - d.user_helplist.append(('name1', 'file1')) - d.user_helplist.append(('name2', 'file2')) + fr = self.frame + del fr.update_help_changes + fr.user_helplist.clear() + fr.user_helplist.append(('name1', 'file1')) + fr.user_helplist.append(('name2', 'file2')) - d.update_help_changes() + fr.update_help_changes() self.assertEqual(mainpage['HelpFiles'], {'1': 'name1;file1', '2': 'name2;file2'}) - d.update_help_changes = Func() + fr.update_help_changes = Func() class VarTraceTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_macosx.py b/Lib/idlelib/idle_test/test_macosx.py index b6bd922e4b99dd..86da8849e5ca00 100644 --- a/Lib/idlelib/idle_test/test_macosx.py +++ b/Lib/idlelib/idle_test/test_macosx.py @@ -12,6 +12,15 @@ alltypes = mactypes | nontypes +def setUpModule(): + global orig_tktype + orig_tktype = macosx._tk_type + + +def tearDownModule(): + macosx._tk_type = orig_tktype + + class InitTktypeTest(unittest.TestCase): "Test _init_tk_type." @@ -34,7 +43,7 @@ def test_init_sets_tktype(self): for platform, types in ('darwin', alltypes), ('other', nontypes): with self.subTest(platform=platform): macosx.platform = platform - macosx._tk_type == None + macosx._tk_type = None macosx._init_tk_type() self.assertIn(macosx._tk_type, types) diff --git a/Lib/idlelib/idle_test/test_multicall.py b/Lib/idlelib/idle_test/test_multicall.py index ba582bb3ca51b4..b3a3bfb88f9c31 100644 --- a/Lib/idlelib/idle_test/test_multicall.py +++ b/Lib/idlelib/idle_test/test_multicall.py @@ -37,7 +37,7 @@ def test_init(self): def test_yview(self): # Added for tree.wheel_event - # (it depends on yview to not be overriden) + # (it depends on yview to not be overridden) mc = self.mc self.assertIs(mc.yview, Text.yview) mctext = self.mc(self.root) diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index fb5726db1d821e..384db566ac76cd 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -284,7 +284,7 @@ def test_get_num_lines_in_stmt(self): tests = ( TestInfo('[x for x in a]\n', 1), # Closed on one line. TestInfo('[x\nfor x in a\n', 2), # Not closed. - TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes. + TestInfo('[x\\\nfor x in a\\\n', 2), # "", unneeded backslashes. TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line. TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1), TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1), diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index e968862688b95e..bb12b2b08652d5 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -1,4 +1,4 @@ -"""Test query, coverage 93%). +"""Test query, coverage 93%. Non-gui tests for Query, SectionName, ModuleName, and HelpSource use dummy versions that extract the non-gui methods and add other needed @@ -136,8 +136,8 @@ def test_good_module_name(self): dialog = self.Dummy_ModuleName('idlelib') self.assertTrue(dialog.entry_ok().endswith('__init__.py')) self.assertEqual(dialog.entry_error['text'], '') - dialog = self.Dummy_ModuleName('os.path') - self.assertTrue(dialog.entry_ok().endswith('path.py')) + dialog = self.Dummy_ModuleName('idlelib.idle') + self.assertTrue(dialog.entry_ok().endswith('idle.py')) self.assertEqual(dialog.entry_error['text'], '') diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index a31671ee0485fa..ec4637c5ca617a 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -1,4 +1,4 @@ -"Test run, coverage 49%." +"Test run, coverage 54%." from idlelib import run import io @@ -12,7 +12,7 @@ idlelib.testing = True # Use {} for executing test user code. -class PrintExceptionTest(unittest.TestCase): +class ExceptionTest(unittest.TestCase): def test_print_exception_unhashable(self): class UnhashableException(Exception): @@ -28,8 +28,7 @@ def __eq__(self, other): raise ex1 except UnhashableException: with captured_stderr() as output: - with mock.patch.object(run, - 'cleanup_traceback') as ct: + with mock.patch.object(run, 'cleanup_traceback') as ct: ct.side_effect = lambda t, e: t run.print_exception() @@ -38,6 +37,46 @@ def __eq__(self, other): self.assertIn('UnhashableException: ex2', tb[3]) self.assertIn('UnhashableException: ex1', tb[10]) + data = (('1/0', ZeroDivisionError, "division by zero\n"), + ('abc', NameError, "name 'abc' is not defined. " + "Did you mean: 'abs'?\n"), + ('int.reel', AttributeError, + "type object 'int' has no attribute 'reel'. " + "Did you mean: 'real'?\n"), + ) + + def test_get_message(self): + for code, exc, msg in self.data: + with self.subTest(code=code): + try: + eval(compile(code, '', 'eval')) + except exc: + typ, val, tb = sys.exc_info() + actual = run.get_message_lines(typ, val, tb)[0] + expect = f'{exc.__name__}: {msg}' + self.assertEqual(actual, expect) + + @mock.patch.object(run, 'cleanup_traceback', + new_callable=lambda: (lambda t, e: None)) + def test_get_multiple_message(self, mock): + d = self.data + data2 = ((d[0], d[1]), (d[1], d[2]), (d[2], d[0])) + subtests = 0 + for (code1, exc1, msg1), (code2, exc2, msg2) in data2: + with self.subTest(codes=(code1,code2)): + try: + eval(compile(code1, '', 'eval')) + except exc1: + try: + eval(compile(code2, '', 'eval')) + except exc2: + with captured_stderr() as output: + run.print_exception() + actual = output.getvalue() + self.assertIn(msg1, actual) + self.assertIn(msg2, actual) + subtests += 1 + self.assertEqual(subtests, len(data2)) # All subtests ran? # StdioFile tests. diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py index 43e8137d7079c9..53ac3eb27335d7 100644 --- a/Lib/idlelib/idle_test/test_sidebar.py +++ b/Lib/idlelib/idle_test/test_sidebar.py @@ -510,19 +510,19 @@ def test_initial_state(self): ) self.assert_sidebar_lines_synced() - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_single_empty_input(self): self.do_input('\n') yield self.assert_sidebar_lines_end_with(['>>>', '>>>']) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_single_line_statement(self): self.do_input('1\n') yield self.assert_sidebar_lines_end_with(['>>>', None, '>>>']) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_multi_line_statement(self): # Block statements are not indented because IDLE auto-indents. self.do_input(dedent('''\ @@ -540,14 +540,14 @@ def test_multi_line_statement(self): '>>>', ]) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_single_long_line_wraps(self): self.do_input('1' * 200 + '\n') yield self.assert_sidebar_lines_end_with(['>>>', None, '>>>']) self.assert_sidebar_lines_synced() - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_squeeze_multi_line_output(self): shell = self.shell text = shell.text @@ -567,7 +567,7 @@ def test_squeeze_multi_line_output(self): self.assert_sidebar_lines_end_with(['>>>', None, None, None, '>>>']) self.assert_sidebar_lines_synced() - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_interrupt_recall_undo_redo(self): text = self.shell.text # Block statements are not indented because IDLE auto-indents. @@ -613,7 +613,7 @@ def test_interrupt_recall_undo_redo(self): ['>>>', '...', '...', '...', None, '>>>'] ) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_very_long_wrapped_line(self): with swap_attr(self.shell, 'squeezer', None): self.do_input('x = ' + '1'*10_000 + '\n') @@ -678,7 +678,7 @@ def get_sidebar_colors(): sidebar.update_colors() self.assertEqual(get_sidebar_colors(), test_colors) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_mousewheel(self): sidebar = self.shell.shell_sidebar text = self.shell.text @@ -703,7 +703,7 @@ def test_mousewheel(self): yield self.assertIsNotNone(text.dlineinfo(text.index(f'{last_lineno}.0'))) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_copy(self): sidebar = self.shell.shell_sidebar text = self.shell.text @@ -728,7 +728,7 @@ def test_copy(self): copied_text = text.clipboard_get() self.assertEqual(copied_text, selected_text) - @run_in_tk_mainloop + @run_in_tk_mainloop() def test_copy_with_prompts(self): sidebar = self.shell.shell_sidebar text = self.shell.text diff --git a/Lib/idlelib/idle_test/tkinter_testing_utils.py b/Lib/idlelib/idle_test/tkinter_testing_utils.py index a9f8386e2cd9f6..a89839bbe38add 100644 --- a/Lib/idlelib/idle_test/tkinter_testing_utils.py +++ b/Lib/idlelib/idle_test/tkinter_testing_utils.py @@ -2,7 +2,7 @@ import functools -def run_in_tk_mainloop(test_method): +def run_in_tk_mainloop(delay=1): """Decorator for running a test method with a real Tk mainloop. This starts a Tk mainloop before running the test, and stops it @@ -13,44 +13,50 @@ def run_in_tk_mainloop(test_method): using "yield" to allow the mainloop to process events and "after" callbacks, and then continue the test from that point. + The delay argument is passed into root.after(...) calls as the number + of ms to wait before passing execution back to the generator function. + This also assumes that the test class has a .root attribute, which is a tkinter.Tk object. For example (from test_sidebar.py): - @run_test_with_tk_mainloop + @run_test_with_tk_mainloop() def test_single_empty_input(self): self.do_input('\n') yield self.assert_sidebar_lines_end_with(['>>>', '>>>']) """ - @functools.wraps(test_method) - def new_test_method(self): - test_generator = test_method(self) - root = self.root - # Exceptions raised by self.assert...() need to be raised - # outside of the after() callback in order for the test - # harness to capture them. - exception = None - def after_callback(): - nonlocal exception - try: - next(test_generator) - except StopIteration: - root.quit() - except Exception as exc: - exception = exc - root.quit() - else: - # Schedule the Tk mainloop to call this function again, - # using a robust method of ensuring that it gets a - # chance to process queued events before doing so. - # See: https://stackoverflow.com/q/18499082#comment65004099_38817470 - root.after(1, root.after_idle, after_callback) - root.after(0, root.after_idle, after_callback) - root.mainloop() - - if exception: - raise exception - - return new_test_method + def decorator(test_method): + @functools.wraps(test_method) + def new_test_method(self): + test_generator = test_method(self) + root = self.root + # Exceptions raised by self.assert...() need to be raised + # outside of the after() callback in order for the test + # harness to capture them. + exception = None + def after_callback(): + nonlocal exception + try: + next(test_generator) + except StopIteration: + root.quit() + except Exception as exc: + exception = exc + root.quit() + else: + # Schedule the Tk mainloop to call this function again, + # using a robust method of ensuring that it gets a + # chance to process queued events before doing so. + # See: https://stackoverflow.com/q/18499082#comment65004099_38817470 + root.after(delay, root.after_idle, after_callback) + root.after(0, root.after_idle, after_callback) + root.mainloop() + + if exception: + raise exception + + return new_test_method + + return decorator diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py index eeaab59ae80295..470de5d89cadd4 100644 --- a/Lib/idlelib/macosx.py +++ b/Lib/idlelib/macosx.py @@ -83,7 +83,7 @@ def tkVersionWarning(root): return False return ("WARNING: The version of Tcl/Tk ({0}) in use may" " be unstable.\n" - "Visit http://www.python.org/download/mac/tcltk/" + "Visit https://www.python.org/download/mac/tcltk/" " for current information.".format(patchlevel)) else: return False diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 4e7440038ac997..6c333b0bc3b818 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -66,6 +66,13 @@ HOST = '127.0.0.1' # python execution server on localhost loopback PORT = 0 # someday pass in host, port for remote debug capability +try: # In case IDLE started with -n. + eof = 'Ctrl-D (end-of-file)' + exit.eof = eof + quit.eof = eof +except NameError: # In case python started with -S. + pass + # Override warnings module to write to warning_stream. Initialize to send IDLE # internal warnings to the console. ScriptBinding.check_syntax() will # temporarily redirect the stream to the shell window to display warnings when diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 07e9a2bf9ceeae..47c4cbdcb8c3f9 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -4,6 +4,7 @@ f'''{sys.executable} -c "__import__('idlelib.run').run.main()"''' '.run' is needed because __import__ returns idlelib, not idlelib.run. """ +import contextlib import functools import io import linecache @@ -39,6 +40,13 @@ LOCALHOST = '127.0.0.1' +try: + eof = 'Ctrl-D (end-of-file)' + exit.eof = eof + quit.eof = eof +except NameError: # In case subprocess started with -S (maybe in future). + pass + def idle_formatwarning(message, category, filename, lineno, line=None): """Format warnings the IDLE way.""" @@ -211,6 +219,19 @@ def show_socket_error(err, address): parent=root) root.destroy() + +def get_message_lines(typ, exc, tb): + "Return line composing the exception message." + if typ in (AttributeError, NameError): + # 3.10+ hints are not directly accessible from python (#44026). + err = io.StringIO() + with contextlib.redirect_stderr(err): + sys.__excepthook__(typ, exc, tb) + return [err.getvalue().split("\n")[-2] + "\n"] + else: + return traceback.format_exception_only(typ, exc) + + def print_exception(): import linecache linecache.checkcache() @@ -241,7 +262,7 @@ def print_exc(typ, exc, tb): "debugger_r.py", "bdb.py") cleanup_traceback(tbe, exclude) traceback.print_list(tbe, file=efile) - lines = traceback.format_exception_only(typ, exc) + lines = get_message_lines(typ, exc, tb) for line in lines: print(line, end='', file=efile) diff --git a/Lib/importlib/__init__.py b/Lib/importlib/__init__.py index a510f08db48a89..ce61883288aa35 100644 --- a/Lib/importlib/__init__.py +++ b/Lib/importlib/__init__.py @@ -79,7 +79,7 @@ def find_loader(name, path=None): """ warnings.warn('Deprecated since Python 3.4 and slated for removal in ' - 'Python 3.10; use importlib.util.find_spec() instead', + 'Python 3.12; use importlib.util.find_spec() instead', DeprecationWarning, stacklevel=2) try: loader = sys.modules[name].__loader__ diff --git a/Lib/importlib/_adapters.py b/Lib/importlib/_adapters.py index eedde49dd03ad9..e72edd10705c26 100644 --- a/Lib/importlib/_adapters.py +++ b/Lib/importlib/_adapters.py @@ -46,10 +46,11 @@ def is_dir(self): def joinpath(self, other): return DegenerateFiles.Path() + @property def name(self): return '' - def open(self): + def open(self, mode='rb', *args, **kwargs): raise ValueError() def __init__(self, spec): diff --git a/Lib/importlib/_common.py b/Lib/importlib/_common.py index 03383048ad7365..549fee379a415f 100644 --- a/Lib/importlib/_common.py +++ b/Lib/importlib/_common.py @@ -7,7 +7,7 @@ import importlib from typing import Union, Any, Optional -from .abc import ResourceReader +from .abc import ResourceReader, Traversable from ._adapters import wrap_spec @@ -15,6 +15,7 @@ def files(package): + # type: (Package) -> Traversable """ Get a Traversable resource from a package """ @@ -30,7 +31,7 @@ def normalize_path(path): str_path = str(path) parent, file_name = os.path.split(str_path) if parent: - raise ValueError('{!r} must be only a file name'.format(path)) + raise ValueError(f'{path!r} must be only a file name') return file_name @@ -64,7 +65,7 @@ def get_package(package): """ resolved = resolve(package) if wrap_spec(resolved).submodule_search_locations is None: - raise TypeError('{!r} is not a package'.format(package)) + raise TypeError(f'{package!r} is not a package') return resolved diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index 142162196fa9b3..ec41ed39157a93 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -15,9 +15,11 @@ import collections from . import _adapters, _meta +from ._meta import PackageMetadata from ._collections import FreezableDefaultDict, Pair from ._functools import method_cache from ._itertools import unique_everseen +from ._meta import PackageMetadata, SimplePath from contextlib import suppress from importlib import import_module @@ -29,6 +31,7 @@ __all__ = [ 'Distribution', 'DistributionFinder', + 'PackageMetadata', 'PackageNotFoundError', 'distribution', 'distributions', @@ -45,8 +48,7 @@ class PackageNotFoundError(ModuleNotFoundError): """The package was not found.""" def __str__(self): - tmpl = "No package metadata was found for {self.name}" - return tmpl.format(**locals()) + return f"No package metadata was found for {self.name}" @property def name(self): @@ -202,7 +204,100 @@ def matches(self, **params): return all(map(operator.eq, params.values(), attrs)) -class EntryPoints(tuple): +class DeprecatedList(list): + """ + Allow an otherwise immutable object to implement mutability + for compatibility. + + >>> recwarn = getfixture('recwarn') + >>> dl = DeprecatedList(range(3)) + >>> dl[0] = 1 + >>> dl.append(3) + >>> del dl[3] + >>> dl.reverse() + >>> dl.sort() + >>> dl.extend([4]) + >>> dl.pop(-1) + 4 + >>> dl.remove(1) + >>> dl += [5] + >>> dl + [6] + [1, 2, 5, 6] + >>> dl + (6,) + [1, 2, 5, 6] + >>> dl.insert(0, 0) + >>> dl + [0, 1, 2, 5] + >>> dl == [0, 1, 2, 5] + True + >>> dl == (0, 1, 2, 5) + True + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "EntryPoints list interface is deprecated. Cast to list if needed.", + DeprecationWarning, + stacklevel=2, + ) + + def __setitem__(self, *args, **kwargs): + self._warn() + return super().__setitem__(*args, **kwargs) + + def __delitem__(self, *args, **kwargs): + self._warn() + return super().__delitem__(*args, **kwargs) + + def append(self, *args, **kwargs): + self._warn() + return super().append(*args, **kwargs) + + def reverse(self, *args, **kwargs): + self._warn() + return super().reverse(*args, **kwargs) + + def extend(self, *args, **kwargs): + self._warn() + return super().extend(*args, **kwargs) + + def pop(self, *args, **kwargs): + self._warn() + return super().pop(*args, **kwargs) + + def remove(self, *args, **kwargs): + self._warn() + return super().remove(*args, **kwargs) + + def __iadd__(self, *args, **kwargs): + self._warn() + return super().__iadd__(*args, **kwargs) + + def __add__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + return self.__class__(tuple(self) + other) + + def insert(self, *args, **kwargs): + self._warn() + return super().insert(*args, **kwargs) + + def sort(self, *args, **kwargs): + self._warn() + return super().sort(*args, **kwargs) + + def __eq__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + + return tuple(self).__eq__(other) + + +class EntryPoints(DeprecatedList): """ An immutable collection of selectable EntryPoint objects. """ @@ -213,6 +308,14 @@ def __getitem__(self, name): # -> EntryPoint: """ Get the EntryPoint in self matching name. """ + if isinstance(name, int): + warnings.warn( + "Accessing entry points by index is deprecated. " + "Cast to tuple if needed.", + DeprecationWarning, + stacklevel=2, + ) + return super().__getitem__(name) try: return next(iter(self.select(name=name))) except StopIteration: @@ -259,14 +362,6 @@ def _parse_groups(text): ) -def flake8_bypass(func): - # defer inspect import as performance optimization. - import inspect - - is_flake8 = any('flake8' in str(frame.filename) for frame in inspect.stack()[:5]) - return func if not is_flake8 else lambda: None - - class Deprecated: """ Compatibility add-in for mapping to indicate that @@ -302,7 +397,7 @@ def __getitem__(self, name): return super().__getitem__(name) def get(self, name, default=None): - flake8_bypass(self._warn)() + self._warn() return super().get(name, default) def __iter__(self): @@ -383,7 +478,7 @@ def __init__(self, spec): self.mode, _, self.value = spec.partition('=') def __repr__(self): - return ''.format(self.mode, self.value) + return f'' class Distribution: @@ -491,6 +586,11 @@ def name(self): """Return the 'Name' metadata for the distribution package.""" return self.metadata['Name'] + @property + def _normalized_name(self): + """Return a normalized version of the name.""" + return Prepared.normalize(self.name) + @property def version(self): """Return the 'Version' metadata for the distribution package.""" @@ -567,18 +667,27 @@ def _convert_egg_info_reqs_to_simple_reqs(sections): """ def make_condition(name): - return name and 'extra == "{name}"'.format(name=name) + return name and f'extra == "{name}"' - def parse_condition(section): + def quoted_marker(section): section = section or '' extra, sep, markers = section.partition(':') if extra and markers: - markers = '({markers})'.format(markers=markers) + markers = f'({markers})' conditions = list(filter(None, [markers, make_condition(extra)])) return '; ' + ' and '.join(conditions) if conditions else '' + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + for section in sections: - yield section.value + parse_condition(section.name) + space = url_req_space(section.value) + yield section.value + space + quoted_marker(section.name) class DistributionFinder(MetaPathFinder): @@ -610,10 +719,11 @@ def __init__(self, **kwargs): @property def path(self): """ - The path that a distribution finder should search. + The sequence of directory path that a distribution finder + should search. - Typically refers to Python package paths and defaults - to ``sys.path``. + Typically refers to Python installed package paths such as + "site-packages" directories and defaults to ``sys.path``. """ return vars(self).get('path', sys.path) @@ -647,7 +757,7 @@ def joinpath(self, child): def children(self): with suppress(Exception): - return os.listdir(self.root or '') + return os.listdir(self.root or '.') with suppress(Exception): return self.zip_children() return [] @@ -770,11 +880,10 @@ def invalidate_caches(cls): class PathDistribution(Distribution): - def __init__(self, path): - """Construct a distribution from a path to the metadata directory. + def __init__(self, path: SimplePath): + """Construct a distribution. - :param path: A pathlib.Path or similar object supporting - .joinpath(), __div__, .parent, and .read_text(). + :param path: SimplePath indicating the metadata directory. """ self._path = path @@ -793,6 +902,22 @@ def read_text(self, filename): def locate_file(self, path): return self._path.parent / path + @property + def _normalized_name(self): + """ + Performance optimization: where possible, resolve the + normalized name from the file system path. + """ + stem = os.path.basename(str(self._path)) + return self._name_from_stem(stem) or super()._normalized_name + + def _name_from_stem(self, stem): + name, ext = os.path.splitext(stem) + if ext not in ('.dist-info', '.egg-info'): + return + name, sep, rest = stem.partition('-') + return name + def distribution(distribution_name): """Get the ``Distribution`` instance for the named package. @@ -847,7 +972,8 @@ def entry_points(**params) -> Union[EntryPoints, SelectableGroups]: :return: EntryPoints or SelectableGroups for all installed packages. """ - unique = functools.partial(unique_everseen, key=operator.attrgetter('name')) + norm_name = operator.attrgetter('_normalized_name') + unique = functools.partial(unique_everseen, key=norm_name) eps = itertools.chain.from_iterable( dist.entry_points for dist in unique(distributions()) ) @@ -868,7 +994,7 @@ def requires(distribution_name): Return a list of requirements for the named package. :return: An iterator of requirements, suitable for - packaging.requirement.Requirement. + packaging.requirement.Requirement. """ return distribution(distribution_name).requires diff --git a/Lib/importlib/metadata/_adapters.py b/Lib/importlib/metadata/_adapters.py index ab086180fc35fc..aa460d3eda50fb 100644 --- a/Lib/importlib/metadata/_adapters.py +++ b/Lib/importlib/metadata/_adapters.py @@ -19,6 +19,7 @@ class Message(email.message.Message): 'Requires-Dist', 'Requires-External', 'Supported-Platform', + 'Dynamic', ], ) ) diff --git a/Lib/importlib/metadata/_meta.py b/Lib/importlib/metadata/_meta.py index 04d9a0235368ed..1a6edbf957d5a0 100644 --- a/Lib/importlib/metadata/_meta.py +++ b/Lib/importlib/metadata/_meta.py @@ -27,3 +27,21 @@ def json(self) -> Dict[str, Union[str, List[str]]]: """ A JSON-compatible form of the metadata. """ + + +class SimplePath(Protocol): + """ + A minimal subset of pathlib.Path required by PathDistribution. + """ + + def joinpath(self) -> 'SimplePath': + ... # pragma: no cover + + def __div__(self) -> 'SimplePath': + ... # pragma: no cover + + def parent(self) -> 'SimplePath': + ... # pragma: no cover + + def read_text(self) -> str: + ... # pragma: no cover diff --git a/Lib/importlib/readers.py b/Lib/importlib/readers.py index 535c8283e9081d..41089c071d8683 100644 --- a/Lib/importlib/readers.py +++ b/Lib/importlib/readers.py @@ -94,15 +94,15 @@ def joinpath(self, child): __truediv__ = joinpath def open(self, *args, **kwargs): - raise FileNotFoundError('{} is not a file'.format(self)) + raise FileNotFoundError(f'{self} is not a file') + @property def name(self): return self._paths[0].name def __repr__(self): - return 'MultiplexedPath({})'.format( - ', '.join("'{}'".format(path) for path in self._paths) - ) + paths = ', '.join(f"'{path}'" for path in self._paths) + return f'MultiplexedPath({paths})' class NamespaceReader(abc.TraversableResources): diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index db0e0c0eeff80b..8a98663ff8e6d5 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -68,9 +68,7 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO: if data is not None: return BytesIO(data) - raise FileNotFoundError( - '{!r} resource not found in {!r}'.format(resource, spec.name) - ) + raise FileNotFoundError(f'{resource!r} resource not found in {spec.name!r}') def open_text( diff --git a/Lib/inspect.py b/Lib/inspect.py index 9f8cc01310f10e..6d43d8dad46b99 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -395,7 +395,7 @@ def iscode(object): co_kwonlyargcount number of keyword only arguments (not including ** arg) co_lnotab encoded mapping of line numbers to bytecode indices co_name name with which this code object was defined - co_names tuple of names of local variables + co_names tuple of names other than arguments and function locals co_nlocals number of local variables co_stacksize virtual machine stack space required co_varnames tuple of names of arguments and local variables""" @@ -781,6 +781,8 @@ def getfile(object): module = sys.modules.get(object.__module__) if getattr(module, '__file__', None): return module.__file__ + if object.__module__ == '__main__': + raise OSError('source code not available') raise TypeError('{!r} is a built-in class'.format(object)) if ismethod(object): object = object.__func__ @@ -857,7 +859,7 @@ def getmodule(object, _filename=None): # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) - except TypeError: + except (TypeError, FileNotFoundError): return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) @@ -1355,6 +1357,8 @@ def getargvalues(frame): def formatannotation(annotation, base_module=None): if getattr(annotation, '__module__', None) == 'typing': return repr(annotation).replace('typing.', '') + if isinstance(annotation, types.GenericAlias): + return str(annotation) if isinstance(annotation, type): if annotation.__module__ in ('builtins', base_module): return annotation.__qualname__ @@ -2471,15 +2475,23 @@ def _signature_from_callable(obj, *, if call is not None: sig = _get_signature_of(call) else: - # Now we check if the 'obj' class has a '__new__' method + factory_method = None new = _signature_get_user_defined_method(obj, '__new__') - if new is not None: - sig = _get_signature_of(new) - else: - # Finally, we should have at least __init__ implemented - init = _signature_get_user_defined_method(obj, '__init__') - if init is not None: - sig = _get_signature_of(init) + init = _signature_get_user_defined_method(obj, '__init__') + # Now we check if the 'obj' class has an own '__new__' method + if '__new__' in obj.__dict__: + factory_method = new + # or an own '__init__' method + elif '__init__' in obj.__dict__: + factory_method = init + # If not, we take inherited '__new__' or '__init__', if present + elif new is not None: + factory_method = new + elif init is not None: + factory_method = init + + if factory_method is not None: + sig = _get_signature_of(factory_method) if sig is None: # At this point we know, that `obj` is a class, with no user- @@ -2561,6 +2573,9 @@ class _ParameterKind(enum.IntEnum): KEYWORD_ONLY = 3 VAR_KEYWORD = 4 + def __str__(self): + return self._name_ + @property def description(self): return _PARAM_NAME_MAPPING[self] diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index af7aedfa6e51a1..4a6496a5da3ef8 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -16,6 +16,7 @@ IPV4LENGTH = 32 IPV6LENGTH = 128 + class AddressValueError(ValueError): """A Value Error related to the address.""" @@ -2002,9 +2003,13 @@ def is_private(self): Returns: A boolean, True if the address is reserved per - iana-ipv6-special-registry. + iana-ipv6-special-registry, or is ipv4_mapped and is + reserved in the iana-ipv4-special-registry. """ + ipv4_mapped = self.ipv4_mapped + if ipv4_mapped is not None: + return ipv4_mapped.is_private return any(self in net for net in self._constants._private_networks) @property diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index 2c52bdeba67546..e4c21daaf3e47f 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -133,7 +133,7 @@ def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) @@ -195,7 +195,7 @@ def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will - result in an ``OverflowError`` (or worse). + result in an ``RecursionError`` (or worse). If ``allow_nan`` is false, then it will be a ``ValueError`` to serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py index c8c78b9c237652..21bff2c1a1fca3 100644 --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -116,7 +116,7 @@ def __init__(self, *, skipkeys=False, ensure_ascii=True, If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). + prevent an infinite recursion (which would cause an RecursionError). Otherwise, no such check takes place. If allow_nan is true, then NaN, Infinity, and -Infinity will be diff --git a/Lib/json/tool.py b/Lib/json/tool.py index 5dee0a744b2a99..0490b8c0be11df 100644 --- a/Lib/json/tool.py +++ b/Lib/json/tool.py @@ -13,6 +13,7 @@ import argparse import json import sys +from pathlib import Path def main(): @@ -25,9 +26,9 @@ def main(): help='a JSON file to be validated or pretty-printed', default=sys.stdin) parser.add_argument('outfile', nargs='?', - type=argparse.FileType('w', encoding="utf-8"), + type=Path, help='write the output of infile to outfile', - default=sys.stdout) + default=None) parser.add_argument('--sort-keys', action='store_true', default=False, help='sort the output of dictionaries alphabetically by key') parser.add_argument('--no-ensure-ascii', dest='ensure_ascii', action='store_false', @@ -58,15 +59,21 @@ def main(): dump_args['indent'] = None dump_args['separators'] = ',', ':' - with options.infile as infile, options.outfile as outfile: + with options.infile as infile: try: if options.json_lines: objs = (json.loads(line) for line in infile) else: - objs = (json.load(infile), ) - for obj in objs: - json.dump(obj, outfile, **dump_args) - outfile.write('\n') + objs = (json.load(infile),) + + if options.outfile is None: + out = sys.stdout + else: + out = options.outfile.open('w', encoding='utf-8') + with out as outfile: + for obj in objs: + json.dump(obj, outfile, **dump_args) + outfile.write('\n') except ValueError as e: raise SystemExit(e) diff --git a/Lib/lib2to3/fixes/fix_metaclass.py b/Lib/lib2to3/fixes/fix_metaclass.py index d1cd10d327587c..fe547b2228072a 100644 --- a/Lib/lib2to3/fixes/fix_metaclass.py +++ b/Lib/lib2to3/fixes/fix_metaclass.py @@ -51,7 +51,7 @@ def fixup_parse_tree(cls_node): # already in the preferred format, do nothing return - # !%@#! oneliners have no suite node, we have to fake one up + # !%@#! one-liners have no suite node, we have to fake one up for i, node in enumerate(cls_node.children): if node.type == token.COLON: break diff --git a/Lib/lib2to3/fixes/fix_paren.py b/Lib/lib2to3/fixes/fix_paren.py index b205aa7e1e93fb..df3da5f5232c9c 100644 --- a/Lib/lib2to3/fixes/fix_paren.py +++ b/Lib/lib2to3/fixes/fix_paren.py @@ -1,4 +1,4 @@ -"""Fixer that addes parentheses where they are required +"""Fixer that adds parentheses where they are required This converts ``[x for x in 1, 2]`` to ``[x for x in (1, 2)]``.""" diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py index 0e2685d40433d7..099dfa7798afd4 100644 --- a/Lib/lib2to3/pgen2/tokenize.py +++ b/Lib/lib2to3/pgen2/tokenize.py @@ -512,13 +512,14 @@ def generate_tokens(readline): stashed = tok continue - if token == 'def': + if token in ('def', 'for'): if (stashed and stashed[0] == NAME and stashed[1] == 'async'): - async_def = True - async_def_indent = indents[-1] + if token == 'def': + async_def = True + async_def_indent = indents[-1] yield (ASYNC, stashed[1], stashed[2], stashed[3], diff --git a/Lib/lib2to3/tests/data/py2_test_grammar.py b/Lib/lib2to3/tests/data/py2_test_grammar.py index b5a4137d1615ef..f9e4ea1374f907 100644 --- a/Lib/lib2to3/tests/data/py2_test_grammar.py +++ b/Lib/lib2to3/tests/data/py2_test_grammar.py @@ -8,7 +8,7 @@ # regression test, the filterwarnings() call has been added to # regrtest.py. -from test.test_support import run_unittest, check_syntax_error +from test.test_support import check_syntax_error import unittest import sys # testing import * @@ -735,7 +735,7 @@ def testSelectors(self): s = a[-5:] s = a[:-1] s = a[-4:-3] - # A rough test of SF bug 1333982. http://python.org/sf/1333982 + # A rough test of SF bug 1333982. https://python.org/sf/1333982 # The testing here is fairly incomplete. # Test cases should include: commas with 1 and 2 colons d = {} @@ -967,8 +967,5 @@ def _checkeval(msg, ret): self.assertEqual((6 < 4 if 0 else 2), 2) -def test_main(): - run_unittest(TokenTests, GrammarTests) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py index d06223207e1ec0..a4a3f7eac0dded 100644 --- a/Lib/lib2to3/tests/data/py3_test_grammar.py +++ b/Lib/lib2to3/tests/data/py3_test_grammar.py @@ -8,7 +8,7 @@ # regression test, the filterwarnings() call has been added to # regrtest.py. -from test.support import run_unittest, check_syntax_error +from test.support import check_syntax_error import unittest import sys # testing import * @@ -714,7 +714,7 @@ def testSelectors(self): s = a[-5:] s = a[:-1] s = a[-4:-3] - # A rough test of SF bug 1333982. http://python.org/sf/1333982 + # A rough test of SF bug 1333982. https://python.org/sf/1333982 # The testing here is fairly incomplete. # Test cases should include: commas with 1 and 2 colons d = {} @@ -952,8 +952,5 @@ def _checkeval(msg, ret): self.assertEqual((6 < 4 if 0 else 2), 2) -def test_main(): - run_unittest(TokenTests, GrammarTests) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py index 1aba0e88945a40..5eefb5aad7d49e 100644 --- a/Lib/lib2to3/tests/test_parser.py +++ b/Lib/lib2to3/tests/test_parser.py @@ -200,20 +200,27 @@ def test_async_var(self): self.validate("""await = 1""") self.validate("""def async(): pass""") - def test_async_with(self): + def test_async_for(self): self.validate("""async def foo(): async for a in b: pass""") - self.invalid_syntax("""def foo(): - async for a in b: pass""") - - def test_async_for(self): + def test_async_with(self): self.validate("""async def foo(): async with a: pass""") self.invalid_syntax("""def foo(): async with a: pass""") + def test_async_generator(self): + self.validate( + """async def foo(): + return (i * 2 async for i in arange(42))""" + ) + self.validate( + """def foo(): + return (i * 2 async for i in arange(42))""" + ) + class TestRaiseChanges(GrammarTest): def test_2x_style_1(self): diff --git a/Lib/linecache.py b/Lib/linecache.py index 513b17e999880b..23191d6501d2a8 100644 --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -154,7 +154,7 @@ def lazycache(filename, module_globals): :return: True if a lazy load is registered in the cache, otherwise False. To register such a load a module loader with a - get_source method must be found, the filename must be a cachable + get_source method must be found, the filename must be a cacheable filename, and the filename must not be already cached. """ if filename in cache: diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 555f598de7a925..19bd2bc20b2502 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -878,6 +878,7 @@ def __init__(self, level=NOTSET): self._name = None self.level = _checkLevel(level) self.formatter = None + self._closed = False # Add the handler to the global _handlerList (for cleanup on shutdown) _addHandlerRef(self) self.createLock() @@ -996,6 +997,7 @@ def close(self): #get the module data lock, as we're updating a shared structure. _acquireLock() try: #unlikely to raise an exception, but you never know... + self._closed = True if self._name and self._name in _handlers: del _handlers[self._name] finally: @@ -1184,6 +1186,8 @@ def close(self): finally: # Issue #19523: call unconditionally to # prevent a handler leak when delay is set + # Also see Issue #42378: we also rely on + # self._closed being set to True there StreamHandler.close(self) finally: self.release() @@ -1203,10 +1207,15 @@ def emit(self, record): If the stream was not opened because 'delay' was specified in the constructor, open it before calling the superclass's emit. + + If stream is not open, current mode is 'w' and `_closed=True`, record + will not be emitted (see Issue #42378). """ if self.stream is None: - self.stream = self._open() - StreamHandler.emit(self, record) + if self.mode != 'w' or not self._closed: + self.stream = self._open() + if self.stream: + StreamHandler.emit(self, record) def __repr__(self): level = getLevelName(self.level) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index b0d5885989ea42..89812e579c5a7f 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1,4 +1,4 @@ -# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,7 @@ Additional handlers for the logging package for Python. The core package is based on PEP 282 and comments thereto in comp.lang.python. -Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. To use, simply 'import logging.handlers' and log away! """ @@ -187,14 +187,17 @@ def shouldRollover(self, record): Basically, see if the supplied record would cause the file to exceed the size limit we have. """ + # See bpo-45401: Never rollover anything other than regular files + if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename): + return False if self.stream is None: # delay was set... self.stream = self._open() if self.maxBytes > 0: # are we rolling over? msg = "%s\n" % self.format(record) self.stream.seek(0, 2) #due to non-posix-compliant Windows feature if self.stream.tell() + len(msg) >= self.maxBytes: - return 1 - return 0 + return True + return False class TimedRotatingFileHandler(BaseRotatingHandler): """ @@ -255,9 +258,15 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, raise ValueError("Invalid rollover interval specified: %s" % self.when) self.extMatch = re.compile(self.extMatch, re.ASCII) - self.interval = self.interval * interval # multiply by units requested - # The following line added because the filename passed in could be a - # path object (see Issue #27493), but self.baseFilename will be a string + + if self.when == 'MIDNIGHT': + self.interval = self.interval # We want to ignore interval on + # midnight rotation to avoid any misinterpretations + else: + self.interval = self.interval * interval # multiply by units requested + # The following line added because the filename passed in could be a + # path object (see Issue #27493), but self.baseFilename will be a string + filename = self.baseFilename if os.path.exists(filename): t = os.stat(filename)[ST_MTIME] @@ -345,10 +354,13 @@ def shouldRollover(self, record): record is not used, as we are just comparing times, but it is needed so the method signatures are the same """ + # See bpo-45401: Never rollover anything other than regular files + if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename): + return False t = int(time.time()) if t >= self.rolloverAt: - return 1 - return 0 + return True + return False def getFilesToDelete(self): """ @@ -359,13 +371,32 @@ def getFilesToDelete(self): dirName, baseName = os.path.split(self.baseFilename) fileNames = os.listdir(dirName) result = [] - prefix = baseName + "." + # See bpo-44753: Don't use the extension when computing the prefix. + n, e = os.path.splitext(baseName) + prefix = n + '.' plen = len(prefix) for fileName in fileNames: + if self.namer is None: + # Our files will always start with baseName + if not fileName.startswith(baseName): + continue + else: + # Our files could be just about anything after custom naming, but + # likely candidates are of the form + # foo.log.DATETIME_SUFFIX or foo.DATETIME_SUFFIX.log + if (not fileName.startswith(baseName) and fileName.endswith(e) and + len(fileName) > (plen + 1) and not fileName[plen+1].isdigit()): + continue + if fileName[:plen] == prefix: suffix = fileName[plen:] - if self.extMatch.match(suffix): - result.append(os.path.join(dirName, fileName)) + # See bpo-45628: The date/time suffix could be anywhere in the + # filename + parts = suffix.split('.') + for part in parts: + if self.extMatch.match(part): + result.append(os.path.join(dirName, fileName)) + break if len(result) < self.backupCount: result = [] else: @@ -1147,7 +1178,7 @@ def close(self): class HTTPHandler(logging.Handler): """ - A class which sends records to a Web server, using either GET or + A class which sends records to a web server, using either GET or POST semantics. """ def __init__(self, host, url, method="GET", secure=False, credentials=None, @@ -1196,7 +1227,7 @@ def emit(self, record): """ Emit a record. - Send the record to the Web server as a percent-encoded dictionary + Send the record to the web server as a percent-encoded dictionary """ try: import urllib.parse diff --git a/Lib/lzma.py b/Lib/lzma.py index 2ada7d81d3c813..800f52198fbb79 100644 --- a/Lib/lzma.py +++ b/Lib/lzma.py @@ -221,22 +221,26 @@ def readline(self, size=-1): self._check_can_read() return self._buffer.readline(size) - def __iter__(self): - self._check_can_read() - return self._buffer.__iter__() - def write(self, data): """Write a bytes object to the file. Returns the number of uncompressed bytes written, which is - always len(data). Note that due to buffering, the file on disk - may not reflect the data written until close() is called. + always the length of data in bytes. Note that due to buffering, + the file on disk may not reflect the data written until close() + is called. """ self._check_can_write() + if isinstance(data, (bytes, bytearray)): + length = len(data) + else: + # accept any data that supports the buffer protocol + data = memoryview(data) + length = data.nbytes + compressed = self._compressor.compress(data) self._fp.write(compressed) - self._pos += len(data) - return len(data) + self._pos += length + return length def seek(self, offset, whence=io.SEEK_SET): """Change the file position. diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index 018793c4f01e46..c389685c08f6f3 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -27,6 +27,12 @@ import sys import posixpath import urllib.parse + +try: + from _winapi import _mimetypes_read_windows_registry +except ImportError: + _mimetypes_read_windows_registry = None + try: import winreg as _winreg except ImportError: @@ -169,7 +175,7 @@ def guess_all_extensions(self, type, strict=True): but non-standard types. """ type = type.lower() - extensions = self.types_map_inv[True].get(type, []) + extensions = list(self.types_map_inv[True].get(type, [])) if not strict: for ext in self.types_map_inv[False].get(type, []): if ext not in extensions: @@ -237,10 +243,21 @@ def read_windows_registry(self, strict=True): types. """ - # Windows only - if not _winreg: + if not _mimetypes_read_windows_registry and not _winreg: return + add_type = self.add_type + if strict: + add_type = lambda type, ext: self.add_type(type, ext, True) + + # Accelerated function if it is available + if _mimetypes_read_windows_registry: + _mimetypes_read_windows_registry(add_type) + elif _winreg: + self._read_windows_registry(add_type) + + @classmethod + def _read_windows_registry(cls, add_type): def enum_types(mimedb): i = 0 while True: @@ -265,7 +282,7 @@ def enum_types(mimedb): subkey, 'Content Type') if datatype != _winreg.REG_SZ: continue - self.add_type(mimetype, subkeyname, strict) + add_type(mimetype, subkeyname) except OSError: continue @@ -349,8 +366,8 @@ def init(files=None): if files is None or _db is None: db = MimeTypes() - if _winreg: - db.read_windows_registry() + # Quick return if not supported + db.read_windows_registry() if files is None: files = knownfiles diff --git a/Lib/msilib/schema.py b/Lib/msilib/schema.py index eeb3ecd27ab658..9f5745cfb14de2 100644 --- a/Lib/msilib/schema.py +++ b/Lib/msilib/schema.py @@ -664,7 +664,7 @@ ('Class','Component_','N',None, None, 'Component',1,'Identifier',None, 'Required foreign key into the Component Table, specifying the component for which to return a path when called through LocateComponent.',), ('Class','Context','N',None, None, None, None, 'Identifier',None, 'The numeric server context for this server. CLSCTX_xxxx',), ('Class','DefInprocHandler','Y',None, None, None, None, 'Filename','1;2;3','Optional default inproc handler. Only optionally provided if Context=CLSCTX_LOCAL_SERVER. Typically "ole32.dll" or "mapi32.dll"',), -('Class','FileTypeMask','Y',None, None, None, None, 'Text',None, 'Optional string containing information for the HKCRthis CLSID) key. If multiple patterns exist, they must be delimited by a semicolon, and numeric subkeys will be generated: 0,1,2...',), +('Class','FileTypeMask','Y',None, None, None, None, 'Text',None, 'Optional string containing information for the HKCRthis CLSID key. If multiple patterns exist, they must be delimited by a semicolon, and numeric subkeys will be generated: 0,1,2...',), ('Class','Icon_','Y',None, None, 'Icon',1,'Identifier',None, 'Optional foreign key into the Icon Table, specifying the icon file associated with this CLSID. Will be written under the DefaultIcon key.',), ('Class','IconIndex','Y',-32767,32767,None, None, None, None, 'Optional icon index.',), ('Class','ProgId_Default','Y',None, None, 'ProgId',1,'Text',None, 'Optional ProgId associated with this CLSID.',), diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 6ee9521c76b48f..b6b4cdd9ac15eb 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -8,8 +8,7 @@ # Licensed to PSF under a Contributor Agreement. # -__all__ = [ 'BaseManager', 'SyncManager', 'BaseProxy', 'Token', - 'SharedMemoryManager' ] +__all__ = [ 'BaseManager', 'SyncManager', 'BaseProxy', 'Token' ] # # Imports @@ -35,9 +34,11 @@ from . import get_context try: from . import shared_memory - HAS_SHMEM = True except ImportError: HAS_SHMEM = False +else: + HAS_SHMEM = True + __all__.append('SharedMemoryManager') # # Register some things for pickling @@ -967,7 +968,7 @@ def MakeProxyType(name, exposed, _cache={}): def AutoProxy(token, serializer, manager=None, authkey=None, - exposed=None, incref=True): + exposed=None, incref=True, manager_owned=False): ''' Return an auto-proxy for `token` ''' @@ -987,7 +988,7 @@ def AutoProxy(token, serializer, manager=None, authkey=None, ProxyType = MakeProxyType('AutoProxy[%s]' % token.typeid, exposed) proxy = ProxyType(token, serializer, manager=manager, authkey=authkey, - incref=incref) + incref=incref, manager_owned=manager_owned) proxy._isauto = True return proxy diff --git a/Lib/numbers.py b/Lib/numbers.py index ed815ef41ebe12..5b98e642083b36 100644 --- a/Lib/numbers.py +++ b/Lib/numbers.py @@ -33,7 +33,7 @@ class Complex(Number): """Complex defines the operations that work on the builtin complex type. In short, those are: a conversion to complex, .real, .imag, +, -, - *, /, abs(), .conjugate, ==, and !=. + *, /, **, abs(), .conjugate, ==, and !=. If it is given heterogeneous arguments, and doesn't have special knowledge about them, it should fall back to the builtin complex @@ -292,7 +292,11 @@ def __float__(self): class Integral(Rational): - """Integral adds a conversion to int and the bit-string operations.""" + """Integral adds methods that work on integral numbers. + + In short, these are conversion to int, pow with modulus, and the + bit-string operations. + """ __slots__ = () diff --git a/Lib/operator.py b/Lib/operator.py index fb58851fa6ef67..241fdbb679e7c1 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -155,10 +155,10 @@ def contains(a, b): return b in a def countOf(a, b): - "Return the number of times b occurs in a." + "Return the number of items in a which are, or which equal, b." count = 0 for i in a: - if i == b: + if i is b or i == b: count += 1 return count @@ -173,7 +173,7 @@ def getitem(a, b): def indexOf(a, b): "Return the first index of b in a." for i, j in enumerate(a): - if j == b: + if j is b or j == b: return i else: raise ValueError('sequence.index(x): x not in sequence') diff --git a/Lib/pathlib.py b/Lib/pathlib.py index cf40370c049a31..621fba0e75c0f7 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -124,16 +124,25 @@ class _WindowsFlavour(_Flavour): ext_namespace_prefix = '\\\\?\\' reserved_names = ( - {'CON', 'PRN', 'AUX', 'NUL'} | - {'COM%d' % i for i in range(1, 10)} | - {'LPT%d' % i for i in range(1, 10)} + {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | + {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | + {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} ) # Interesting findings about extended paths: - # - '\\?\c:\a', '//?/c:\a' and '//?/c:/a' are all supported - # but '\\?\c:/a' is not - # - extended paths are always absolute; "relative" extended paths will - # fail. + # * '\\?\c:\a' is an extended path, which bypasses normal Windows API + # path processing. Thus relative paths are not resolved and slash is not + # translated to backslash. It has the native NT path limit of 32767 + # characters, but a bit less after resolving device symbolic links, + # such as '\??\C:' => '\Device\HarddiskVolume2'. + # * '\\?\c:/a' looks for a device named 'C:/a' because slash is a + # regular name character in the object namespace. + # * '\\?\c:\foo/bar' is invalid because '/' is illegal in NT filesystems. + # The only path separator at the filesystem level is backslash. + # * '//?/c:\a' and '//?/c:/a' are effectively equivalent to '\\.\c:\a' and + # thus limited to MAX_PATH. + # * Prior to Windows 8, ANSI API bytes paths are limited to MAX_PATH, + # even with the '\\?\' prefix. def splitroot(self, part, sep=sep): first = part[0:1] @@ -195,15 +204,16 @@ def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix): def is_reserved(self, parts): # NOTE: the rules for reserved names seem somewhat complicated - # (e.g. r"..\NUL" is reserved but not r"foo\NUL"). - # We err on the side of caution and return True for paths which are - # not considered reserved by Windows. + # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not + # exist). We err on the side of caution and return True for paths + # which are not considered reserved by Windows. if not parts: return False if parts[0].startswith('\\\\'): # UNC paths are never reserved return False - return parts[-1].partition('.')[0].upper() in self.reserved_names + name = parts[-1].partition('.')[0].partition(':')[0].rstrip(' ') + return name.upper() in self.reserved_names def make_uri(self, path): # Under Windows, file URIs use the UTF-8 encoding. @@ -1265,7 +1275,7 @@ def link_to(self, target): warnings.warn("pathlib.Path.link_to() is deprecated and is scheduled " "for removal in Python 3.12. " "Use pathlib.Path.hardlink_to() instead.", - DeprecationWarning) + DeprecationWarning, stacklevel=2) self._accessor.link(self, target) # Convenience functions for querying the stat results @@ -1295,7 +1305,7 @@ def is_dir(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path @@ -1312,7 +1322,7 @@ def is_file(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path @@ -1363,7 +1373,7 @@ def is_block_device(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path @@ -1379,7 +1389,7 @@ def is_char_device(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path @@ -1395,7 +1405,7 @@ def is_fifo(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path @@ -1411,7 +1421,7 @@ def is_socket(self): if not _ignore_error(e): raise # Path doesn't exist or is a broken symlink - # (see https://bitbucket.org/pitrou/pathlib/issue/12/) + # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) return False except ValueError: # Non-encodable path diff --git a/Lib/pdb.py b/Lib/pdb.py index 98dc975eafafdc..943211158ac41e 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -384,8 +384,7 @@ def default(self, line): sys.stdin = save_stdin sys.displayhook = save_displayhook except: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() def precmd(self, line): """Handle alias expansion and ';;' separator.""" @@ -752,7 +751,8 @@ def checkline(self, filename, lineno): """ # this method should be callable before starting debugging, so default # to "no globals" if there is no current frame - globs = self.curframe.f_globals if hasattr(self, 'curframe') else None + frame = getattr(self, 'curframe', None) + globs = frame.f_globals if frame else None line = linecache.getline(filename, lineno, globs) if not line: self.message('End of file') @@ -893,7 +893,7 @@ def do_clear(self, arg): except ValueError: err = "Invalid line number (%s)" % arg else: - bplist = self.get_breaks(filename, lineno) + bplist = self.get_breaks(filename, lineno)[:] err = self.clear_break(filename, lineno) if err: self.error(err) @@ -1026,7 +1026,11 @@ def do_run(self, arg): if arg: import shlex argv0 = sys.argv[0:1] - sys.argv = shlex.split(arg) + try: + sys.argv = shlex.split(arg) + except ValueError as e: + self.error('Cannot run %s: %s' % (arg, e)) + return sys.argv[:0] = argv0 # this is caught in the main debugger loop raise Restart @@ -1103,8 +1107,7 @@ def do_debug(self, arg): try: sys.call_tracing(p.run, (arg, globals, locals)) except Exception: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() self.message("LEAVING RECURSIVE DEBUGGER") sys.settrace(self.trace_dispatch) self.lastcmd = p.lastcmd @@ -1162,8 +1165,7 @@ def _getval(self, arg): try: return eval(arg, self.curframe.f_globals, self.curframe_locals) except: - exc_info = sys.exc_info()[:2] - self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + self._error_exc() raise def _getval_except(self, arg, frame=None): @@ -1177,23 +1179,31 @@ def _getval_except(self, arg, frame=None): err = traceback.format_exception_only(*exc_info)[-1].strip() return _rstr('** raised %s **' % err) + def _error_exc(self): + exc_info = sys.exc_info()[:2] + self.error(traceback.format_exception_only(*exc_info)[-1].strip()) + + def _msg_val_func(self, arg, func): + try: + val = self._getval(arg) + except: + return # _getval() has displayed the error + try: + self.message(func(val)) + except: + self._error_exc() + def do_p(self, arg): """p expression Print the value of the expression. """ - try: - self.message(repr(self._getval(arg))) - except: - pass + self._msg_val_func(arg, repr) def do_pp(self, arg): """pp expression Pretty-print the value of the expression. """ - try: - self.message(pprint.pformat(self._getval(arg))) - except: - pass + self._msg_val_func(arg, pprint.pformat) complete_print = _complete_expression complete_p = _complete_expression @@ -1684,6 +1694,14 @@ def main(): print('Error:', mainpyfile, 'does not exist') sys.exit(1) + if run_as_module: + import runpy + try: + runpy._get_module_details(mainpyfile) + except Exception: + traceback.print_exc() + sys.exit(1) + sys.argv[:] = args # Hide "pdb.py" and pdb options from argument list if not run_as_module: diff --git a/Lib/pickle.py b/Lib/pickle.py index 5ab312f2acaee6..e7f30f226101f5 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -1173,7 +1173,7 @@ def __init__(self, file, *, fix_imports=True, used in Python 3. The *encoding* and *errors* tell pickle how to decode 8-bit string instances pickled by Python 2; these default to 'ASCII' and 'strict', respectively. *encoding* can be - 'bytes' to read theses 8-bit string instances as bytes objects. + 'bytes' to read these 8-bit string instances as bytes objects. """ self._buffers = iter(buffers) if buffers is not None else None self._file_readline = file.readline diff --git a/Lib/pipes.py b/Lib/pipes.py index f1a16f63de60a0..8cc74b0f1f781b 100644 --- a/Lib/pipes.py +++ b/Lib/pipes.py @@ -109,7 +109,7 @@ def debug(self, flag): def append(self, cmd, kind): """t.append(cmd, kind) adds a new step at the end.""" - if type(cmd) is not type(''): + if not isinstance(cmd, str): raise TypeError('Template.append: cmd must be a string') if kind not in stepkinds: raise ValueError('Template.append: bad kind %r' % (kind,)) @@ -125,7 +125,7 @@ def append(self, cmd, kind): def prepend(self, cmd, kind): """t.prepend(cmd, kind) adds a new step at the front.""" - if type(cmd) is not type(''): + if not isinstance(cmd, str): raise TypeError('Template.prepend: cmd must be a string') if kind not in stepkinds: raise ValueError('Template.prepend: bad kind %r' % (kind,)) diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index 2c3429856be46d..8e010c79c12668 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -671,7 +671,7 @@ def resolve_name(name): ValueError - if `name` isn't in a recognised format ImportError - if an import failed when it shouldn't have AttributeError - if a failure occurred when traversing the object hierarchy - within the imported package to get to the desired object) + within the imported package to get to the desired object. """ global _NAME_PATTERN if _NAME_PATTERN is None: diff --git a/Lib/platform.py b/Lib/platform.py index d298a42edc8483..e32f9c11cdbf16 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -280,6 +280,7 @@ def _syscmd_ver(system='', release='', version='', for cmd in ('ver', 'command /c ver', 'cmd /c ver'): try: info = subprocess.check_output(cmd, + stdin=subprocess.DEVNULL, stderr=subprocess.DEVNULL, text=True, shell=True) @@ -1261,7 +1262,7 @@ def platform(aliased=0, terse=0): def _parse_os_release(lines): # These fields are mandatory fields with well-known defaults - # in pratice all Linux distributions override NAME, ID, and PRETTY_NAME. + # in practice all Linux distributions override NAME, ID, and PRETTY_NAME. info = { "NAME": "Linux", "ID": "linux", diff --git a/Lib/plistlib.py b/Lib/plistlib.py index 5772efdfe6710a..2eeebe4c9a4244 100644 --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -61,7 +61,8 @@ from xml.parsers.expat import ParserCreate -PlistFormat = enum.global_enum(enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__)) +PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__) +globals().update(PlistFormat.__members__) class UID: diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 259baa64b193b8..195374613a779f 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -352,6 +352,7 @@ def normpath(path): initial_slashes = path.startswith(sep) # POSIX allows one or two initial slashes, but treats three or more # as single slash. + # (see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13) if (initial_slashes and path.startswith(sep*2) and not path.startswith(sep*3)): initial_slashes = 2 diff --git a/Lib/pprint.py b/Lib/pprint.py index 13819f3fef212a..d91421f0a6bf60 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -50,7 +50,8 @@ def pprint(object, stream=None, indent=1, width=80, depth=None, *, """Pretty-print a Python object to a stream [default is sys.stdout].""" printer = PrettyPrinter( stream=stream, indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, underscore_numbers=False) + compact=compact, sort_dicts=sort_dicts, + underscore_numbers=underscore_numbers) printer.pprint(object) def pformat(object, indent=1, width=80, depth=None, *, diff --git a/Lib/pstats.py b/Lib/pstats.py index e77459d38b33ec..0f93ae02c95074 100644 --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -26,15 +26,14 @@ import marshal import re -from enum import StrEnum, _simple_enum +from enum import Enum from functools import cmp_to_key from dataclasses import dataclass from typing import Dict __all__ = ["Stats", "SortKey", "FunctionProfile", "StatsProfile"] -@_simple_enum(StrEnum) -class SortKey: +class SortKey(str, Enum): CALLS = 'calls', 'ncalls' CUMULATIVE = 'cumulative', 'cumtime' FILENAME = 'filename', 'module' diff --git a/Lib/pty.py b/Lib/pty.py index a32432041fa1db..8d8ce40df541c1 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -1,7 +1,7 @@ """Pseudo terminal utilities.""" # Bugs: No signal handling. Doesn't set slave termios and window size. -# Only tested on Linux. +# Only tested on Linux, FreeBSD, and macOS. # See: W. Richard Stevens. 1992. Advanced Programming in the # UNIX Environment. Chapter 19. # Author: Steen Lumholt -- with additions by Guido. @@ -11,7 +11,11 @@ import sys import tty -__all__ = ["openpty","fork","spawn"] +# names imported directly for test mocking purposes +from os import close, waitpid +from tty import setraw, tcgetattr, tcsetattr + +__all__ = ["openpty", "fork", "spawn"] STDIN_FILENO = 0 STDOUT_FILENO = 1 @@ -105,8 +109,8 @@ def fork(): os.dup2(slave_fd, STDIN_FILENO) os.dup2(slave_fd, STDOUT_FILENO) os.dup2(slave_fd, STDERR_FILENO) - if (slave_fd > STDERR_FILENO): - os.close (slave_fd) + if slave_fd > STDERR_FILENO: + os.close(slave_fd) # Explicitly open the tty to make it become a controlling tty. tmp_fd = os.open(os.ttyname(STDOUT_FILENO), os.O_RDWR) @@ -133,14 +137,22 @@ def _copy(master_fd, master_read=_read, stdin_read=_read): pty master -> standard output (master_read) standard input -> pty master (stdin_read)""" fds = [master_fd, STDIN_FILENO] - while True: - rfds, wfds, xfds = select(fds, [], []) + while fds: + rfds, _wfds, _xfds = select(fds, [], []) + if master_fd in rfds: - data = master_read(master_fd) + # Some OSes signal EOF by returning an empty byte string, + # some throw OSErrors. + try: + data = master_read(master_fd) + except OSError: + data = b"" if not data: # Reached EOF. - fds.remove(master_fd) + return # Assume the child process has exited and is + # unreachable, so we clean up. else: os.write(STDOUT_FILENO, data) + if STDIN_FILENO in rfds: data = stdin_read(STDIN_FILENO) if not data: @@ -153,20 +165,23 @@ def spawn(argv, master_read=_read, stdin_read=_read): if type(argv) == type(''): argv = (argv,) sys.audit('pty.spawn', argv) + pid, master_fd = fork() if pid == CHILD: os.execlp(argv[0], *argv) + try: - mode = tty.tcgetattr(STDIN_FILENO) - tty.setraw(STDIN_FILENO) - restore = 1 + mode = tcgetattr(STDIN_FILENO) + setraw(STDIN_FILENO) + restore = True except tty.error: # This is the same as termios.error - restore = 0 + restore = False + try: _copy(master_fd, master_read, stdin_read) - except OSError: + finally: if restore: - tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) + tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) - os.close(master_fd) - return os.waitpid(pid, 0)[1] + close(master_fd) + return waitpid(pid, 0)[1] diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 0f9b59025cee38..388614e51b1847 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -190,7 +190,7 @@ def main(): ) args = parser.parse_args() if args.filenames == ['-']: - filenames = sys.stdin.readlines() + filenames = [filename.rstrip('\n') for filename in sys.stdin.readlines()] else: filenames = args.filenames for filename in filenames: diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 8eecd66a2c2fbf..4a8c10a379ed82 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -23,7 +23,7 @@ class or function within a module or module in a package. If the local machine. Port number 0 can be used to get an arbitrary unused port. Run "pydoc -b" to start an HTTP server on an arbitrary unused port and -open a Web browser to interactively browse documentation. Combine with +open a web browser to interactively browse documentation. Combine with the -n and -p options to control the hostname and port used. Run "pydoc -w " to write out the HTML documentation for a module @@ -694,7 +694,7 @@ def markup(self, text, escape=None, funcs={}, classes={}, methods={}): url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) results.append('%s' % (url, escape(all))) elif pep: - url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep) + url = 'https://www.python.org/dev/peps/pep-%04d/' % int(pep) results.append('%s' % (url, escape(all))) elif selfdot: # Create a link for methods like 'self.method(...)' @@ -1618,13 +1618,14 @@ def pipepager(text, cmd): def tempfilepager(text, cmd): """Page through text by invoking a program on a temporary file.""" import tempfile - filename = tempfile.mktemp() - with open(filename, 'w', errors='backslashreplace') as file: - file.write(text) - try: + with tempfile.TemporaryDirectory() as tempdir: + filename = os.path.join(tempdir, 'pydoc.out') + with open(filename, 'w', errors='backslashreplace', + encoding=os.device_encoding(0) if + sys.platform == 'win32' else None + ) as file: + file.write(text) os.system(cmd + ' "' + filename + '"') - finally: - os.unlink(filename) def _escape_stdout(text): # Escape non-encodable characters to avoid encoding errors later @@ -2065,7 +2066,7 @@ def intro(self): Welcome to Python {0}'s help utility! If this is your first time using Python, you should definitely check out -the tutorial on the Internet at https://docs.python.org/{0}/tutorial/. +the tutorial on the internet at https://docs.python.org/{0}/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and @@ -2279,13 +2280,13 @@ def onerror(modname): warnings.filterwarnings('ignore') # ignore problems during import ModuleScanner().run(callback, key, onerror=onerror) -# --------------------------------------- enhanced Web browser interface +# --------------------------------------- enhanced web browser interface def _start_server(urlhandler, hostname, port): """Start an HTTP server thread on a specific port. Start an HTML/text server thread, so HTML or text documents can be - browsed dynamically and interactively with a Web browser. Example use: + browsed dynamically and interactively with a web browser. Example use: >>> import time >>> import pydoc @@ -2671,7 +2672,7 @@ def get_html_page(url): def browse(port=0, *, open_browser=True, hostname='localhost'): - """Start the enhanced pydoc Web server and open a Web browser. + """Start the enhanced pydoc web server and open a web browser. Use port '0' to start the server on an arbitrary port. Set open_browser to False to suppress opening a browser. @@ -2823,7 +2824,7 @@ class BadUsage(Exception): pass number 0 can be used to get an arbitrary unused port. {cmd} -b - Start an HTTP server on an arbitrary unused port and open a Web browser + Start an HTTP server on an arbitrary unused port and open a web browser to interactively browse documentation. This option can be used in combination with -n and/or -p. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 83e1a975ec78b2..00c98ad51072cf 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon Apr 5 17:39:41 2021 +# Autogenerated by Sphinx on Mon Dec 6 17:57:38 2021 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -551,13 +551,65 @@ 'exception.\n' ' That new exception causes the old one to be lost.\n' '\n' - '[2] A string literal appearing as the first statement in the ' + '[2] In pattern matching, a sequence is defined as one of the\n' + ' following:\n' + '\n' + ' * a class that inherits from "collections.abc.Sequence"\n' + '\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Sequence"\n' + '\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_SEQUENCE"\n' + ' bit set\n' + '\n' + ' * a class that inherits from any of the above\n' + '\n' + ' The following standard library classes are sequences:\n' + '\n' + ' * "array.array"\n' + '\n' + ' * "collections.deque"\n' + '\n' + ' * "list"\n' + '\n' + ' * "memoryview"\n' + '\n' + ' * "range"\n' + '\n' + ' * "tuple"\n' + '\n' + ' Note:\n' + '\n' + ' Subject values of type "str", "bytes", and "bytearray" do ' + 'not\n' + ' match sequence patterns.\n' + '\n' + '[3] In pattern matching, a mapping is defined as one of the ' + 'following:\n' + '\n' + ' * a class that inherits from "collections.abc.Mapping"\n' + '\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Mapping"\n' + '\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_MAPPING"\n' + ' bit set\n' + '\n' + ' * a class that inherits from any of the above\n' + '\n' + ' The standard library classes "dict" and ' + '"types.MappingProxyType"\n' + ' are mappings.\n' + '\n' + '[4] A string literal appearing as the first statement in the ' 'function\n' ' body is transformed into the function’s "__doc__" attribute ' 'and\n' ' therefore the function’s *docstring*.\n' '\n' - '[3] A string literal appearing as the first statement in the class\n' + '[5] A string literal appearing as the first statement in the class\n' ' body is transformed into the namespace’s "__doc__" item and\n' ' therefore the class’s *docstring*.\n', 'atom-identifiers': 'Identifiers (Names)\n' @@ -884,32 +936,6 @@ '*instance* of the\n' ' owner class.\n' '\n' - 'object.__set_name__(self, owner, name)\n' - '\n' - ' Called at the time the owning class *owner* is ' - 'created. The\n' - ' descriptor has been assigned to *name*.\n' - '\n' - ' Note:\n' - '\n' - ' "__set_name__()" is only called implicitly as part ' - 'of the "type"\n' - ' constructor, so it will need to be called ' - 'explicitly with the\n' - ' appropriate parameters when a descriptor is added ' - 'to a class\n' - ' after initial creation:\n' - '\n' - ' class A:\n' - ' pass\n' - ' descr = custom_descriptor()\n' - ' A.attr = descr\n' - " descr.__set_name__(A, 'attr')\n" - '\n' - ' See Creating the class object for more details.\n' - '\n' - ' New in version 3.6.\n' - '\n' 'The attribute "__objclass__" is interpreted by the ' '"inspect" module as\n' 'specifying the class where this object was defined ' @@ -988,9 +1014,9 @@ '\n' 'For instance bindings, the precedence of descriptor ' 'invocation depends\n' - 'on the which descriptor methods are defined. A ' - 'descriptor can define\n' - 'any combination of "__get__()", "__set__()" and ' + 'on which descriptor methods are defined. A descriptor ' + 'can define any\n' + 'combination of "__get__()", "__set__()" and ' '"__delete__()". If it\n' 'does not define "__get__()", then accessing the ' 'attribute will return\n' @@ -1261,6 +1287,10 @@ 'In the latter case, sequence repetition is performed; a negative\n' 'repetition factor yields an empty sequence.\n' '\n' + 'This operation can be customized using the special "__mul__()" ' + 'and\n' + '"__rmul__()" methods.\n' + '\n' 'The "@" (at) operator is intended to be used for matrix\n' 'multiplication. No builtin Python types implement this operator.\n' '\n' @@ -1276,6 +1306,10 @@ 'result. Division by zero raises the "ZeroDivisionError" ' 'exception.\n' '\n' + 'This operation can be customized using the special "__truediv__()" ' + 'and\n' + '"__floordiv__()" methods.\n' + '\n' 'The "%" (modulo) operator yields the remainder from the division ' 'of\n' 'the first argument by the second. The numeric arguments are ' @@ -1307,6 +1341,10 @@ 'string formatting is described in the Python Library Reference,\n' 'section printf-style String Formatting.\n' '\n' + 'The *modulo* operation can be customized using the special ' + '"__mod__()"\n' + 'method.\n' + '\n' 'The floor division operator, the modulo operator, and the ' '"divmod()"\n' 'function are not defined for complex numbers. Instead, convert to ' @@ -1321,9 +1359,16 @@ 'and then added together. In the latter case, the sequences are\n' 'concatenated.\n' '\n' + 'This operation can be customized using the special "__add__()" ' + 'and\n' + '"__radd__()" methods.\n' + '\n' 'The "-" (subtraction) operator yields the difference of its ' 'arguments.\n' - 'The numeric arguments are first converted to a common type.\n', + 'The numeric arguments are first converted to a common type.\n' + '\n' + 'This operation can be customized using the special "__sub__()" ' + 'method.\n', 'bitwise': 'Binary bitwise operations\n' '*************************\n' '\n' @@ -1336,14 +1381,18 @@ '\n' 'The "&" operator yields the bitwise AND of its arguments, which ' 'must\n' - 'be integers.\n' + 'be integers or one of them must be a custom object overriding\n' + '"__and__()" or "__rand__()" special methods.\n' '\n' 'The "^" operator yields the bitwise XOR (exclusive OR) of its\n' - 'arguments, which must be integers.\n' + 'arguments, which must be integers or one of them must be a ' + 'custom\n' + 'object overriding "__xor__()" or "__rxor__()" special methods.\n' '\n' 'The "|" operator yields the bitwise (inclusive) OR of its ' 'arguments,\n' - 'which must be integers.\n', + 'which must be integers or one of them must be a custom object\n' + 'overriding "__or__()" or "__ror__()" special methods.\n', 'bltin-code-objects': 'Code Objects\n' '************\n' '\n' @@ -1360,6 +1409,10 @@ 'through their "__code__" attribute. See also the ' '"code" module.\n' '\n' + 'Accessing "__code__" raises an auditing event ' + '"object.__getattr__"\n' + 'with arguments "obj" and ""__code__"".\n' + '\n' 'A code object can be executed or evaluated by passing ' 'it (instead of a\n' 'source string) to the "exec()" or "eval()" built-in ' @@ -1704,7 +1757,7 @@ 'original global namespace. (Usually, the suite contains mostly\n' 'function definitions.) When the class’s suite finishes execution, ' 'its\n' - 'execution frame is discarded but its local namespace is saved. [3] ' + 'execution frame is discarded but its local namespace is saved. [5] ' 'A\n' 'class object is then created using the inheritance list for the ' 'base\n' @@ -1785,7 +1838,11 @@ ' comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n' ' | "is" ["not"] | ["not"] "in"\n' '\n' - 'Comparisons yield boolean values: "True" or "False".\n' + 'Comparisons yield boolean values: "True" or "False". Custom ' + '*rich\n' + 'comparison methods* may return non-boolean values. In this ' + 'case Python\n' + 'will call "bool()" on such value in boolean contexts.\n' '\n' 'Comparisons can be chained arbitrarily, e.g., "x < y <= z" ' 'is\n' @@ -2694,7 +2751,7 @@ ' subject_expr ::= star_named_expression "," ' 'star_named_expressions?\n' ' | named_expression\n' - " case_block ::= 'case' patterns [guard] ':' block\n" + ' case_block ::= \'case\' patterns [guard] ":" block\n' '\n' 'Note:\n' '\n' @@ -2764,7 +2821,7 @@ 'have\n' ' happened.\n' '\n' - ' * If the guard evaluates as truthy or missing, the "block" ' + ' * If the guard evaluates as true or is missing, the "block" ' 'inside\n' ' "case_block" is executed.\n' '\n' @@ -2825,12 +2882,12 @@ '\n' '2. If the pattern succeeded, evaluate the "guard".\n' '\n' - ' * If the "guard" condition evaluates to “truthy”, the case ' - 'block is\n' + ' * If the "guard" condition evaluates as true, the case block ' + 'is\n' ' selected.\n' '\n' - ' * If the "guard" condition evaluates to “falsy”, the case ' - 'block is\n' + ' * If the "guard" condition evaluates as false, the case block ' + 'is\n' ' not selected.\n' '\n' ' * If the "guard" raises an exception during evaluation, the\n' @@ -3001,7 +3058,7 @@ '\n' 'A single underscore "_" is not a capture pattern (this is what ' '"!\'_\'"\n' - 'expresses). And is instead treated as a "wildcard_pattern".\n' + 'expresses). It is instead treated as a "wildcard_pattern".\n' '\n' 'In a given pattern, a given name can only be bound once. E.g. ' '"case\n' @@ -3029,7 +3086,10 @@ '\n' " wildcard_pattern ::= '_'\n" '\n' - '"_" is a soft keyword.\n' + '"_" is a soft keyword within any pattern, but only within ' + 'patterns.\n' + 'It is an identifier, as usual, even within "match" subject\n' + 'expressions, "guard"s, and "case" blocks.\n' '\n' 'In simple terms, "_" will always succeed.\n' '\n' @@ -3073,7 +3133,7 @@ 'additional\n' 'syntax. Syntax:\n' '\n' - " group_pattern ::= '(' pattern ')'\n" + ' group_pattern ::= "(" pattern ")"\n' '\n' 'In simple terms "(P)" has the same effect as "P".\n' '\n' @@ -3120,8 +3180,9 @@ 'pattern\n' 'against a subject value:\n' '\n' - '1. If the subject value is not an instance of a\n' - ' "collections.abc.Sequence" the sequence pattern fails.\n' + '1. If the subject value is not a sequence [2], the sequence ' + 'pattern\n' + ' fails.\n' '\n' '2. If the subject value is an instance of "str", "bytes" or\n' ' "bytearray" the sequence pattern fails.\n' @@ -3176,7 +3237,7 @@ 'the\n' 'following happens:\n' '\n' - '* "isinstance(, collections.abc.Sequence)"\n' + '* check "" is a sequence\n' '\n' '* "len(subject) == "\n' '\n' @@ -3210,18 +3271,19 @@ 'double star pattern must be the last subpattern in the mapping\n' 'pattern.\n' '\n' - 'Duplicate key values in mapping patterns are disallowed. (If all ' - 'key\n' - 'patterns are literal patterns this is considered a syntax ' - 'error;\n' - 'otherwise this is a runtime error and will raise "ValueError".)\n' + 'Duplicate keys in mapping patterns are disallowed. Duplicate ' + 'literal\n' + 'keys will raise a "SyntaxError". Two keys that otherwise have ' + 'the same\n' + 'value will raise a "ValueError" at runtime.\n' '\n' 'The following is the logical flow for matching a mapping ' 'pattern\n' 'against a subject value:\n' '\n' - '1. If the subject value is not an instance of\n' - ' "collections.abc.Mapping", the mapping pattern fails.\n' + '1. If the subject value is not a mapping [3],the mapping ' + 'pattern\n' + ' fails.\n' '\n' '2. If every key given in the mapping pattern is present in the ' 'subject\n' @@ -3231,7 +3293,10 @@ '\n' '3. If duplicate keys are detected in the mapping pattern, the ' 'pattern\n' - ' is considered invalid and "ValueError" is raised.\n' + ' is considered invalid. A "SyntaxError" is raised for ' + 'duplicate\n' + ' literal values; or a "ValueError" for named keys of the same ' + 'value.\n' '\n' 'Note:\n' '\n' @@ -3247,7 +3312,7 @@ 'the\n' 'following happens:\n' '\n' - '* "isinstance(, collections.abc.Mapping)"\n' + '* check "" is a mapping\n' '\n' '* "KEY1 in "\n' '\n' @@ -3274,9 +3339,9 @@ '\n' 'The same keyword should not be repeated in class patterns.\n' '\n' - 'The following is the logical flow for matching a mapping ' - 'pattern\n' - 'against a subject value:\n' + 'The following is the logical flow for matching a class pattern ' + 'against\n' + 'a subject value:\n' '\n' '1. If "name_or_attr" is not an instance of the builtin "type" , ' 'raise\n' @@ -3293,7 +3358,9 @@ ' For a number of built-in types (specified below), a single\n' ' positional subpattern is accepted which will match the ' 'entire\n' - ' subject; for these types no keyword patterns are accepted.\n' + ' subject; for these types keyword patterns also work as for ' + 'other\n' + ' types.\n' '\n' ' If only keyword patterns are present, they are processed as\n' ' follows, one by one:\n' @@ -3324,15 +3391,14 @@ 'class\n' ' "name_or_attr" before matching:\n' '\n' - ' I. The equivalent of "getattr(cls, "__match_args__", ()))" ' - 'is\n' + ' I. The equivalent of "getattr(cls, "__match_args__", ())" is\n' ' called.\n' '\n' ' * If this raises an exception, the exception bubbles up.\n' '\n' - ' * If the returned value is not a list or tuple, the ' - 'conversion\n' - ' fails and "TypeError" is raised.\n' + ' * If the returned value is not a tuple, the conversion ' + 'fails and\n' + ' "TypeError" is raised.\n' '\n' ' * If there are more positional patterns than\n' ' "len(cls.__match_args__)", "TypeError" is raised.\n' @@ -3426,7 +3492,6 @@ ' decorators ::= decorator+\n' ' decorator ::= "@" assignment_expression ' 'NEWLINE\n' - ' dotted_name ::= identifier ("." identifier)*\n' ' parameter_list ::= defparameter ("," ' 'defparameter)* "," "/" ["," [parameter_list_no_posonly]]\n' ' | parameter_list_no_posonly\n' @@ -3451,7 +3516,7 @@ '\n' 'The function definition does not execute the function body; this ' 'gets\n' - 'executed only when the function is called. [2]\n' + 'executed only when the function is called. [4]\n' '\n' 'A function definition may be wrapped by one or more *decorator*\n' 'expressions. Decorator expressions are evaluated when the ' @@ -3526,7 +3591,7 @@ 'Calls.\n' 'A function call always assigns values to all parameters ' 'mentioned in\n' - 'the parameter list, either from position arguments, from ' + 'the parameter list, either from positional arguments, from ' 'keyword\n' 'arguments, or from default values. If the form “"*identifier"” ' 'is\n' @@ -3538,8 +3603,14 @@ 'new\n' 'empty mapping of the same type. Parameters after “"*"” or\n' '“"*identifier"” are keyword-only parameters and may only be ' - 'passed\n' - 'used keyword arguments.\n' + 'passed by\n' + 'keyword arguments. Parameters before “"/"” are positional-only\n' + 'parameters and may only be passed by positional arguments.\n' + '\n' + 'Changed in version 3.8: The "/" function parameter syntax may be ' + 'used\n' + 'to indicate positional-only parameters. See **PEP 570** for ' + 'details.\n' '\n' 'Parameters may have an *annotation* of the form “": ' 'expression"”\n' @@ -3552,11 +3623,20 @@ 'parameter list. These annotations can be any valid Python ' 'expression.\n' 'The presence of annotations does not change the semantics of a\n' - 'function. The annotation values are available as string values ' - 'in a\n' + 'function. The annotation values are available as values of a\n' 'dictionary keyed by the parameters’ names in the ' '"__annotations__"\n' - 'attribute of the function object.\n' + 'attribute of the function object. If the "annotations" import ' + 'from\n' + '"__future__" is used, annotations are preserved as strings at ' + 'runtime\n' + 'which enables postponed evaluation. Otherwise, they are ' + 'evaluated\n' + 'when the function definition is executed. In this case ' + 'annotations\n' + 'may be evaluated in a different order than they appear in the ' + 'source\n' + 'code.\n' '\n' 'It is also possible to create anonymous functions (functions not ' 'bound\n' @@ -3641,7 +3721,7 @@ 'function definitions.) When the class’s suite finishes ' 'execution, its\n' 'execution frame is discarded but its local namespace is saved. ' - '[3] A\n' + '[5] A\n' 'class object is then created using the inheritance list for the ' 'base\n' 'classes and the saved local namespace for the attribute ' @@ -3845,13 +3925,65 @@ 'exception.\n' ' That new exception causes the old one to be lost.\n' '\n' - '[2] A string literal appearing as the first statement in the ' + '[2] In pattern matching, a sequence is defined as one of the\n' + ' following:\n' + '\n' + ' * a class that inherits from "collections.abc.Sequence"\n' + '\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Sequence"\n' + '\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_SEQUENCE"\n' + ' bit set\n' + '\n' + ' * a class that inherits from any of the above\n' + '\n' + ' The following standard library classes are sequences:\n' + '\n' + ' * "array.array"\n' + '\n' + ' * "collections.deque"\n' + '\n' + ' * "list"\n' + '\n' + ' * "memoryview"\n' + '\n' + ' * "range"\n' + '\n' + ' * "tuple"\n' + '\n' + ' Note:\n' + '\n' + ' Subject values of type "str", "bytes", and "bytearray" do ' + 'not\n' + ' match sequence patterns.\n' + '\n' + '[3] In pattern matching, a mapping is defined as one of the ' + 'following:\n' + '\n' + ' * a class that inherits from "collections.abc.Mapping"\n' + '\n' + ' * a Python class that has been registered as\n' + ' "collections.abc.Mapping"\n' + '\n' + ' * a builtin class that has its (CPython) ' + '"Py_TPFLAGS_MAPPING"\n' + ' bit set\n' + '\n' + ' * a class that inherits from any of the above\n' + '\n' + ' The standard library classes "dict" and ' + '"types.MappingProxyType"\n' + ' are mappings.\n' + '\n' + '[4] A string literal appearing as the first statement in the ' 'function\n' ' body is transformed into the function’s "__doc__" attribute ' 'and\n' ' therefore the function’s *docstring*.\n' '\n' - '[3] A string literal appearing as the first statement in the ' + '[5] A string literal appearing as the first statement in the ' 'class\n' ' body is transformed into the namespace’s "__doc__" item and\n' ' therefore the class’s *docstring*.\n', @@ -3989,13 +4121,13 @@ '\n' ' If "__new__()" is invoked during object construction and ' 'it returns\n' - ' an instance or subclass of *cls*, then the new ' - 'instance’s\n' - ' "__init__()" method will be invoked like ' - '"__init__(self[, ...])",\n' - ' where *self* is the new instance and the remaining ' - 'arguments are\n' - ' the same as were passed to the object constructor.\n' + ' an instance of *cls*, then the new instance’s ' + '"__init__()" method\n' + ' will be invoked like "__init__(self[, ...])", where ' + '*self* is the\n' + ' new instance and the remaining arguments are the same as ' + 'were\n' + ' passed to the object constructor.\n' '\n' ' If "__new__()" does not return an instance of *cls*, ' 'then the new\n' @@ -5356,20 +5488,32 @@ 'binding\n' 'operations.\n' '\n' - 'The following constructs bind names: formal parameters to ' - 'functions,\n' - '"import" statements, class and function definitions (these bind ' - 'the\n' - 'class or function name in the defining block), and targets that ' - 'are\n' - 'identifiers if occurring in an assignment, "for" loop header, ' - 'or after\n' - '"as" in a "with" statement or "except" clause. The "import" ' - 'statement\n' - 'of the form "from ... import *" binds all names defined in the\n' - 'imported module, except those beginning with an underscore. ' - 'This form\n' - 'may only be used at the module level.\n' + 'The following constructs bind names:\n' + '\n' + '* formal parameters to functions,\n' + '\n' + '* class definitions,\n' + '\n' + '* function definitions,\n' + '\n' + '* assignment expressions,\n' + '\n' + '* targets that are identifiers if occurring in an assignment:\n' + '\n' + ' * "for" loop header,\n' + '\n' + ' * after "as" in a "with" statement, "except" clause or in the ' + 'as-\n' + ' pattern in structural pattern matching,\n' + '\n' + ' * in a capture pattern in structural pattern matching\n' + '\n' + '* "import" statements.\n' + '\n' + 'The "import" statement of the form "from ... import *" binds ' + 'all names\n' + 'defined in the imported module, except those beginning with an\n' + 'underscore. This form may only be used at the module level.\n' '\n' 'A target occurring in a "del" statement is also considered ' 'bound for\n' @@ -5442,9 +5586,9 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of ' - 'the name\n' - 'specified in the statement refer to the binding of that name in ' - 'the\n' + 'the names\n' + 'specified in the statement refer to the bindings of those names ' + 'in the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' 'searching the global namespace, i.e. the namespace of the ' @@ -5453,9 +5597,10 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is ' - 'searched. The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed ' + 'names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -6075,19 +6220,19 @@ 'complex\n' 'types. For integers, when binary, octal, or hexadecimal ' 'output is\n' - 'used, this option adds the prefix respective "\'0b\'", ' - '"\'0o\'", or "\'0x\'"\n' - 'to the output value. For float and complex the alternate ' - 'form causes\n' - 'the result of the conversion to always contain a ' - 'decimal-point\n' - 'character, even if no digits follow it. Normally, a ' - 'decimal-point\n' - 'character appears in the result of these conversions only ' - 'if a digit\n' - 'follows it. In addition, for "\'g\'" and "\'G\'" ' - 'conversions, trailing\n' - 'zeros are not removed from the result.\n' + 'used, this option adds the respective prefix "\'0b\'", ' + '"\'0o\'", "\'0x\'",\n' + 'or "\'0X\'" to the output value. For float and complex the ' + 'alternate\n' + 'form causes the result of the conversion to always contain ' + 'a decimal-\n' + 'point character, even if no digits follow it. Normally, a ' + 'decimal-\n' + 'point character appears in the result of these conversions ' + 'only if a\n' + 'digit follows it. In addition, for "\'g\'" and "\'G\'" ' + 'conversions,\n' + 'trailing zeros are not removed from the result.\n' '\n' 'The "\',\'" option signals the use of a comma for a ' 'thousands separator.\n' @@ -6204,8 +6349,12 @@ '+-----------+------------------------------------------------------------+\n' ' | "\'X\'" | Hex format. Outputs the number in base ' '16, using upper- |\n' - ' | | case letters for the digits above ' - '9. |\n' + ' | | case letters for the digits above 9. In ' + 'case "\'#\'" is |\n' + ' | | specified, the prefix "\'0x\'" will be ' + 'upper-cased to "\'0X\'" |\n' + ' | | as ' + 'well. |\n' ' ' '+-----------+------------------------------------------------------------+\n' ' | "\'n\'" | Number. This is the same as "\'d\'", ' @@ -6562,7 +6711,6 @@ ' decorators ::= decorator+\n' ' decorator ::= "@" assignment_expression ' 'NEWLINE\n' - ' dotted_name ::= identifier ("." identifier)*\n' ' parameter_list ::= defparameter ("," ' 'defparameter)* "," "/" ["," [parameter_list_no_posonly]]\n' ' | parameter_list_no_posonly\n' @@ -6587,7 +6735,7 @@ '\n' 'The function definition does not execute the function body; this ' 'gets\n' - 'executed only when the function is called. [2]\n' + 'executed only when the function is called. [4]\n' '\n' 'A function definition may be wrapped by one or more *decorator*\n' 'expressions. Decorator expressions are evaluated when the ' @@ -6662,7 +6810,7 @@ 'Calls.\n' 'A function call always assigns values to all parameters ' 'mentioned in\n' - 'the parameter list, either from position arguments, from ' + 'the parameter list, either from positional arguments, from ' 'keyword\n' 'arguments, or from default values. If the form “"*identifier"” ' 'is\n' @@ -6674,8 +6822,14 @@ 'new\n' 'empty mapping of the same type. Parameters after “"*"” or\n' '“"*identifier"” are keyword-only parameters and may only be ' - 'passed\n' - 'used keyword arguments.\n' + 'passed by\n' + 'keyword arguments. Parameters before “"/"” are positional-only\n' + 'parameters and may only be passed by positional arguments.\n' + '\n' + 'Changed in version 3.8: The "/" function parameter syntax may be ' + 'used\n' + 'to indicate positional-only parameters. See **PEP 570** for ' + 'details.\n' '\n' 'Parameters may have an *annotation* of the form “": ' 'expression"”\n' @@ -6688,11 +6842,20 @@ 'parameter list. These annotations can be any valid Python ' 'expression.\n' 'The presence of annotations does not change the semantics of a\n' - 'function. The annotation values are available as string values ' - 'in a\n' + 'function. The annotation values are available as values of a\n' 'dictionary keyed by the parameters’ names in the ' '"__annotations__"\n' - 'attribute of the function object.\n' + 'attribute of the function object. If the "annotations" import ' + 'from\n' + '"__future__" is used, annotations are preserved as strings at ' + 'runtime\n' + 'which enables postponed evaluation. Otherwise, they are ' + 'evaluated\n' + 'when the function definition is executed. In this case ' + 'annotations\n' + 'may be evaluated in a different order than they appear in the ' + 'source\n' + 'code.\n' '\n' 'It is also possible to create anonymous functions (functions not ' 'bound\n' @@ -6793,22 +6956,31 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' - 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result of ' + 'the\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used to ' + 'name\n' + ' “special” items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' ' The name "_" is often used in conjunction with\n' ' internationalization; refer to the documentation for the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as “dunder” names. ' @@ -6963,15 +7135,23 @@ 'trailing underscore characters:\n' '\n' '"_*"\n' - ' Not imported by "from module import *". The special ' - 'identifier "_"\n' - ' is used in the interactive interpreter to store the result ' + ' Not imported by "from module import *".\n' + '\n' + '"_"\n' + ' In a "case" pattern within a "match" statement, "_" is a ' + 'soft\n' + ' keyword that denotes a wildcard.\n' + '\n' + ' Separately, the interactive interpreter makes the result ' 'of the\n' - ' last evaluation; it is stored in the "builtins" module. ' - 'When not\n' - ' in interactive mode, "_" has no special meaning and is not ' - 'defined.\n' - ' See section The import statement.\n' + ' last evaluation available in the variable "_". (It is ' + 'stored in the\n' + ' "builtins" module, alongside built-in functions like ' + '"print".)\n' + '\n' + ' Elsewhere, "_" is a regular identifier. It is often used ' + 'to name\n' + ' “special” items, but it is not special to Python itself.\n' '\n' ' Note:\n' '\n' @@ -6979,7 +7159,8 @@ ' internationalization; refer to the documentation for ' 'the\n' ' "gettext" module for more information on this ' - 'convention.\n' + 'convention.It is\n' + ' also commonly used for unused variables.\n' '\n' '"__*__"\n' ' System-defined names, informally known as “dunder” names. ' @@ -7051,7 +7232,7 @@ ' | "from" relative_module "import" "(" ' 'identifier ["as" identifier]\n' ' ("," identifier ["as" identifier])* [","] ")"\n' - ' | "from" module "import" "*"\n' + ' | "from" relative_module "import" "*"\n' ' module ::= (identifier ".")* identifier\n' ' relative_module ::= "."* module | "."+\n' '\n' @@ -7395,10 +7576,7 @@ 'lambda': 'Lambdas\n' '*******\n' '\n' - ' lambda_expr ::= "lambda" [parameter_list] ":" ' - 'expression\n' - ' lambda_expr_nocond ::= "lambda" [parameter_list] ":" ' - 'expression_nocond\n' + ' lambda_expr ::= "lambda" [parameter_list] ":" expression\n' '\n' 'Lambda expressions (sometimes called lambda forms) are used to ' 'create\n' @@ -7443,20 +7621,32 @@ '*Names* refer to objects. Names are introduced by name binding\n' 'operations.\n' '\n' - 'The following constructs bind names: formal parameters to ' - 'functions,\n' - '"import" statements, class and function definitions (these bind ' - 'the\n' - 'class or function name in the defining block), and targets that ' - 'are\n' - 'identifiers if occurring in an assignment, "for" loop header, or ' - 'after\n' - '"as" in a "with" statement or "except" clause. The "import" ' - 'statement\n' - 'of the form "from ... import *" binds all names defined in the\n' - 'imported module, except those beginning with an underscore. This ' - 'form\n' - 'may only be used at the module level.\n' + 'The following constructs bind names:\n' + '\n' + '* formal parameters to functions,\n' + '\n' + '* class definitions,\n' + '\n' + '* function definitions,\n' + '\n' + '* assignment expressions,\n' + '\n' + '* targets that are identifiers if occurring in an assignment:\n' + '\n' + ' * "for" loop header,\n' + '\n' + ' * after "as" in a "with" statement, "except" clause or in the ' + 'as-\n' + ' pattern in structural pattern matching,\n' + '\n' + ' * in a capture pattern in structural pattern matching\n' + '\n' + '* "import" statements.\n' + '\n' + 'The "import" statement of the form "from ... import *" binds all ' + 'names\n' + 'defined in the imported module, except those beginning with an\n' + 'underscore. This form may only be used at the module level.\n' '\n' 'A target occurring in a "del" statement is also considered bound ' 'for\n' @@ -7526,8 +7716,8 @@ 'operations.\n' '\n' 'If the "global" statement occurs within a block, all uses of the ' - 'name\n' - 'specified in the statement refer to the binding of that name in ' + 'names\n' + 'specified in the statement refer to the bindings of those names in ' 'the\n' 'top-level namespace. Names are resolved in the top-level ' 'namespace by\n' @@ -7536,9 +7726,9 @@ 'namespace\n' 'of the module "builtins". The global namespace is searched ' 'first. If\n' - 'the name is not found there, the builtins namespace is searched. ' - 'The\n' - '"global" statement must precede all uses of the name.\n' + 'the names are not found there, the builtins namespace is ' + 'searched.\n' + 'The "global" statement must precede all uses of the listed names.\n' '\n' 'The "global" statement has the same scope as a name binding ' 'operation\n' @@ -7873,9 +8063,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n', + ' The built-in function "int()" falls back to ' + '"__trunc__()" if\n' + ' neither "__int__()" nor "__index__()" is defined.\n', 'objects': 'Objects, values and types\n' '*************************\n' '\n' @@ -8009,8 +8199,8 @@ '\n' 'The following table summarizes the operator precedence ' 'in Python, from\n' - 'lowest precedence (least binding) to highest precedence ' - '(most\n' + 'highest precedence (most binding) to lowest precedence ' + '(least\n' 'binding). Operators in the same box have the same ' 'precedence. Unless\n' 'the syntax is explicitly given, operators are binary. ' @@ -8029,71 +8219,71 @@ '| Operator | ' 'Description |\n' '|=================================================|=======================================|\n' - '| ":=" | ' - 'Assignment expression |\n' - '+-------------------------------------------------+---------------------------------------+\n' - '| "lambda" | ' - 'Lambda expression |\n' + '| "(expressions...)", "[expressions...]", "{key: | ' + 'Binding or parenthesized expression, |\n' + '| value...}", "{expressions...}" | list ' + 'display, dictionary display, set |\n' + '| | ' + 'display |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "if" – "else" | ' - 'Conditional expression |\n' + '| "x[index]", "x[index:index]", | ' + 'Subscription, slicing, call, |\n' + '| "x(arguments...)", "x.attribute" | ' + 'attribute reference |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "or" | ' - 'Boolean OR |\n' + '| "await" "x" | ' + 'Await expression |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "and" | ' - 'Boolean AND |\n' + '| "**" | ' + 'Exponentiation [5] |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "not" "x" | ' - 'Boolean NOT |\n' + '| "+x", "-x", "~x" | ' + 'Positive, negative, bitwise NOT |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "in", "not in", "is", "is not", "<", "<=", ">", | ' - 'Comparisons, including membership |\n' - '| ">=", "!=", "==" | ' - 'tests and identity tests |\n' + '| "*", "@", "/", "//", "%" | ' + 'Multiplication, matrix |\n' + '| | ' + 'multiplication, division, floor |\n' + '| | ' + 'division, remainder [6] |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "|" | ' - 'Bitwise OR |\n' + '| "+", "-" | ' + 'Addition and subtraction |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "^" | ' - 'Bitwise XOR |\n' + '| "<<", ">>" | ' + 'Shifts |\n' '+-------------------------------------------------+---------------------------------------+\n' '| "&" | ' 'Bitwise AND |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "<<", ">>" | ' - 'Shifts |\n' + '| "^" | ' + 'Bitwise XOR |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "+", "-" | ' - 'Addition and subtraction |\n' + '| "|" | ' + 'Bitwise OR |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "*", "@", "/", "//", "%" | ' - 'Multiplication, matrix |\n' - '| | ' - 'multiplication, division, floor |\n' - '| | ' - 'division, remainder [5] |\n' + '| "in", "not in", "is", "is not", "<", "<=", ">", | ' + 'Comparisons, including membership |\n' + '| ">=", "!=", "==" | ' + 'tests and identity tests |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "+x", "-x", "~x" | ' - 'Positive, negative, bitwise NOT |\n' + '| "not" "x" | ' + 'Boolean NOT |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "**" | ' - 'Exponentiation [6] |\n' + '| "and" | ' + 'Boolean AND |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "await" "x" | ' - 'Await expression |\n' + '| "or" | ' + 'Boolean OR |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "x[index]", "x[index:index]", | ' - 'Subscription, slicing, call, |\n' - '| "x(arguments...)", "x.attribute" | ' - 'attribute reference |\n' + '| "if" – "else" | ' + 'Conditional expression |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "(expressions...)", "[expressions...]", "{key: | ' - 'Binding or parenthesized expression, |\n' - '| value...}", "{expressions...}" | list ' - 'display, dictionary display, set |\n' - '| | ' - 'display |\n' + '| "lambda" | ' + 'Lambda expression |\n' + '+-------------------------------------------------+---------------------------------------+\n' + '| ":=" | ' + 'Assignment expression |\n' '+-------------------------------------------------+---------------------------------------+\n' '\n' '-[ Footnotes ]-\n' @@ -8174,14 +8364,14 @@ 'Check their\n' ' documentation for more info.\n' '\n' - '[5] The "%" operator is also used for string formatting; ' - 'the same\n' - ' precedence applies.\n' - '\n' - '[6] The power operator "**" binds less tightly than an ' + '[5] The power operator "**" binds less tightly than an ' 'arithmetic or\n' ' bitwise unary operator on its right, that is, ' - '"2**-1" is "0.5".\n', + '"2**-1" is "0.5".\n' + '\n' + '[6] The "%" operator is also used for string formatting; ' + 'the same\n' + ' precedence applies.\n', 'pass': 'The "pass" statement\n' '********************\n' '\n' @@ -8229,7 +8419,10 @@ '"ZeroDivisionError".\n' 'Raising a negative number to a fractional power results in a ' '"complex"\n' - 'number. (In earlier versions it raised a "ValueError".)\n', + 'number. (In earlier versions it raised a "ValueError".)\n' + '\n' + 'This operation can be customized using the special "__pow__()" ' + 'method.\n', 'raise': 'The "raise" statement\n' '*********************\n' '\n' @@ -8266,12 +8459,18 @@ '\n' 'The "from" clause is used for exception chaining: if given, the ' 'second\n' - '*expression* must be another exception class or instance, which ' - 'will\n' - 'then be attached to the raised exception as the "__cause__" ' - 'attribute\n' - '(which is writable). If the raised exception is not handled, both\n' - 'exceptions will be printed:\n' + '*expression* must be another exception class or instance. If the\n' + 'second expression is an exception instance, it will be attached to ' + 'the\n' + 'raised exception as the "__cause__" attribute (which is writable). ' + 'If\n' + 'the expression is an exception class, the class will be ' + 'instantiated\n' + 'and the resulting exception instance will be attached to the ' + 'raised\n' + 'exception as the "__cause__" attribute. If the raised exception is ' + 'not\n' + 'handled, both exceptions will be printed:\n' '\n' ' >>> try:\n' ' ... print(1 / 0)\n' @@ -8488,22 +8687,24 @@ 'object.__getitem__(self, key)\n' '\n' ' Called to implement evaluation of "self[key]". For ' - 'sequence types,\n' - ' the accepted keys should be integers and slice ' - 'objects. Note that\n' - ' the special interpretation of negative indexes (if the ' - 'class wishes\n' - ' to emulate a sequence type) is up to the ' - '"__getitem__()" method. If\n' - ' *key* is of an inappropriate type, "TypeError" may be ' - 'raised; if of\n' - ' a value outside the set of indexes for the sequence ' - '(after any\n' - ' special interpretation of negative values), ' - '"IndexError" should be\n' - ' raised. For mapping types, if *key* is missing (not in ' + '*sequence*\n' + ' types, the accepted keys should be integers and slice ' + 'objects.\n' + ' Note that the special interpretation of negative ' + 'indexes (if the\n' + ' class wishes to emulate a *sequence* type) is up to ' 'the\n' - ' container), "KeyError" should be raised.\n' + ' "__getitem__()" method. If *key* is of an inappropriate ' + 'type,\n' + ' "TypeError" may be raised; if of a value outside the ' + 'set of indexes\n' + ' for the sequence (after any special interpretation of ' + 'negative\n' + ' values), "IndexError" should be raised. For *mapping* ' + 'types, if\n' + ' *key* is missing (not in the container), "KeyError" ' + 'should be\n' + ' raised.\n' '\n' ' Note:\n' '\n' @@ -8513,6 +8714,15 @@ 'of the\n' ' sequence.\n' '\n' + ' Note:\n' + '\n' + ' When subscripting a *class*, the special class ' + 'method\n' + ' "__class_getitem__()" may be called instead of ' + '"__getitem__()".\n' + ' See __class_getitem__ versus __getitem__ for more ' + 'details.\n' + '\n' 'object.__setitem__(self, key, value)\n' '\n' ' Called to implement assignment to "self[key]". Same ' @@ -8548,19 +8758,13 @@ '\n' 'object.__iter__(self)\n' '\n' - ' This method is called when an iterator is required for ' - 'a container.\n' - ' This method should return a new iterator object that ' - 'can iterate\n' - ' over all the objects in the container. For mappings, ' - 'it should\n' - ' iterate over the keys of the container.\n' - '\n' - ' Iterator objects also need to implement this method; ' - 'they are\n' - ' required to return themselves. For more information on ' - 'iterator\n' - ' objects, see Iterator Types.\n' + ' This method is called when an *iterator* is required ' + 'for a\n' + ' container. This method should return a new iterator ' + 'object that can\n' + ' iterate over all the objects in the container. For ' + 'mappings, it\n' + ' should iterate over the keys of the container.\n' '\n' 'object.__reversed__(self)\n' '\n' @@ -8623,6 +8827,10 @@ 'the\n' 'second argument.\n' '\n' + 'This operation can be customized using the special ' + '"__lshift__()" and\n' + '"__rshift__()" methods.\n' + '\n' 'A right shift by *n* bits is defined as floor division by ' '"pow(2,n)".\n' 'A left shift by *n* bits is defined as multiplication with ' @@ -8837,13 +9045,13 @@ '\n' ' If "__new__()" is invoked during object construction and ' 'it returns\n' - ' an instance or subclass of *cls*, then the new ' - 'instance’s\n' - ' "__init__()" method will be invoked like "__init__(self[, ' - '...])",\n' - ' where *self* is the new instance and the remaining ' - 'arguments are\n' - ' the same as were passed to the object constructor.\n' + ' an instance of *cls*, then the new instance’s ' + '"__init__()" method\n' + ' will be invoked like "__init__(self[, ...])", where ' + '*self* is the\n' + ' new instance and the remaining arguments are the same as ' + 'were\n' + ' passed to the object constructor.\n' '\n' ' If "__new__()" does not return an instance of *cls*, then ' 'the new\n' @@ -9511,32 +9719,6 @@ 'of the\n' ' owner class.\n' '\n' - 'object.__set_name__(self, owner, name)\n' - '\n' - ' Called at the time the owning class *owner* is created. ' - 'The\n' - ' descriptor has been assigned to *name*.\n' - '\n' - ' Note:\n' - '\n' - ' "__set_name__()" is only called implicitly as part of ' - 'the "type"\n' - ' constructor, so it will need to be called explicitly ' - 'with the\n' - ' appropriate parameters when a descriptor is added to a ' - 'class\n' - ' after initial creation:\n' - '\n' - ' class A:\n' - ' pass\n' - ' descr = custom_descriptor()\n' - ' A.attr = descr\n' - " descr.__set_name__(A, 'attr')\n" - '\n' - ' See Creating the class object for more details.\n' - '\n' - ' New in version 3.6.\n' - '\n' 'The attribute "__objclass__" is interpreted by the "inspect" ' 'module as\n' 'specifying the class where this object was defined (setting ' @@ -9613,10 +9795,10 @@ '\n' 'For instance bindings, the precedence of descriptor ' 'invocation depends\n' - 'on the which descriptor methods are defined. A descriptor ' - 'can define\n' - 'any combination of "__get__()", "__set__()" and ' - '"__delete__()". If it\n' + 'on which descriptor methods are defined. A descriptor can ' + 'define any\n' + 'combination of "__get__()", "__set__()" and "__delete__()". ' + 'If it\n' 'does not define "__get__()", then accessing the attribute ' 'will return\n' 'the descriptor object itself unless there is a value in the ' @@ -9826,6 +10008,38 @@ '\n' ' New in version 3.6.\n' '\n' + 'When a class is created, "type.__new__()" scans the class ' + 'variables\n' + 'and makes callbacks to those with a "__set_name__()" hook.\n' + '\n' + 'object.__set_name__(self, owner, name)\n' + '\n' + ' Automatically called at the time the owning class *owner* ' + 'is\n' + ' created. The object has been assigned to *name* in that ' + 'class:\n' + '\n' + ' class A:\n' + ' x = C() # Automatically calls: x.__set_name__(A, ' + "'x')\n" + '\n' + ' If the class variable is assigned after the class is ' + 'created,\n' + ' "__set_name__()" will not be called automatically. If ' + 'needed,\n' + ' "__set_name__()" can be called directly:\n' + '\n' + ' class A:\n' + ' pass\n' + '\n' + ' c = C()\n' + ' A.x = c # The hook is not called\n' + " c.__set_name__(A, 'x') # Manually invoke the hook\n" + '\n' + ' See Creating the class object for more details.\n' + '\n' + ' New in version 3.6.\n' + '\n' '\n' 'Metaclasses\n' '-----------\n' @@ -10021,22 +10235,21 @@ 'When using the default metaclass "type", or any metaclass ' 'that\n' 'ultimately calls "type.__new__", the following additional\n' - 'customisation steps are invoked after creating the class ' + 'customization steps are invoked after creating the class ' 'object:\n' '\n' - '* first, "type.__new__" collects all of the descriptors in ' - 'the class\n' - ' namespace that define a "__set_name__()" method;\n' + '1. The "type.__new__" method collects all of the attributes ' + 'in the\n' + ' class namespace that define a "__set_name__()" method;\n' '\n' - '* second, all of these "__set_name__" methods are called ' - 'with the\n' - ' class being defined and the assigned name of that ' - 'particular\n' - ' descriptor;\n' + '2. Those "__set_name__" methods are called with the class ' + 'being\n' + ' defined and the assigned name of that particular ' + 'attribute;\n' '\n' - '* finally, the "__init_subclass__()" hook is called on the ' - 'immediate\n' - ' parent of the new class in its method resolution order.\n' + '3. The "__init_subclass__()" hook is called on the immediate ' + 'parent of\n' + ' the new class in its method resolution order.\n' '\n' 'After the class object is created, it is passed to the ' 'class\n' @@ -10129,9 +10342,33 @@ 'Emulating generic types\n' '=======================\n' '\n' - 'One can implement the generic class syntax as specified by ' - '**PEP 484**\n' - '(for example "List[int]") by defining a special method:\n' + 'When using *type annotations*, it is often useful to ' + '*parameterize* a\n' + '*generic type* using Python’s square-brackets notation. For ' + 'example,\n' + 'the annotation "list[int]" might be used to signify a "list" ' + 'in which\n' + 'all the elements are of type "int".\n' + '\n' + 'See also:\n' + '\n' + ' **PEP 484** - Type Hints\n' + ' Introducing Python’s framework for type annotations\n' + '\n' + ' Generic Alias Types\n' + ' Documentation for objects representing parameterized ' + 'generic\n' + ' classes\n' + '\n' + ' Generics, user-defined generics and "typing.Generic"\n' + ' Documentation on how to implement generic classes that ' + 'can be\n' + ' parameterized at runtime and understood by static ' + 'type-checkers.\n' + '\n' + 'A class can *generally* only be parameterized if it defines ' + 'the\n' + 'special class method "__class_getitem__()".\n' '\n' 'classmethod object.__class_getitem__(cls, key)\n' '\n' @@ -10139,18 +10376,144 @@ 'generic class\n' ' by type arguments found in *key*.\n' '\n' - 'This method is looked up on the class object itself, and ' - 'when defined\n' - 'in the class body, this method is implicitly a class ' - 'method. Note,\n' - 'this mechanism is primarily reserved for use with static ' - 'type hints,\n' - 'other usage is discouraged.\n' + ' When defined on a class, "__class_getitem__()" is ' + 'automatically a\n' + ' class method. As such, there is no need for it to be ' + 'decorated with\n' + ' "@classmethod" when it is defined.\n' + '\n' + '\n' + 'The purpose of *__class_getitem__*\n' + '----------------------------------\n' + '\n' + 'The purpose of "__class_getitem__()" is to allow runtime\n' + 'parameterization of standard-library generic classes in ' + 'order to more\n' + 'easily apply *type hints* to these classes.\n' + '\n' + 'To implement custom generic classes that can be ' + 'parameterized at\n' + 'runtime and understood by static type-checkers, users should ' + 'either\n' + 'inherit from a standard library class that already ' + 'implements\n' + '"__class_getitem__()", or inherit from "typing.Generic", ' + 'which has its\n' + 'own implementation of "__class_getitem__()".\n' + '\n' + 'Custom implementations of "__class_getitem__()" on classes ' + 'defined\n' + 'outside of the standard library may not be understood by ' + 'third-party\n' + 'type-checkers such as mypy. Using "__class_getitem__()" on ' + 'any class\n' + 'for purposes other than type hinting is discouraged.\n' + '\n' + '\n' + '*__class_getitem__* versus *__getitem__*\n' + '----------------------------------------\n' + '\n' + 'Usually, the subscription of an object using square brackets ' + 'will call\n' + 'the "__getitem__()" instance method defined on the object’s ' + 'class.\n' + 'However, if the object being subscribed is itself a class, ' + 'the class\n' + 'method "__class_getitem__()" may be called instead.\n' + '"__class_getitem__()" should return a GenericAlias object if ' + 'it is\n' + 'properly defined.\n' + '\n' + 'Presented with the *expression* "obj[x]", the Python ' + 'interpreter\n' + 'follows something like the following process to decide ' + 'whether\n' + '"__getitem__()" or "__class_getitem__()" should be called:\n' + '\n' + ' from inspect import isclass\n' + '\n' + ' def subscribe(obj, x):\n' + ' """Return the result of the expression `obj[x]`"""\n' + '\n' + ' class_of_obj = type(obj)\n' + '\n' + ' # If the class of obj defines __getitem__,\n' + ' # call class_of_obj.__getitem__(obj, x)\n' + " if hasattr(class_of_obj, '__getitem__'):\n" + ' return class_of_obj.__getitem__(obj, x)\n' + '\n' + ' # Else, if obj is a class and defines ' + '__class_getitem__,\n' + ' # call obj.__class_getitem__(x)\n' + ' elif isclass(obj) and hasattr(obj, ' + "'__class_getitem__'):\n" + ' return obj.__class_getitem__(x)\n' + '\n' + ' # Else, raise an exception\n' + ' else:\n' + ' raise TypeError(\n' + ' f"\'{class_of_obj.__name__}\' object is not ' + 'subscriptable"\n' + ' )\n' + '\n' + 'In Python, all classes are themselves instances of other ' + 'classes. The\n' + 'class of a class is known as that class’s *metaclass*, and ' + 'most\n' + 'classes have the "type" class as their metaclass. "type" ' + 'does not\n' + 'define "__getitem__()", meaning that expressions such as ' + '"list[int]",\n' + '"dict[str, float]" and "tuple[str, bytes]" all result in\n' + '"__class_getitem__()" being called:\n' + '\n' + ' >>> # list has class "type" as its metaclass, like most ' + 'classes:\n' + ' >>> type(list)\n' + " \n" + ' >>> type(dict) == type(list) == type(tuple) == type(str) ' + '== type(bytes)\n' + ' True\n' + ' >>> # "list[int]" calls "list.__class_getitem__(int)"\n' + ' >>> list[int]\n' + ' list[int]\n' + ' >>> # list.__class_getitem__ returns a GenericAlias ' + 'object:\n' + ' >>> type(list[int])\n' + " \n" + '\n' + 'However, if a class has a custom metaclass that defines\n' + '"__getitem__()", subscribing the class may result in ' + 'different\n' + 'behaviour. An example of this can be found in the "enum" ' + 'module:\n' + '\n' + ' >>> from enum import Enum\n' + ' >>> class Menu(Enum):\n' + ' ... """A breakfast menu"""\n' + " ... SPAM = 'spam'\n" + " ... BACON = 'bacon'\n" + ' ...\n' + ' >>> # Enum classes have a custom metaclass:\n' + ' >>> type(Menu)\n' + " \n" + ' >>> # EnumMeta defines __getitem__,\n' + ' >>> # so __class_getitem__ is not called,\n' + ' >>> # and the result is not a GenericAlias object:\n' + " >>> Menu['SPAM']\n" + " \n" + " >>> type(Menu['SPAM'])\n" + " \n" '\n' 'See also:\n' '\n' - ' **PEP 560** - Core support for typing module and generic ' + ' **PEP 560** - Core Support for typing module and generic ' 'types\n' + ' Introducing "__class_getitem__()", and outlining when ' + 'a\n' + ' subscription results in "__class_getitem__()" being ' + 'called\n' + ' instead of "__getitem__()"\n' '\n' '\n' 'Emulating callable objects\n' @@ -10280,22 +10643,23 @@ 'object.__getitem__(self, key)\n' '\n' ' Called to implement evaluation of "self[key]". For ' - 'sequence types,\n' - ' the accepted keys should be integers and slice objects. ' - 'Note that\n' - ' the special interpretation of negative indexes (if the ' - 'class wishes\n' - ' to emulate a sequence type) is up to the "__getitem__()" ' - 'method. If\n' - ' *key* is of an inappropriate type, "TypeError" may be ' - 'raised; if of\n' - ' a value outside the set of indexes for the sequence ' - '(after any\n' - ' special interpretation of negative values), "IndexError" ' + '*sequence*\n' + ' types, the accepted keys should be integers and slice ' + 'objects.\n' + ' Note that the special interpretation of negative indexes ' + '(if the\n' + ' class wishes to emulate a *sequence* type) is up to the\n' + ' "__getitem__()" method. If *key* is of an inappropriate ' + 'type,\n' + ' "TypeError" may be raised; if of a value outside the set ' + 'of indexes\n' + ' for the sequence (after any special interpretation of ' + 'negative\n' + ' values), "IndexError" should be raised. For *mapping* ' + 'types, if\n' + ' *key* is missing (not in the container), "KeyError" ' 'should be\n' - ' raised. For mapping types, if *key* is missing (not in ' - 'the\n' - ' container), "KeyError" should be raised.\n' + ' raised.\n' '\n' ' Note:\n' '\n' @@ -10305,6 +10669,14 @@ 'the\n' ' sequence.\n' '\n' + ' Note:\n' + '\n' + ' When subscripting a *class*, the special class method\n' + ' "__class_getitem__()" may be called instead of ' + '"__getitem__()".\n' + ' See __class_getitem__ versus __getitem__ for more ' + 'details.\n' + '\n' 'object.__setitem__(self, key, value)\n' '\n' ' Called to implement assignment to "self[key]". Same note ' @@ -10340,19 +10712,13 @@ '\n' 'object.__iter__(self)\n' '\n' - ' This method is called when an iterator is required for a ' - 'container.\n' - ' This method should return a new iterator object that can ' - 'iterate\n' - ' over all the objects in the container. For mappings, it ' - 'should\n' - ' iterate over the keys of the container.\n' - '\n' - ' Iterator objects also need to implement this method; they ' - 'are\n' - ' required to return themselves. For more information on ' - 'iterator\n' - ' objects, see Iterator Types.\n' + ' This method is called when an *iterator* is required for ' + 'a\n' + ' container. This method should return a new iterator ' + 'object that can\n' + ' iterate over all the objects in the container. For ' + 'mappings, it\n' + ' should iterate over the keys of the container.\n' '\n' 'object.__reversed__(self)\n' '\n' @@ -10595,9 +10961,9 @@ ' of the object truncated to an "Integral" (typically an ' '"int").\n' '\n' - ' If "__int__()" is not defined then the built-in function ' - '"int()"\n' - ' falls back to "__trunc__()".\n' + ' The built-in function "int()" falls back to "__trunc__()" ' + 'if\n' + ' neither "__int__()" nor "__index__()" is defined.\n' '\n' '\n' 'With Statement Context Managers\n' @@ -10677,17 +11043,16 @@ '\n' 'object.__match_args__\n' '\n' - ' This class variable can be assigned a tuple or list of ' - 'strings.\n' - ' When this class is used in a class pattern with ' - 'positional\n' - ' arguments, each positional argument will be converted ' - 'into a\n' - ' keyword argument, using the corresponding value in ' - '*__match_args__*\n' - ' as the keyword. The absence of this attribute is ' - 'equivalent to\n' - ' setting it to "()".\n' + ' This class variable can be assigned a tuple of strings. ' + 'When this\n' + ' class is used in a class pattern with positional ' + 'arguments, each\n' + ' positional argument will be converted into a keyword ' + 'argument,\n' + ' using the corresponding value in *__match_args__* as the ' + 'keyword.\n' + ' The absence of this attribute is equivalent to setting it ' + 'to "()".\n' '\n' 'For example, if "MyClass.__match_args__" is "("left", ' '"center",\n' @@ -12680,7 +13045,13 @@ '| |\n' ' | | and "\'return\'" for the ' 'return | |\n' - ' | | annotation, if provided. ' + ' | | annotation, if provided. For ' + '| |\n' + ' | | more information on working ' + '| |\n' + ' | | with this attribute, see ' + '| |\n' + ' | | Annotations Best Practices. ' '| |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' @@ -12801,20 +13172,18 @@ ' A function or method which uses the "yield" statement (see\n' ' section The yield statement) is called a *generator ' 'function*.\n' - ' Such a function, when called, always returns an iterator ' - 'object\n' - ' which can be used to execute the body of the function: ' - 'calling\n' - ' the iterator’s "iterator.__next__()" method will cause the\n' - ' function to execute until it provides a value using the ' - '"yield"\n' - ' statement. When the function executes a "return" statement ' - 'or\n' - ' falls off the end, a "StopIteration" exception is raised and ' - 'the\n' - ' iterator will have reached the end of the set of values to ' - 'be\n' - ' returned.\n' + ' Such a function, when called, always returns an *iterator*\n' + ' object which can be used to execute the body of the ' + 'function:\n' + ' calling the iterator’s "iterator.__next__()" method will ' + 'cause\n' + ' the function to execute until it provides a value using the\n' + ' "yield" statement. When the function executes a "return"\n' + ' statement or falls off the end, a "StopIteration" exception ' + 'is\n' + ' raised and the iterator will have reached the end of the set ' + 'of\n' + ' values to be returned.\n' '\n' ' Coroutine functions\n' ' A function or method which is defined using "async def" is\n' @@ -12830,9 +13199,9 @@ ' which uses the "yield" statement is called a *asynchronous\n' ' generator function*. Such a function, when called, returns ' 'an\n' - ' asynchronous iterator object which can be used in an "async ' - 'for"\n' - ' statement to execute the body of the function.\n' + ' *asynchronous iterator* object which can be used in an ' + '"async\n' + ' for" statement to execute the body of the function.\n' '\n' ' Calling the asynchronous iterator’s "aiterator.__anext__()"\n' ' method will return an *awaitable* which when awaited will\n' @@ -12905,20 +13274,34 @@ ' Attribute assignment updates the module’s namespace dictionary,\n' ' e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n' '\n' - ' Predefined (writable) attributes: "__name__" is the module’s ' - 'name;\n' - ' "__doc__" is the module’s documentation string, or "None" if\n' - ' unavailable; "__annotations__" (optional) is a dictionary\n' - ' containing *variable annotations* collected during module body\n' - ' execution; "__file__" is the pathname of the file from which ' + ' Predefined (writable) attributes:\n' + '\n' + ' "__name__"\n' + ' The module’s name.\n' + '\n' + ' "__doc__"\n' + ' The module’s documentation string, or "None" if ' + 'unavailable.\n' + '\n' + ' "__file__"\n' + ' The pathname of the file from which the module was loaded, ' + 'if\n' + ' it was loaded from a file. The "__file__" attribute may ' + 'be\n' + ' missing for certain types of modules, such as C modules ' + 'that\n' + ' are statically linked into the interpreter. For ' + 'extension\n' + ' modules loaded dynamically from a shared library, it’s ' 'the\n' - ' module was loaded, if it was loaded from a file. The "__file__"\n' - ' attribute may be missing for certain types of modules, such as ' - 'C\n' - ' modules that are statically linked into the interpreter; for\n' - ' extension modules loaded dynamically from a shared library, it ' - 'is\n' - ' the pathname of the shared library file.\n' + ' pathname of the shared library file.\n' + '\n' + ' "__annotations__"\n' + ' A dictionary containing *variable annotations* collected\n' + ' during module body execution. For best practices on ' + 'working\n' + ' with "__annotations__", please see Annotations Best\n' + ' Practices.\n' '\n' ' Special read-only attribute: "__dict__" is the module’s ' 'namespace\n' @@ -12976,20 +13359,31 @@ 'instance\n' ' (see below).\n' '\n' - ' Special attributes: "__name__" is the class name; "__module__" ' - 'is\n' - ' the module name in which the class was defined; "__dict__" is ' - 'the\n' - ' dictionary containing the class’s namespace; "__bases__" is a ' - 'tuple\n' - ' containing the base classes, in the order of their occurrence ' - 'in\n' - ' the base class list; "__doc__" is the class’s documentation ' - 'string,\n' - ' or "None" if undefined; "__annotations__" (optional) is a\n' - ' dictionary containing *variable annotations* collected during ' - 'class\n' - ' body execution.\n' + ' Special attributes:\n' + '\n' + ' "__name__"\n' + ' The class name.\n' + '\n' + ' "__module__"\n' + ' The name of the module in which the class was defined.\n' + '\n' + ' "__dict__"\n' + ' The dictionary containing the class’s namespace.\n' + '\n' + ' "__bases__"\n' + ' A tuple containing the base classes, in the order of ' + 'their\n' + ' occurrence in the base class list.\n' + '\n' + ' "__doc__"\n' + ' The class’s documentation string, or "None" if undefined.\n' + '\n' + ' "__annotations__"\n' + ' A dictionary containing *variable annotations* collected\n' + ' during class body execution. For best practices on ' + 'working\n' + ' with "__annotations__", please see Annotations Best\n' + ' Practices.\n' '\n' 'Class instances\n' ' A class instance is created by calling a class object (see ' @@ -13150,6 +13544,10 @@ ' gives the precise instruction (this is an index into the\n' ' bytecode string of the code object).\n' '\n' + ' Accessing "f_code" raises an auditing event ' + '"object.__getattr__"\n' + ' with arguments "obj" and ""f_code"".\n' + '\n' ' Special writable attributes: "f_trace", if not "None", is a\n' ' function called for various events during code execution ' '(this\n' @@ -13233,6 +13631,9 @@ ' the exception occurred in a "try" statement with no matching\n' ' except clause or with a finally clause.\n' '\n' + ' Accessing "tb_frame" raises an auditing event\n' + ' "object.__getattr__" with arguments "obj" and ""tb_frame"".\n' + '\n' ' Special writable attribute: "tb_next" is the next level in ' 'the\n' ' stack trace (towards the frame where the exception occurred), ' @@ -13283,9 +13684,8 @@ ' object actually returned is the wrapped object, which is not\n' ' subject to any further transformation. Static method objects ' 'are\n' - ' not themselves callable, although the objects they wrap ' - 'usually\n' - ' are. Static method objects are created by the built-in\n' + ' also callable. Static method objects are created by the ' + 'built-in\n' ' "staticmethod()" constructor.\n' '\n' ' Class method objects\n' @@ -14237,7 +14637,7 @@ '| | "s[i:i] = ' '[x]") | |\n' '+--------------------------------+----------------------------------+-----------------------+\n' - '| "s.pop([i])" | retrieves the item at *i* ' + '| "s.pop()" or "s.pop(i)" | retrieves the item at *i* ' 'and | (2) |\n' '| | also removes it from ' '*s* | |\n' @@ -14700,7 +15100,7 @@ '| | "s[i:i] = ' '[x]") | |\n' '+--------------------------------+----------------------------------+-----------------------+\n' - '| "s.pop([i])" | retrieves the item at ' + '| "s.pop()" or "s.pop(i)" | retrieves the item at ' '*i* and | (2) |\n' '| | also removes it from ' '*s* | |\n' @@ -14765,15 +15165,21 @@ ' u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n' '\n' 'The unary "-" (minus) operator yields the negation of its numeric\n' - 'argument.\n' + 'argument; the operation can be overridden with the "__neg__()" ' + 'special\n' + 'method.\n' '\n' 'The unary "+" (plus) operator yields its numeric argument ' - 'unchanged.\n' + 'unchanged;\n' + 'the operation can be overridden with the "__pos__()" special ' + 'method.\n' '\n' 'The unary "~" (invert) operator yields the bitwise inversion of ' 'its\n' 'integer argument. The bitwise inversion of "x" is defined as\n' - '"-(x+1)". It only applies to integral numbers.\n' + '"-(x+1)". It only applies to integral numbers or to custom ' + 'objects\n' + 'that override the "__invert__()" special method.\n' '\n' 'In all three cases, if the argument does not have the proper type, ' 'a\n' diff --git a/Lib/random.py b/Lib/random.py index 3a835aef0bc1d4..1310a2d9d0e071 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -154,8 +154,7 @@ def seed(self, a=None, version=2): elif version == 2 and isinstance(a, (str, bytes, bytearray)): if isinstance(a, str): a = a.encode() - a += _sha512(a).digest() - a = int.from_bytes(a, 'big') + a = int.from_bytes(a + _sha512(a).digest(), 'big') elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)): _warn('Seeding based on hashing is deprecated\n' diff --git a/Lib/re.py b/Lib/re.py index ea41217ce08c2d..1d82b5006396cd 100644 --- a/Lib/re.py +++ b/Lib/re.py @@ -142,9 +142,7 @@ __version__ = "2.2.1" -@enum.global_enum -@enum._simple_enum(enum.IntFlag, boundary=enum.KEEP) -class RegexFlag: +class RegexFlag(enum.IntFlag): ASCII = A = sre_compile.SRE_FLAG_ASCII # assume ascii "locale" IGNORECASE = I = sre_compile.SRE_FLAG_IGNORECASE # ignore case LOCALE = L = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale @@ -156,6 +154,30 @@ class RegexFlag: TEMPLATE = T = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation + def __repr__(self): + if self._name_ is not None: + return f're.{self._name_}' + value = self._value_ + members = [] + negative = value < 0 + if negative: + value = ~value + for m in self.__class__: + if value & m._value_: + value &= ~m._value_ + members.append(f're.{m._name_}') + if value: + members.append(hex(value)) + res = '|'.join(members) + if negative: + if len(members) > 1: + res = f'~({res})' + else: + res = f'~{res}' + return res + __str__ = object.__str__ +globals().update(RegexFlag.__members__) + # sre exception error = sre_compile.error diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py index c06388e8d9c2dd..98b7930b32fab3 100644 --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -176,13 +176,20 @@ def attr_matches(self, text): if (word[:n] == attr and not (noprefix and word[:n+1] == noprefix)): match = "%s.%s" % (expr, word) - try: - val = getattr(thisobject, word) - except Exception: - pass # Include even if attribute not set + if isinstance(getattr(type(thisobject), word, None), + property): + # bpo-44752: thisobject.word is a method decorated by + # `@property`. What follows applies a postfix if + # thisobject.word is callable, but know we know that + # this is not callable (because it is a property). + # Also, getattr(thisobject, word) will evaluate the + # property method, which is not desirable. + matches.append(match) + continue + if (value := getattr(thisobject, word, None)) is not None: + matches.append(self._callable_postfix(value, match)) else: - match = self._callable_postfix(val, match) - matches.append(match) + matches.append(match) if matches or not noprefix: break if noprefix == '_': diff --git a/Lib/shutil.py b/Lib/shutil.py index e29fe4d83e9277..0056a1bc77ad84 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -251,28 +251,37 @@ def copyfile(src, dst, *, follow_symlinks=True): if not follow_symlinks and _islink(src): os.symlink(os.readlink(src), dst) else: - with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst: - # macOS - if _HAS_FCOPYFILE: - try: - _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA) - return dst - except _GiveupOnFastCopy: - pass - # Linux - elif _USE_CP_SENDFILE: - try: - _fastcopy_sendfile(fsrc, fdst) - return dst - except _GiveupOnFastCopy: - pass - # Windows, see: - # https://github.com/python/cpython/pull/7160#discussion_r195405230 - elif _WINDOWS and file_size > 0: - _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE)) - return dst - - copyfileobj(fsrc, fdst) + with open(src, 'rb') as fsrc: + try: + with open(dst, 'wb') as fdst: + # macOS + if _HAS_FCOPYFILE: + try: + _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA) + return dst + except _GiveupOnFastCopy: + pass + # Linux + elif _USE_CP_SENDFILE: + try: + _fastcopy_sendfile(fsrc, fdst) + return dst + except _GiveupOnFastCopy: + pass + # Windows, see: + # https://github.com/python/cpython/pull/7160#discussion_r195405230 + elif _WINDOWS and file_size > 0: + _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE)) + return dst + + copyfileobj(fsrc, fdst) + + # Issue 43219, raise a less confusing exception + except IsADirectoryError as e: + if not os.path.exists(dst): + raise FileNotFoundError(f'Directory does not exist: {dst}') from e + else: + raise return dst @@ -1161,20 +1170,16 @@ def _unpack_zipfile(filename, extract_dir): if name.startswith('/') or '..' in name: continue - target = os.path.join(extract_dir, *name.split('/')) - if not target: + targetpath = os.path.join(extract_dir, *name.split('/')) + if not targetpath: continue - _ensure_directory(target) + _ensure_directory(targetpath) if not name.endswith('/'): # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data + with zip.open(name, 'r') as source, \ + open(targetpath, 'wb') as target: + copyfileobj(source, target) finally: zip.close() diff --git a/Lib/signal.py b/Lib/signal.py index d4a6d6fe2ada8b..50b215b29d2fad 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -1,6 +1,5 @@ import _signal from _signal import * -from functools import wraps as _wraps from enum import IntEnum as _IntEnum _globals = globals() @@ -42,6 +41,16 @@ def _enum_to_int(value): return value +# Similar to functools.wraps(), but only assign __doc__. +# __module__ should be preserved, +# __name__ and __qualname__ are already fine, +# __annotations__ is not set. +def _wraps(wrapped): + def decorator(wrapper): + wrapper.__doc__ = wrapped.__doc__ + return wrapper + return decorator + @_wraps(_signal.signal) def signal(signalnum, handler): handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) @@ -59,7 +68,6 @@ def getsignal(signalnum): def pthread_sigmask(how, mask): sigs_set = _signal.pthread_sigmask(how, mask) return set(_int_to_enum(x, Signals) for x in sigs_set) - pthread_sigmask.__doc__ = _signal.pthread_sigmask.__doc__ if 'sigpending' in _globals: @@ -73,7 +81,6 @@ def sigpending(): def sigwait(sigset): retsig = _signal.sigwait(sigset) return _int_to_enum(retsig, Signals) - sigwait.__doc__ = _signal.sigwait if 'valid_signals' in _globals: diff --git a/Lib/smtpd.py b/Lib/smtpd.py index 1e2adc87a2bf2a..bc433312510097 100755 --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -83,8 +83,6 @@ import getopt import time import socket -import asyncore -import asynchat import collections from warnings import warn from email._header_value_parser import get_addr_spec, get_angle_addr @@ -94,6 +92,19 @@ "MailmanProxy", ] +warn( + 'The smtpd module is deprecated and unmaintained. Please see aiosmtpd ' + '(https://aiosmtpd.readthedocs.io/) for the recommended replacement.', + DeprecationWarning, + stacklevel=2) + + +# These are imported after the above warning so that users get the correct +# deprecation warning. +import asyncore +import asynchat + + program = sys.argv[0] __version__ = 'Python SMTP proxy version 0.3' diff --git a/Lib/smtplib.py b/Lib/smtplib.py index bfba5c8f21be06..324a1c19f12afe 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -168,7 +168,7 @@ def quotedata(data): """Quote data for email. Double leading '.', and change Unix newline '\\n', or Mac '\\r' into - Internet CRLF end-of-line. + internet CRLF end-of-line. """ return re.sub(r'(?m)^\.', '..', re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)) @@ -367,10 +367,15 @@ def send(self, s): def putcmd(self, cmd, args=""): """Send a command to the server.""" if args == "": - str = '%s%s' % (cmd, CRLF) + s = cmd else: - str = '%s %s%s' % (cmd, args, CRLF) - self.send(str) + s = f'{cmd} {args}' + if '\r' in s or '\n' in s: + s = s.replace('\n', '\\n').replace('\r', '\\r') + raise ValueError( + f'command and arguments contain prohibited newline characters: {s}' + ) + self.send(f'{s}{CRLF}') def getreply(self): """Get a reply from the server. diff --git a/Lib/socket.py b/Lib/socket.py index fc11eb783c3dd1..63ba0acc908c3c 100755 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -782,8 +782,9 @@ def getfqdn(name=''): An empty argument is interpreted as meaning the local host. First the hostname returned by gethostbyaddr() is checked, then - possibly existing aliases. In case no FQDN is available, hostname - from gethostname() is returned. + possibly existing aliases. In case no FQDN is available and `name` + was given, it is returned unchanged. If `name` was empty or '0.0.0.0', + hostname from gethostname() is returned. """ name = name.strip() if not name or name == '0.0.0.0': diff --git a/Lib/sqlite3/__init__.py b/Lib/sqlite3/__init__.py index f001c0678e195f..0dedf186b1a1eb 100644 --- a/Lib/sqlite3/__init__.py +++ b/Lib/sqlite3/__init__.py @@ -20,6 +20,40 @@ # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. +""" +The sqlite3 extension module provides a DB-API 2.0 (PEP 249) compilant +interface to the SQLite library, and requires SQLite 3.7.15 or newer. + +To use the module, start by creating a database Connection object: + + import sqlite3 + cx = sqlite3.connect("test.db") # test.db will be created or opened + +The special path name ":memory:" can be provided to connect to a transient +in-memory database: + + cx = sqlite3.connect(":memory:") # connect to a database in RAM + +Once a connection has been established, create a Cursor object and call +its execute() method to perform SQL queries: + + cu = cx.cursor() + + # create a table + cu.execute("create table lang(name, first_appeared)") + + # insert values into a table + cu.execute("insert into lang values (?, ?)", ("C", 1972)) + + # execute a query and iterate over the result + for row in cu.execute("select * from lang"): + print(row) + + cx.close() + +The sqlite3 module is written by Gerhard Häring . +""" + from sqlite3.dbapi2 import * diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 39c9bf5b61143d..e332184a7d1074 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -20,11 +20,13 @@ # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. +import subprocess import threading import unittest import sqlite3 as sqlite import sys +from test.support import check_disallow_instantiation, SHORT_TIMEOUT from test.support.os_helper import TESTFN, unlink @@ -92,6 +94,10 @@ def test_shared_cache_deprecated(self): sqlite.enable_shared_cache(enable) self.assertIn("dbapi.py", cm.filename) + def test_disallow_instantiation(self): + cx = sqlite.connect(":memory:") + check_disallow_instantiation(self, type(cx("select 1"))) + class ConnectionTests(unittest.TestCase): @@ -192,6 +198,26 @@ def test_open_uri(self): cx.execute('insert into test(id) values(1)') +class UninitialisedConnectionTests(unittest.TestCase): + def setUp(self): + self.cx = sqlite.Connection.__new__(sqlite.Connection) + + def test_uninit_operations(self): + funcs = ( + lambda: self.cx.isolation_level, + lambda: self.cx.total_changes, + lambda: self.cx.in_transaction, + lambda: self.cx.iterdump(), + lambda: self.cx.cursor(), + lambda: self.cx.close(), + ) + for func in funcs: + with self.subTest(func=func): + self.assertRaisesRegex(sqlite.ProgrammingError, + "Base Connection.__init__ not called", + func) + + class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") @@ -372,6 +398,9 @@ class MyIter: def __init__(self): self.value = 5 + def __iter__(self): + return self + def __next__(self): if self.value == 10: raise StopIteration @@ -425,7 +454,7 @@ def test_fetchone_no_statement(self): self.assertEqual(row, None) def test_array_size(self): - # must default ot 1 + # must default to 1 self.assertEqual(self.cu.arraysize, 1) # now set to 2 @@ -933,6 +962,77 @@ def test_on_conflict_replace(self): self.assertEqual(self.cu.fetchall(), [('Very different data!', 'foo')]) +class MultiprocessTests(unittest.TestCase): + CONNECTION_TIMEOUT = SHORT_TIMEOUT / 1000. # Defaults to 30 ms + + def tearDown(self): + unlink(TESTFN) + + def test_ctx_mgr_rollback_if_commit_failed(self): + # bpo-27334: ctx manager does not rollback if commit fails + SCRIPT = f"""if 1: + import sqlite3 + def wait(): + print("started") + assert "database is locked" in input() + + cx = sqlite3.connect("{TESTFN}", timeout={self.CONNECTION_TIMEOUT}) + cx.create_function("wait", 0, wait) + with cx: + cx.execute("create table t(t)") + try: + # execute two transactions; both will try to lock the db + cx.executescript(''' + -- start a transaction and wait for parent + begin transaction; + select * from t; + select wait(); + rollback; + + -- start a new transaction; would fail if parent holds lock + begin transaction; + select * from t; + rollback; + ''') + finally: + cx.close() + """ + + # spawn child process + proc = subprocess.Popen( + [sys.executable, "-c", SCRIPT], + encoding="utf-8", + bufsize=0, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + self.addCleanup(proc.communicate) + + # wait for child process to start + self.assertEqual("started", proc.stdout.readline().strip()) + + cx = sqlite.connect(TESTFN, timeout=self.CONNECTION_TIMEOUT) + try: # context manager should correctly release the db lock + with cx: + cx.execute("insert into t values('test')") + except sqlite.OperationalError as exc: + proc.stdin.write(str(exc)) + else: + proc.stdin.write("no error") + finally: + cx.close() + + # terminate child process + self.assertIsNone(proc.returncode) + try: + proc.communicate(input="end", timeout=SHORT_TIMEOUT) + except subprocess.TimeoutExpired: + proc.kill() + proc.communicate() + raise + self.assertEqual(proc.returncode, 0) + + def suite(): tests = [ ClosedConTests, @@ -942,8 +1042,10 @@ def suite(): CursorTests, ExtensionTests, ModuleTests, + MultiprocessTests, SqliteOnConflictTests, ThreadTests, + UninitialisedConnectionTests, ] return unittest.TestSuite( [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests] diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py index a219e8911f7063..8c60bdcf5d70aa 100644 --- a/Lib/sqlite3/test/hooks.py +++ b/Lib/sqlite3/test/hooks.py @@ -237,7 +237,7 @@ def trace(statement): traced_statements.append(statement) con.set_trace_callback(trace) con.execute("create table foo(x)") - con.execute('insert into foo(x) values ("%s")' % unicode_value) + con.execute("insert into foo(x) values ('%s')" % unicode_value) con.commit() self.assertTrue(any(unicode_value in stmt for stmt in traced_statements), "Unicode data %s garbled in trace callback: %s" diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index 417a53109c87c7..70d0ff9af10713 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -125,11 +125,11 @@ def test_type_map_usage(self): con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES) con.execute("create table foo(bar timestamp)") con.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),)) - con.execute(SELECT) + con.execute(SELECT).close() con.execute("drop table foo") con.execute("create table foo(bar integer)") con.execute("insert into foo(bar) values (5)") - con.execute(SELECT) + con.execute(SELECT).close() def test_bind_mutating_list(self): # Issue41662: Crash when mutate a list of parameters during iteration. diff --git a/Lib/sqlite3/test/userfunctions.py b/Lib/sqlite3/test/userfunctions.py index 148d9f596a91c8..75e803582e06ba 100644 --- a/Lib/sqlite3/test/userfunctions.py +++ b/Lib/sqlite3/test/userfunctions.py @@ -23,10 +23,13 @@ import unittest import unittest.mock +import gc import sqlite3 as sqlite def func_returntext(): return "foo" +def func_returntextwithnull(): + return "1\x002" def func_returnunicode(): return "bar" def func_returnint(): @@ -137,11 +140,21 @@ def step(self, val): def finalize(self): return self.val +class AggrText: + def __init__(self): + self.txt = "" + def step(self, txt): + self.txt = self.txt + txt + def finalize(self): + return self.txt + + class FunctionTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.con.create_function("returntext", 0, func_returntext) + self.con.create_function("returntextwithnull", 0, func_returntextwithnull) self.con.create_function("returnunicode", 0, func_returnunicode) self.con.create_function("returnint", 0, func_returnint) self.con.create_function("returnfloat", 0, func_returnfloat) @@ -185,6 +198,12 @@ def test_func_return_text(self): self.assertEqual(type(val), str) self.assertEqual(val, "foo") + def test_func_return_text_with_null_char(self): + cur = self.con.cursor() + res = cur.execute("select returntextwithnull()").fetchone()[0] + self.assertEqual(type(res), str) + self.assertEqual(res, "1\x002") + def test_func_return_unicode(self): cur = self.con.cursor() cur.execute("select returnunicode()") @@ -236,9 +255,11 @@ def test_func_exception(self): def test_param_string(self): cur = self.con.cursor() - cur.execute("select isstring(?)", ("foo",)) - val = cur.fetchone()[0] - self.assertEqual(val, 1) + for text in ["foo", str()]: + with self.subTest(text=text): + cur.execute("select isstring(?)", (text,)) + val = cur.fetchone()[0] + self.assertEqual(val, 1) def test_param_int(self): cur = self.con.cursor() @@ -320,6 +341,22 @@ def test_func_deterministic_keyword_only(self): with self.assertRaises(TypeError): self.con.create_function("deterministic", 0, int, True) + def test_function_destructor_via_gc(self): + # See bpo-44304: The destructor of the user function can + # crash if is called without the GIL from the gc functions + dest = sqlite.connect(':memory:') + def md5sum(t): + return + + dest.create_function("md5", 1, md5sum) + x = dest("create table lang (name, first_appeared)") + del md5sum, dest + + y = [x] + y.append(y) + + del x,y + gc.collect() class AggregateTests(unittest.TestCase): def setUp(self): @@ -345,6 +382,7 @@ def setUp(self): self.con.create_aggregate("checkType", 2, AggrCheckType) self.con.create_aggregate("checkTypes", -1, AggrCheckTypes) self.con.create_aggregate("mysum", 1, AggrSum) + self.con.create_aggregate("aggtxt", 1, AggrText) def tearDown(self): #self.cur.close() @@ -391,9 +429,9 @@ def test_aggr_exception_in_finalize(self): def test_aggr_check_param_str(self): cur = self.con.cursor() - cur.execute("select checkType('str', ?)", ("foo",)) + cur.execute("select checkTypes('str', ?, ?)", ("foo", str())) val = cur.fetchone()[0] - self.assertEqual(val, 1) + self.assertEqual(val, 2) def test_aggr_check_param_int(self): cur = self.con.cursor() @@ -438,6 +476,15 @@ def test_aggr_no_match(self): val = cur.fetchone()[0] self.assertIsNone(val) + def test_aggr_text(self): + cur = self.con.cursor() + for txt in ["foo", "1\x002"]: + with self.subTest(txt=txt): + cur.execute("select aggtxt(?) from test", (txt,)) + val = cur.fetchone()[0] + self.assertEqual(val, txt) + + class AuthorizerTests(unittest.TestCase): @staticmethod def authorizer_cb(action, arg1, arg2, dbname, source): diff --git a/Lib/ssl.py b/Lib/ssl.py index 2b131de04306ac..181065d2e53bac 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -94,7 +94,6 @@ import os from collections import namedtuple from enum import Enum as _Enum, IntEnum as _IntEnum, IntFlag as _IntFlag -from enum import _simple_enum, _test_simple_enum import _ssl # if we can't import it, let the error propagate @@ -156,8 +155,7 @@ _SSLv2_IF_EXISTS = getattr(_SSLMethod, 'PROTOCOL_SSLv2', None) -@_simple_enum(_IntEnum) -class TLSVersion: +class TLSVersion(_IntEnum): MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED SSLv3 = _ssl.PROTO_SSLv3 TLSv1 = _ssl.PROTO_TLSv1 @@ -167,8 +165,7 @@ class TLSVersion: MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED -@_simple_enum(_IntEnum) -class _TLSContentType: +class _TLSContentType(_IntEnum): """Content types (record layer) See RFC 8446, section B.1 @@ -182,8 +179,7 @@ class _TLSContentType: INNER_CONTENT_TYPE = 0x101 -@_simple_enum(_IntEnum) -class _TLSAlertType: +class _TLSAlertType(_IntEnum): """Alert types for TLSContentType.ALERT messages See RFC 8466, section B.2 @@ -224,8 +220,7 @@ class _TLSAlertType: NO_APPLICATION_PROTOCOL = 120 -@_simple_enum(_IntEnum) -class _TLSMessageType: +class _TLSMessageType(_IntEnum): """Message types (handshake protocol) See RFC 8446, section B.3 @@ -387,7 +382,7 @@ def match_hostname(cert, hostname): returns nothing. """ warnings.warn( - "ssl module: match_hostname() is deprecated", + "ssl.match_hostname() is deprecated", category=DeprecationWarning, stacklevel=2 ) @@ -492,8 +487,7 @@ class SSLContext(_SSLContext): def __new__(cls, protocol=None, *args, **kwargs): if protocol is None: warnings.warn( - "ssl module: " - "SSLContext() without protocol argument is deprecated.", + "ssl.SSLContext() without protocol argument is deprecated.", category=DeprecationWarning, stacklevel=2 ) @@ -536,7 +530,11 @@ def wrap_bio(self, incoming, outgoing, server_side=False, ) def set_npn_protocols(self, npn_protocols): - warnings.warn("NPN is deprecated, use ALPN instead", stacklevel=2) + warnings.warn( + "ssl NPN is deprecated, use ALPN instead", + DeprecationWarning, + stacklevel=2 + ) protos = bytearray() for protocol in npn_protocols: b = bytes(protocol, 'ascii') @@ -940,7 +938,9 @@ def selected_npn_protocol(self): if a next protocol was not negotiated or if NPN is not supported by one of the peers.""" warnings.warn( - "ssl module: NPN is deprecated, use ALPN instead", stacklevel=2 + "ssl NPN is deprecated, use ALPN instead", + DeprecationWarning, + stacklevel=2 ) def selected_alpn_protocol(self): @@ -1157,7 +1157,9 @@ def getpeercert(self, binary_form=False): def selected_npn_protocol(self): self._checkClosed() warnings.warn( - "ssl module: NPN is deprecated, use ALPN instead", stacklevel=2 + "ssl NPN is deprecated, use ALPN instead", + DeprecationWarning, + stacklevel=2 ) return None @@ -1419,7 +1421,7 @@ def wrap_socket(sock, keyfile=None, certfile=None, suppress_ragged_eofs=True, ciphers=None): warnings.warn( - "ssl module: wrap_socket is deprecated, use SSLContext.wrap_socket()", + "ssl.wrap_socket() is deprecated, use SSLContext.wrap_socket()", category=DeprecationWarning, stacklevel=2 ) diff --git a/Lib/statistics.py b/Lib/statistics.py index 673a162b3a79fc..f66245380abb17 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -94,7 +94,7 @@ >>> correlation(x, y) #doctest: +ELLIPSIS 0.31622776601... >>> linear_regression(x, y) #doctest: -LinearRegression(intercept=1.5, slope=0.1) +LinearRegression(slope=0.1, intercept=1.5) Exceptions @@ -107,9 +107,12 @@ __all__ = [ 'NormalDist', 'StatisticsError', + 'correlation', + 'covariance', 'fmean', 'geometric_mean', 'harmonic_mean', + 'linear_regression', 'mean', 'median', 'median_grouped', @@ -122,9 +125,6 @@ 'quantiles', 'stdev', 'variance', - 'correlation', - 'covariance', - 'linear_regression', ] import math @@ -147,21 +147,17 @@ class StatisticsError(ValueError): # === Private utilities === -def _sum(data, start=0): - """_sum(data [, start]) -> (type, sum, count) +def _sum(data): + """_sum(data) -> (type, sum, count) Return a high-precision sum of the given numeric data as a fraction, together with the type to be converted to and the count of items. - If optional argument ``start`` is given, it is added to the total. - If ``data`` is empty, ``start`` (defaulting to 0) is returned. - - Examples -------- - >>> _sum([3, 2.25, 4.5, -0.5, 1.0], 0.75) - (, Fraction(11, 1), 5) + >>> _sum([3, 2.25, 4.5, -0.5, 0.25]) + (, Fraction(19, 2), 5) Some sources of round-off error will be avoided: @@ -184,10 +180,9 @@ def _sum(data, start=0): allowed. """ count = 0 - n, d = _exact_ratio(start) - partials = {d: n} + partials = {} partials_get = partials.get - T = _coerce(int, type(start)) + T = int for typ, values in groupby(data, type): T = _coerce(T, typ) # or raise TypeError for n, d in map(_exact_ratio, values): @@ -200,8 +195,7 @@ def _sum(data, start=0): assert not _isfinite(total) else: # Sum all the partial sums using builtin sum. - # FIXME is this faster if we sum them in order of the denominator? - total = sum(Fraction(n, d) for d, n in sorted(partials.items())) + total = sum(Fraction(n, d) for d, n in partials.items()) return (T, total, count) @@ -252,27 +246,19 @@ def _exact_ratio(x): x is expected to be an int, Fraction, Decimal or float. """ try: - # Optimise the common case of floats. We expect that the most often - # used numeric type will be builtin floats, so try to make this as - # fast as possible. - if type(x) is float or type(x) is Decimal: - return x.as_integer_ratio() - try: - # x may be an int, Fraction, or Integral ABC. - return (x.numerator, x.denominator) - except AttributeError: - try: - # x may be a float or Decimal subclass. - return x.as_integer_ratio() - except AttributeError: - # Just give up? - pass + return x.as_integer_ratio() + except AttributeError: + pass except (OverflowError, ValueError): # float NAN or INF. assert not _isfinite(x) return (x, None) - msg = "can't convert type '{}' to numerator/denominator" - raise TypeError(msg.format(type(x).__name__)) + try: + # x may be an Integral ABC. + return (x.numerator, x.denominator) + except AttributeError: + msg = f"can't convert type '{type(x).__name__}' to numerator/denominator" + raise TypeError(msg) def _convert(value, T): @@ -388,7 +374,7 @@ def geometric_mean(data): return exp(fmean(map(log, data))) except ValueError: raise StatisticsError('geometric mean requires a non-empty dataset ' - ' containing positive numbers') from None + 'containing positive numbers') from None def harmonic_mean(data, weights=None): @@ -719,14 +705,20 @@ def _ss(data, c=None): if c is not None: T, total, count = _sum((x-c)**2 for x in data) return (T, total) - c = mean(data) - T, total, count = _sum((x-c)**2 for x in data) - # The following sum should mathematically equal zero, but due to rounding - # error may not. - U, total2, count2 = _sum((x - c) for x in data) - assert T == U and count == count2 - total -= total2 ** 2 / len(data) - assert not total < 0, 'negative sum of square deviations: %f' % total + T, total, count = _sum(data) + mean_n, mean_d = (total / count).as_integer_ratio() + partials = Counter() + for n, d in map(_exact_ratio, data): + diff_n = n * mean_d - d * mean_n + diff_d = d * mean_d + partials[diff_d * diff_d] += diff_n * diff_n + if None in partials: + # The sum will be a NAN or INF. We can ignore all the finite + # partials, and just look at this special one. + total = partials[None] + assert not _isfinite(total) + else: + total = sum(Fraction(n, d) for d, n in partials.items()) return (T, total) @@ -830,6 +822,9 @@ def stdev(data, xbar=None): 1.0810874155219827 """ + # Fixme: Despite the exact sum of squared deviations, some inaccuracy + # remain because there are two rounding steps. The first occurs in + # the _convert() step for variance(), the second occurs in math.sqrt(). var = variance(data, xbar) try: return var.sqrt() @@ -846,6 +841,9 @@ def pstdev(data, mu=None): 0.986893273527251 """ + # Fixme: Despite the exact sum of squared deviations, some inaccuracy + # remain because there are two rounding steps. The first occurs in + # the _convert() step for pvariance(), the second occurs in math.sqrt(). var = pvariance(data, mu) try: return var.sqrt() @@ -882,10 +880,10 @@ def covariance(x, y, /): raise StatisticsError('covariance requires that both inputs have same number of data points') if n < 2: raise StatisticsError('covariance requires at least two data points') - xbar = mean(x) - ybar = mean(y) - total = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) - return total / (n - 1) + xbar = fsum(x) / n + ybar = fsum(y) / n + sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) + return sxy / (n - 1) def correlation(x, y, /): @@ -910,54 +908,60 @@ def correlation(x, y, /): raise StatisticsError('correlation requires that both inputs have same number of data points') if n < 2: raise StatisticsError('correlation requires at least two data points') - cov = covariance(x, y) - stdx = stdev(x) - stdy = stdev(y) + xbar = fsum(x) / n + ybar = fsum(y) / n + sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) + sxx = fsum((xi - xbar) ** 2.0 for xi in x) + syy = fsum((yi - ybar) ** 2.0 for yi in y) try: - return cov / (stdx * stdy) + return sxy / sqrt(sxx * syy) except ZeroDivisionError: raise StatisticsError('at least one of the inputs is constant') -LinearRegression = namedtuple('LinearRegression', ['intercept', 'slope']) +LinearRegression = namedtuple('LinearRegression', ('slope', 'intercept')) -def linear_regression(regressor, dependent_variable, /): - """Intercept and slope for simple linear regression +def linear_regression(x, y, /): + """Slope and intercept for simple linear regression. - Return the intercept and slope of simple linear regression + Return the slope and intercept of simple linear regression parameters estimated using ordinary least squares. Simple linear - regression describes relationship between *regressor* and - *dependent variable* in terms of linear function:: + regression describes relationship between an independent variable + *x* and a dependent variable *y* in terms of linear function: - dependent_variable = intercept + slope * regressor + noise + y = slope * x + intercept + noise - where ``intercept`` and ``slope`` are the regression parameters that are - estimated, and noise term is an unobserved random variable, for the - variability of the data that was not explained by the linear regression - (it is equal to the difference between prediction and the actual values - of dependent variable). + where *slope* and *intercept* are the regression parameters that are + estimated, and noise represents the variability of the data that was + not explained by the linear regression (it is equal to the + difference between predicted and actual values of the dependent + variable). The parameters are returned as a named tuple. - >>> regressor = [1, 2, 3, 4, 5] + >>> x = [1, 2, 3, 4, 5] >>> noise = NormalDist().samples(5, seed=42) - >>> dependent_variable = [2 + 3 * regressor[i] + noise[i] for i in range(5)] - >>> linear_regression(regressor, dependent_variable) #doctest: +ELLIPSIS - LinearRegression(intercept=1.75684970486..., slope=3.09078914170...) + >>> y = [3 * x[i] + 2 + noise[i] for i in range(5)] + >>> linear_regression(x, y) #doctest: +ELLIPSIS + LinearRegression(slope=3.09078914170..., intercept=1.75684970486...) """ - n = len(regressor) - if len(dependent_variable) != n: + n = len(x) + if len(y) != n: raise StatisticsError('linear regression requires that both inputs have same number of data points') if n < 2: raise StatisticsError('linear regression requires at least two data points') + xbar = fsum(x) / n + ybar = fsum(y) / n + sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) + sxx = fsum((xi - xbar) ** 2.0 for xi in x) try: - slope = covariance(regressor, dependent_variable) / variance(regressor) + slope = sxy / sxx # equivalent to: covariance(x, y) / variance(x) except ZeroDivisionError: - raise StatisticsError('regressor is constant') - intercept = mean(dependent_variable) - slope * mean(regressor) - return LinearRegression(intercept=intercept, slope=slope) + raise StatisticsError('x is constant') + intercept = ybar - slope * xbar + return LinearRegression(slope=slope, intercept=intercept) ## Normal Distribution ##################################################### diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 8203aded7d5529..ccb46a6337b3d9 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -660,8 +660,9 @@ def _use_posix_spawn(): # os.posix_spawn() is not available return False - if sys.platform == 'darwin': - # posix_spawn() is a syscall on macOS and properly reports errors + if sys.platform in ('darwin', 'sunos5'): + # posix_spawn() is a syscall on both macOS and Solaris, + # and properly reports errors return True # Check libc name and runtime libc version diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index e8869af0b5cc94..daf9f000060a35 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -101,7 +101,7 @@ def joinuser(*args): 'stdlib': '{userbase}/{platlibdir}/python{py_version_short}', 'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}', 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', - 'platlib': '{userbase}/{platlibdir}/python{py_version_short}/site-packages', + 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 'include': '{userbase}/include/python{py_version_short}', 'scripts': '{userbase}/bin', 'data': '{userbase}', @@ -111,7 +111,7 @@ def joinuser(*args): 'platstdlib': '{userbase}/lib/python', 'purelib': '{userbase}/lib/python/site-packages', 'platlib': '{userbase}/lib/python/site-packages', - 'include': '{userbase}/include', + 'include': '{userbase}/include/python{py_version_short}', 'scripts': '{userbase}/bin', 'data': '{userbase}', }, @@ -182,6 +182,18 @@ def is_python_build(check_home=False): _PYTHON_BUILD = is_python_build(True) +if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + # On POSIX-y platforms, Python will: + # - Build from .h files in 'headers' (which is only added to the + # scheme when building CPython) + # - Install .h files to 'include' + scheme = _INSTALL_SCHEMES[scheme] + scheme['headers'] = scheme['include'] + scheme['include'] = '{srcdir}/Include' + scheme['platinclude'] = '{projectbase}/.' + + def _subst_vars(s, local_vars): try: return s.format(**local_vars) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 18d415adf54418..c1ee1222e09b5a 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2349,6 +2349,15 @@ def next(self): raise ReadError(str(e)) from None except SubsequentHeaderError as e: raise ReadError(str(e)) from None + except Exception as e: + try: + import zlib + if isinstance(e, zlib.error): + raise ReadError(f'zlib error: {e}') from None + else: + raise e + except ImportError: + raise e break if tarinfo is not None: diff --git a/Lib/tempfile.py b/Lib/tempfile.py index efcf7a7fb3bbc1..7b6821240f2b4b 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -88,6 +88,10 @@ def _infer_return_type(*args): for arg in args: if arg is None: continue + + if isinstance(arg, _os.PathLike): + arg = _os.fspath(arg) + if isinstance(arg, bytes): if return_type is str: raise TypeError("Can't mix bytes and non-bytes in " diff --git a/Lib/test/_test_atexit.py b/Lib/test/_test_atexit.py index a31658531113ba..55d28083349175 100644 --- a/Lib/test/_test_atexit.py +++ b/Lib/test/_test_atexit.py @@ -116,6 +116,21 @@ def test_bound_methods(self): atexit._run_exitfuncs() self.assertEqual(l, [5]) + def test_atexit_with_unregistered_function(self): + # See bpo-46025 for more info + def func(): + atexit.unregister(func) + 1/0 + atexit.register(func) + try: + with support.catch_unraisable_exception() as cm: + atexit._run_exitfuncs() + self.assertEqual(cm.unraisable.object, func) + self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError) + self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError) + finally: + atexit.unregister(func) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index ead92cfa2abfea..3bc5b8f3d79b02 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -611,6 +611,7 @@ def test_lose_target_ref(self): del c p.start() p.join() + gc.collect() # For PyPy or other GCs. self.assertIs(wr(), None) self.assertEqual(q.get(), 5) close_queue(q) @@ -2286,6 +2287,16 @@ def test_dict_proxy_nested(self): self.assertIsInstance(outer[0], list) # Not a ListProxy self.assertEqual(outer[-1][-1]['feed'], 3) + def test_nested_queue(self): + a = self.list() # Test queue inside list + a.append(self.Queue()) + a[0].put(123) + self.assertEqual(a[0].get(), 123) + b = self.dict() # Test queue inside dict + b[0] = self.Queue() + b[0].put(456) + self.assertEqual(b[0].get(), 456) + def test_namespace(self): n = self.Namespace() n.name = 'Bob' @@ -2657,6 +2668,7 @@ def test_release_task_refs(self): self.pool.map(identity, objs) del objs + gc.collect() # For PyPy or other GCs. time.sleep(DELTA) # let threaded cleanup code run self.assertEqual(set(wr() for wr in refs), {None}) # With a process pool, copies of the objects are returned, check @@ -3761,12 +3773,19 @@ def _attach_existing_shmem_then_write(shmem_name_or_obj, binary_data): local_sms.buf[:len(binary_data)] = binary_data local_sms.close() + def _new_shm_name(self, prefix): + # Add a PID to the name of a POSIX shared memory object to allow + # running multiprocessing tests (test_multiprocessing_fork, + # test_multiprocessing_spawn, etc) in parallel. + return prefix + str(os.getpid()) + def test_shared_memory_basics(self): - sms = shared_memory.SharedMemory('test01_tsmb', create=True, size=512) + name_tsmb = self._new_shm_name('test01_tsmb') + sms = shared_memory.SharedMemory(name_tsmb, create=True, size=512) self.addCleanup(sms.unlink) # Verify attributes are readable. - self.assertEqual(sms.name, 'test01_tsmb') + self.assertEqual(sms.name, name_tsmb) self.assertGreaterEqual(sms.size, 512) self.assertGreaterEqual(len(sms.buf), sms.size) @@ -3774,25 +3793,17 @@ def test_shared_memory_basics(self): self.assertIn(sms.name, str(sms)) self.assertIn(str(sms.size), str(sms)) - # Test pickling - sms.buf[0:6] = b'pickle' - pickled_sms = pickle.dumps(sms) - sms2 = pickle.loads(pickled_sms) - self.assertEqual(sms.name, sms2.name) - self.assertEqual(sms.size, sms2.size) - self.assertEqual(bytes(sms.buf[0:6]), bytes(sms2.buf[0:6]), b'pickle') - # Modify contents of shared memory segment through memoryview. sms.buf[0] = 42 self.assertEqual(sms.buf[0], 42) # Attach to existing shared memory segment. - also_sms = shared_memory.SharedMemory('test01_tsmb') + also_sms = shared_memory.SharedMemory(name_tsmb) self.assertEqual(also_sms.buf[0], 42) also_sms.close() # Attach to existing shared memory segment but specify a new size. - same_sms = shared_memory.SharedMemory('test01_tsmb', size=20*sms.size) + same_sms = shared_memory.SharedMemory(name_tsmb, size=20*sms.size) self.assertLess(same_sms.size, 20*sms.size) # Size was ignored. same_sms.close() @@ -3810,7 +3821,7 @@ def test_shared_memory_basics(self): 'multiprocessing.shared_memory._make_filename') as mock_make_filename: NAME_PREFIX = shared_memory._SHM_NAME_PREFIX - names = ['test01_fn', 'test02_fn'] + names = [self._new_shm_name('test01_fn'), self._new_shm_name('test02_fn')] # Prepend NAME_PREFIX which can be '/psm_' or 'wnsm_', necessary # because some POSIX compliant systems require name to start with / names = [NAME_PREFIX + name for name in names] @@ -3832,17 +3843,17 @@ def test_shared_memory_basics(self): # manages unlinking on its own and unlink() does nothing). # True release of shared memory segment does not necessarily # happen until process exits, depending on the OS platform. + name_dblunlink = self._new_shm_name('test01_dblunlink') + sms_uno = shared_memory.SharedMemory( + name_dblunlink, + create=True, + size=5000 + ) with self.assertRaises(FileNotFoundError): - sms_uno = shared_memory.SharedMemory( - 'test01_dblunlink', - create=True, - size=5000 - ) - try: self.assertGreaterEqual(sms_uno.size, 5000) - sms_duo = shared_memory.SharedMemory('test01_dblunlink') + sms_duo = shared_memory.SharedMemory(name_dblunlink) sms_duo.unlink() # First shm_unlink() call. sms_duo.close() sms_uno.close() @@ -3854,7 +3865,7 @@ def test_shared_memory_basics(self): # Attempting to create a new shared memory segment with a # name that is already in use triggers an exception. there_can_only_be_one_sms = shared_memory.SharedMemory( - 'test01_tsmb', + name_tsmb, create=True, size=512 ) @@ -3868,7 +3879,7 @@ def test_shared_memory_basics(self): # case of MacOS/darwin, requesting a smaller size is disallowed. class OptionalAttachSharedMemory(shared_memory.SharedMemory): _flags = os.O_CREAT | os.O_RDWR - ok_if_exists_sms = OptionalAttachSharedMemory('test01_tsmb') + ok_if_exists_sms = OptionalAttachSharedMemory(name_tsmb) self.assertEqual(ok_if_exists_sms.size, sms.size) ok_if_exists_sms.close() @@ -3880,6 +3891,29 @@ class OptionalAttachSharedMemory(shared_memory.SharedMemory): sms.close() + def test_shared_memory_recreate(self): + # Test if shared memory segment is created properly, + # when _make_filename returns an existing shared memory segment name + with unittest.mock.patch( + 'multiprocessing.shared_memory._make_filename') as mock_make_filename: + + NAME_PREFIX = shared_memory._SHM_NAME_PREFIX + names = ['test01_fn', 'test02_fn'] + # Prepend NAME_PREFIX which can be '/psm_' or 'wnsm_', necessary + # because some POSIX compliant systems require name to start with / + names = [NAME_PREFIX + name for name in names] + + mock_make_filename.side_effect = names + shm1 = shared_memory.SharedMemory(create=True, size=1) + self.addCleanup(shm1.unlink) + self.assertEqual(shm1._name, names[0]) + + mock_make_filename.side_effect = names + shm2 = shared_memory.SharedMemory(create=True, size=1) + self.addCleanup(shm2.unlink) + self.assertEqual(shm2._name, names[1]) + + def test_invalid_shared_memory_cration(self): # Test creating a shared memory segment with negative size with self.assertRaises(ValueError): sms_invalid = shared_memory.SharedMemory(create=True, size=-1) @@ -3892,6 +3926,47 @@ class OptionalAttachSharedMemory(shared_memory.SharedMemory): with self.assertRaises(ValueError): sms_invalid = shared_memory.SharedMemory(create=True) + def test_shared_memory_pickle_unpickle(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + sms = shared_memory.SharedMemory(create=True, size=512) + self.addCleanup(sms.unlink) + sms.buf[0:6] = b'pickle' + + # Test pickling + pickled_sms = pickle.dumps(sms, protocol=proto) + + # Test unpickling + sms2 = pickle.loads(pickled_sms) + self.assertIsInstance(sms2, shared_memory.SharedMemory) + self.assertEqual(sms.name, sms2.name) + self.assertEqual(bytes(sms.buf[0:6]), b'pickle') + self.assertEqual(bytes(sms2.buf[0:6]), b'pickle') + + # Test that unpickled version is still the same SharedMemory + sms.buf[0:6] = b'newval' + self.assertEqual(bytes(sms.buf[0:6]), b'newval') + self.assertEqual(bytes(sms2.buf[0:6]), b'newval') + + sms2.buf[0:6] = b'oldval' + self.assertEqual(bytes(sms.buf[0:6]), b'oldval') + self.assertEqual(bytes(sms2.buf[0:6]), b'oldval') + + def test_shared_memory_pickle_unpickle_dead_object(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + sms = shared_memory.SharedMemory(create=True, size=512) + sms.buf[0:6] = b'pickle' + pickled_sms = pickle.dumps(sms, protocol=proto) + + # Now, we are going to kill the original object. + # So, unpickled one won't be able to attach to it. + sms.close() + sms.unlink() + + with self.assertRaises(FileNotFoundError): + pickle.loads(pickled_sms) + def test_shared_memory_across_processes(self): # bpo-40135: don't define shared memory block's name in case of # the failure when we run multiprocessing tests in parallel. @@ -4073,10 +4148,11 @@ def test_shared_memory_ShareableList_basics(self): self.assertEqual(sl.count(b'adios'), 0) # Exercise creating a duplicate. - sl_copy = shared_memory.ShareableList(sl, name='test03_duplicate') + name_duplicate = self._new_shm_name('test03_duplicate') + sl_copy = shared_memory.ShareableList(sl, name=name_duplicate) try: self.assertNotEqual(sl.shm.name, sl_copy.shm.name) - self.assertEqual('test03_duplicate', sl_copy.shm.name) + self.assertEqual(name_duplicate, sl_copy.shm.name) self.assertEqual(list(sl), list(sl_copy)) self.assertEqual(sl.format, sl_copy.format) sl_copy[-1] = 77 @@ -4108,29 +4184,45 @@ def test_shared_memory_ShareableList_basics(self): empty_sl.shm.unlink() def test_shared_memory_ShareableList_pickling(self): - sl = shared_memory.ShareableList(range(10)) - self.addCleanup(sl.shm.unlink) - - serialized_sl = pickle.dumps(sl) - deserialized_sl = pickle.loads(serialized_sl) - self.assertTrue( - isinstance(deserialized_sl, shared_memory.ShareableList) - ) - self.assertTrue(deserialized_sl[-1], 9) - self.assertFalse(sl is deserialized_sl) - deserialized_sl[4] = "changed" - self.assertEqual(sl[4], "changed") - - # Verify data is not being put into the pickled representation. - name = 'a' * len(sl.shm.name) - larger_sl = shared_memory.ShareableList(range(400)) - self.addCleanup(larger_sl.shm.unlink) - serialized_larger_sl = pickle.dumps(larger_sl) - self.assertTrue(len(serialized_sl) == len(serialized_larger_sl)) - larger_sl.shm.close() - - deserialized_sl.shm.close() - sl.shm.close() + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + sl = shared_memory.ShareableList(range(10)) + self.addCleanup(sl.shm.unlink) + + serialized_sl = pickle.dumps(sl, protocol=proto) + deserialized_sl = pickle.loads(serialized_sl) + self.assertIsInstance( + deserialized_sl, shared_memory.ShareableList) + self.assertEqual(deserialized_sl[-1], 9) + self.assertIsNot(sl, deserialized_sl) + + deserialized_sl[4] = "changed" + self.assertEqual(sl[4], "changed") + sl[3] = "newvalue" + self.assertEqual(deserialized_sl[3], "newvalue") + + larger_sl = shared_memory.ShareableList(range(400)) + self.addCleanup(larger_sl.shm.unlink) + serialized_larger_sl = pickle.dumps(larger_sl, protocol=proto) + self.assertEqual(len(serialized_sl), len(serialized_larger_sl)) + larger_sl.shm.close() + + deserialized_sl.shm.close() + sl.shm.close() + + def test_shared_memory_ShareableList_pickling_dead_object(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + sl = shared_memory.ShareableList(range(10)) + serialized_sl = pickle.dumps(sl, protocol=proto) + + # Now, we are going to kill the original object. + # So, unpickled one won't be able to attach to it. + sl.shm.close() + sl.shm.unlink() + + with self.assertRaises(FileNotFoundError): + pickle.loads(serialized_sl) def test_shared_memory_cleaned_after_process_termination(self): cmd = '''if 1: @@ -4167,6 +4259,13 @@ def test_shared_memory_cleaned_after_process_termination(self): " a process was abruptly terminated.") if os.name == 'posix': + # Without this line it was raising warnings like: + # UserWarning: resource_tracker: + # There appear to be 1 leaked shared_memory + # objects to clean up at shutdown + # See: https://bugs.python.org/issue45209 + resource_tracker.unregister(f"/{name}", "shared_memory") + # A warning was emitted by the subprocess' own # resource_tracker (on Windows, shared memory segments # are released automatically by the OS). @@ -4176,7 +4275,7 @@ def test_shared_memory_cleaned_after_process_termination(self): "shared_memory objects to clean up at shutdown", err) # -# +# Test to verify that `Finalize` works. # class _TestFinalize(BaseTestCase): @@ -4188,6 +4287,7 @@ def setUp(self): util._finalizer_registry.clear() def tearDown(self): + gc.collect() # For PyPy or other GCs. self.assertFalse(util._finalizer_registry) util._finalizer_registry.update(self.registry_backup) @@ -4199,12 +4299,14 @@ class Foo(object): a = Foo() util.Finalize(a, conn.send, args=('a',)) del a # triggers callback for a + gc.collect() # For PyPy or other GCs. b = Foo() close_b = util.Finalize(b, conn.send, args=('b',)) close_b() # triggers callback for b close_b() # does nothing because callback has already been called del b # does nothing because callback has already been called + gc.collect() # For PyPy or other GCs. c = Foo() util.Finalize(c, conn.send, args=('c',)) diff --git a/Lib/test/_typed_dict_helper.py b/Lib/test/_typed_dict_helper.py new file mode 100644 index 00000000000000..d333db193183eb --- /dev/null +++ b/Lib/test/_typed_dict_helper.py @@ -0,0 +1,18 @@ +"""Used to test `get_type_hints()` on a cross-module inherited `TypedDict` class + +This script uses future annotations to postpone a type that won't be available +on the module inheriting from to `Foo`. The subclass in the other module should +look something like this: + + class Bar(_typed_dict_helper.Foo, total=False): + b: int +""" + +from __future__ import annotations + +from typing import Optional, TypedDict + +OptionalIntType = Optional[int] + +class Foo(TypedDict): + a: OptionalIntType diff --git a/Lib/test/ann_module.py b/Lib/test/ann_module.py index 0567d6de1b6478..5081e6b58345a9 100644 --- a/Lib/test/ann_module.py +++ b/Lib/test/ann_module.py @@ -58,3 +58,5 @@ def dec(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper + +u: int | float diff --git a/Lib/test/ann_module5.py b/Lib/test/ann_module5.py new file mode 100644 index 00000000000000..837041e121f652 --- /dev/null +++ b/Lib/test/ann_module5.py @@ -0,0 +1,10 @@ +# Used by test_typing to verify that Final wrapped in ForwardRef works. + +from __future__ import annotations + +from typing import Final + +name: Final[str] = "final" + +class MyClass: + value: Final = 3000 diff --git a/Lib/test/ann_module6.py b/Lib/test/ann_module6.py new file mode 100644 index 00000000000000..679175669bc3ac --- /dev/null +++ b/Lib/test/ann_module6.py @@ -0,0 +1,7 @@ +# Tests that top-level ClassVar is not allowed + +from __future__ import annotations + +from typing import ClassVar + +wrong: ClassVar[int] = 1 diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index 7a7de637c38823..ccec9fedc4460d 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -6,6 +6,7 @@ """ import contextlib +import os import sys @@ -106,6 +107,32 @@ def test_block_add_hook_baseexception(): pass +def test_marshal(): + import marshal + o = ("a", "b", "c", 1, 2, 3) + payload = marshal.dumps(o) + + with TestHook() as hook: + assertEqual(o, marshal.loads(marshal.dumps(o))) + + try: + with open("test-marshal.bin", "wb") as f: + marshal.dump(o, f) + with open("test-marshal.bin", "rb") as f: + assertEqual(o, marshal.load(f)) + finally: + os.unlink("test-marshal.bin") + + actual = [(a[0], a[1]) for e, a in hook.seen if e == "marshal.dumps"] + assertSequenceEqual(actual, [(o, marshal.version)] * 2) + + actual = [a[0] for e, a in hook.seen if e == "marshal.loads"] + assertSequenceEqual(actual, [payload]) + + actual = [e for e, a in hook.seen if e == "marshal.load"] + assertSequenceEqual(actual, ["marshal.load"]) + + def test_pickle(): import pickle diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 316cf0b8da7b48..9f551d9b9748d3 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -344,7 +344,7 @@ def test_comparison(self): with self.assertRaises(TypeError): timezone(ZERO) < timezone(ZERO) self.assertIn(timezone(ZERO), {timezone(ZERO)}) self.assertTrue(timezone(ZERO) != None) - self.assertFalse(timezone(ZERO) == None) + self.assertFalse(timezone(ZERO) == None) tz = timezone(ZERO) self.assertTrue(tz == ALWAYS_EQ) @@ -4064,7 +4064,7 @@ def test_even_more_compare(self): self.assertEqual(t1, t1) self.assertEqual(t2, t2) - # Equal afer adjustment. + # Equal after adjustment. t1 = self.theclass(1, 12, 31, 23, 59, tzinfo=FixedOffset(1, "")) t2 = self.theclass(2, 1, 1, 3, 13, tzinfo=FixedOffset(3*60+13+2, "")) self.assertEqual(t1, t2) @@ -4903,7 +4903,7 @@ def test_easy(self): # OTOH, these fail! Don't enable them. The difficulty is that # the edge case tests assume that every hour is representable in # the "utc" class. This is always true for a fixed-offset tzinfo - # class (lke utc_real and utc_fake), but not for Eastern or Central. + # class (like utc_real and utc_fake), but not for Eastern or Central. # For these adjacent DST-aware time zones, the range of time offsets # tested ends up creating hours in the one that aren't representable # in the other. For the same reason, we would see failures in the diff --git a/Lib/test/decimaltestdata/abs.decTest b/Lib/test/decimaltestdata/abs.decTest index 01f73d7766648f..569b8fcd84ab62 100644 --- a/Lib/test/decimaltestdata/abs.decTest +++ b/Lib/test/decimaltestdata/abs.decTest @@ -20,7 +20,7 @@ version: 2.59 -- This set of tests primarily tests the existence of the operator. --- Additon, subtraction, rounding, and more overflows are tested +-- Addition, subtraction, rounding, and more overflows are tested -- elsewhere. precision: 9 diff --git a/Lib/test/decimaltestdata/extra.decTest b/Lib/test/decimaltestdata/extra.decTest index b630d8e3f9d45e..31291202a35e79 100644 --- a/Lib/test/decimaltestdata/extra.decTest +++ b/Lib/test/decimaltestdata/extra.decTest @@ -156,7 +156,7 @@ extr1302 fma -Inf 0E-456 sNaN148 -> NaN Invalid_operation -- max/min/max_mag/min_mag bug in 2.5.2/2.6/3.0: max(NaN, finite) gave -- incorrect answers when the finite number required rounding; similarly --- for the other thre functions +-- for the other three functions maxexponent: 999 minexponent: -999 precision: 6 diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py index a4bac79c8af680..29f4ede523b007 100644 --- a/Lib/test/libregrtest/cmdline.py +++ b/Lib/test/libregrtest/cmdline.py @@ -140,6 +140,39 @@ # default (see bpo-30822). RESOURCE_NAMES = ALL_RESOURCES + ('extralargefile', 'tzdata') + +class Namespace(argparse.Namespace): + def __init__(self, **kwargs) -> None: + self.testdir = None + self.verbose = 0 + self.quiet = False + self.exclude = False + self.single = False + self.randomize = False + self.fromfile = None + self.findleaks = 1 + self.fail_env_changed = False + self.use_resources = None + self.trace = False + self.coverdir = 'coverage' + self.runleaks = False + self.huntrleaks = False + self.verbose2 = False + self.verbose3 = False + self.print_slow = False + self.random_seed = None + self.use_mp = None + self.forever = False + self.header = False + self.failfast = False + self.match_tests = None + self.ignore_tests = None + self.pgo = False + self.pgo_extended = False + + super().__init__(**kwargs) + + class _ArgParser(argparse.ArgumentParser): def error(self, message): @@ -320,13 +353,7 @@ def resources_list(string): def _parse_args(args, **kwargs): # Defaults - ns = argparse.Namespace(testdir=None, verbose=0, quiet=False, - exclude=False, single=False, randomize=False, fromfile=None, - findleaks=1, use_resources=None, trace=False, coverdir='coverage', - runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, - random_seed=None, use_mp=None, verbose3=False, forever=False, - header=False, failfast=False, match_tests=None, ignore_tests=None, - pgo=False) + ns = Namespace() for k, v in kwargs.items(): if not hasattr(ns, k): raise TypeError('%r is an invalid keyword argument ' diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 1df927da403d6e..52cc065da115d9 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -11,10 +11,10 @@ import unittest from test.libregrtest.cmdline import _parse_args from test.libregrtest.runtest import ( - findtests, runtest, get_abs_module, - STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED, - INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, TIMEOUT, - PROGRESS_MIN_TIME, format_test_result, is_failed) + findtests, runtest, get_abs_module, is_failed, + STDTESTS, NOTTESTS, PROGRESS_MIN_TIME, + Passed, Failed, EnvChanged, Skipped, ResourceDenied, Interrupted, + ChildError, DidNotRun) from test.libregrtest.setup import setup_tests from test.libregrtest.pgo import setup_pgo_tests from test.libregrtest.utils import removepy, count, format_duration, printlist @@ -66,6 +66,7 @@ def __init__(self): self.resource_denieds = [] self.environment_changed = [] self.run_no_tests = [] + self.need_rerun = [] self.rerun = [] self.first_result = None self.interrupted = False @@ -99,34 +100,32 @@ def get_executed(self): | set(self.run_no_tests)) def accumulate_result(self, result, rerun=False): - test_name = result.test_name - ok = result.result + test_name = result.name - if ok not in (CHILD_ERROR, INTERRUPTED) and not rerun: - self.test_times.append((result.test_time, test_name)) + if not isinstance(result, (ChildError, Interrupted)) and not rerun: + self.test_times.append((result.duration_sec, test_name)) - if ok == PASSED: + if isinstance(result, Passed): self.good.append(test_name) - elif ok in (FAILED, CHILD_ERROR): - if not rerun: - self.bad.append(test_name) - elif ok == ENV_CHANGED: - self.environment_changed.append(test_name) - elif ok == SKIPPED: - self.skipped.append(test_name) - elif ok == RESOURCE_DENIED: + elif isinstance(result, ResourceDenied): self.skipped.append(test_name) self.resource_denieds.append(test_name) - elif ok == TEST_DID_NOT_RUN: + elif isinstance(result, Skipped): + self.skipped.append(test_name) + elif isinstance(result, EnvChanged): + self.environment_changed.append(test_name) + elif isinstance(result, Failed): + if not rerun: + self.bad.append(test_name) + self.need_rerun.append(result) + elif isinstance(result, DidNotRun): self.run_no_tests.append(test_name) - elif ok == INTERRUPTED: + elif isinstance(result, Interrupted): self.interrupted = True - elif ok == TIMEOUT: - self.bad.append(test_name) else: - raise ValueError("invalid test result: %r" % ok) + raise ValueError("invalid test result: %r" % result) - if rerun and ok not in {FAILED, CHILD_ERROR, INTERRUPTED}: + if rerun and not isinstance(result, (Failed, Interrupted)): self.bad.remove(test_name) xml_data = result.xml_data @@ -314,15 +313,33 @@ def rerun_failed_tests(self): self.log() self.log("Re-running failed tests in verbose mode") - self.rerun = self.bad[:] - for test_name in self.rerun: - self.log(f"Re-running {test_name} in verbose mode") + rerun_list = list(self.need_rerun) + self.need_rerun.clear() + for result in rerun_list: + test_name = result.name + self.rerun.append(test_name) + + errors = result.errors or [] + failures = result.failures or [] + error_names = [test_full_name.split(" ")[0] for (test_full_name, *_) in errors] + failure_names = [test_full_name.split(" ")[0] for (test_full_name, *_) in failures] self.ns.verbose = True + orig_match_tests = self.ns.match_tests + if errors or failures: + if self.ns.match_tests is None: + self.ns.match_tests = [] + self.ns.match_tests.extend(error_names) + self.ns.match_tests.extend(failure_names) + matching = "matching: " + ", ".join(self.ns.match_tests) + self.log(f"Re-running {test_name} in verbose mode ({matching})") + else: + self.log(f"Re-running {test_name} in verbose mode") result = runtest(self.ns, test_name) + self.ns.match_tests = orig_match_tests self.accumulate_result(result, rerun=True) - if result.result == INTERRUPTED: + if isinstance(result, Interrupted): break if self.bad: @@ -423,14 +440,14 @@ def run_tests_sequential(self): result = runtest(self.ns, test_name) self.accumulate_result(result) - if result.result == INTERRUPTED: + if isinstance(result, Interrupted): break - previous_test = format_test_result(result) + previous_test = str(result) test_time = time.monotonic() - start_time if test_time >= PROGRESS_MIN_TIME: previous_test = "%s in %s" % (previous_test, format_duration(test_time)) - elif result.result == PASSED: + elif isinstance(result, Passed): # be quiet: say nothing if the test passed shortly previous_test = None diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py index 7c7086a806b1cd..b56a84856d14fd 100644 --- a/Lib/test/libregrtest/refleak.py +++ b/Lib/test/libregrtest/refleak.py @@ -112,7 +112,7 @@ def get_pooled_int(value): # These checkers return False on success, True on failure def check_rc_deltas(deltas): - # Checker for reference counters and memomry blocks. + # Checker for reference counters and memory blocks. # # bpo-30776: Try to ignore false positives: # diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py index 927c4706629705..489ab986cb4e5e 100644 --- a/Lib/test/libregrtest/runtest.py +++ b/Lib/test/libregrtest/runtest.py @@ -1,4 +1,3 @@ -import collections import faulthandler import functools import gc @@ -12,33 +11,109 @@ from test import support from test.support import os_helper -from test.libregrtest.utils import clear_caches +from test.libregrtest.cmdline import Namespace from test.libregrtest.save_env import saved_test_environment -from test.libregrtest.utils import format_duration, print_warning - - -# Test result constants. -PASSED = 1 -FAILED = 0 -ENV_CHANGED = -1 -SKIPPED = -2 -RESOURCE_DENIED = -3 -INTERRUPTED = -4 -CHILD_ERROR = -5 # error in a child process -TEST_DID_NOT_RUN = -6 -TIMEOUT = -7 - -_FORMAT_TEST_RESULT = { - PASSED: '%s passed', - FAILED: '%s failed', - ENV_CHANGED: '%s failed (env changed)', - SKIPPED: '%s skipped', - RESOURCE_DENIED: '%s skipped (resource denied)', - INTERRUPTED: '%s interrupted', - CHILD_ERROR: '%s crashed', - TEST_DID_NOT_RUN: '%s run no tests', - TIMEOUT: '%s timed out', -} +from test.libregrtest.utils import clear_caches, format_duration, print_warning + + +class TestResult: + def __init__( + self, + name: str, + duration_sec: float = 0.0, + xml_data: list[str] | None = None, + ) -> None: + self.name = name + self.duration_sec = duration_sec + self.xml_data = xml_data + + def __str__(self) -> str: + return f"{self.name} finished" + + +class Passed(TestResult): + def __str__(self) -> str: + return f"{self.name} passed" + + +class Failed(TestResult): + def __init__( + self, + name: str, + duration_sec: float = 0.0, + xml_data: list[str] | None = None, + errors: list[tuple[str, str]] | None = None, + failures: list[tuple[str, str]] | None = None, + ) -> None: + super().__init__(name, duration_sec=duration_sec, xml_data=xml_data) + self.errors = errors + self.failures = failures + + def __str__(self) -> str: + if self.errors and self.failures: + le = len(self.errors) + lf = len(self.failures) + error_s = "error" + ("s" if le > 1 else "") + failure_s = "failure" + ("s" if lf > 1 else "") + return f"{self.name} failed ({le} {error_s}, {lf} {failure_s})" + + if self.errors: + le = len(self.errors) + error_s = "error" + ("s" if le > 1 else "") + return f"{self.name} failed ({le} {error_s})" + + if self.failures: + lf = len(self.failures) + failure_s = "failure" + ("s" if lf > 1 else "") + return f"{self.name} failed ({lf} {failure_s})" + + return f"{self.name} failed" + + +class UncaughtException(Failed): + def __str__(self) -> str: + return f"{self.name} failed (uncaught exception)" + + +class EnvChanged(Failed): + def __str__(self) -> str: + return f"{self.name} failed (env changed)" + + +class RefLeak(Failed): + def __str__(self) -> str: + return f"{self.name} failed (reference leak)" + + +class Skipped(TestResult): + def __str__(self) -> str: + return f"{self.name} skipped" + + +class ResourceDenied(Skipped): + def __str__(self) -> str: + return f"{self.name} skipped (resource denied)" + + +class Interrupted(TestResult): + def __str__(self) -> str: + return f"{self.name} interrupted" + + +class ChildError(Failed): + def __str__(self) -> str: + return f"{self.name} crashed" + + +class DidNotRun(TestResult): + def __str__(self) -> str: + return f"{self.name} ran no tests" + + +class Timeout(Failed): + def __str__(self) -> str: + return f"{self.name} timed out ({format_duration(self.duration_sec)})" + # Minimum duration of a test to display its duration or to mention that # the test is running in background @@ -67,21 +142,10 @@ FOUND_GARBAGE = [] -def is_failed(result, ns): - ok = result.result - if ok in (PASSED, RESOURCE_DENIED, SKIPPED, TEST_DID_NOT_RUN): - return False - if ok == ENV_CHANGED: +def is_failed(result: TestResult, ns: Namespace) -> bool: + if isinstance(result, EnvChanged): return ns.fail_env_changed - return True - - -def format_test_result(result): - fmt = _FORMAT_TEST_RESULT.get(result.result, "%s") - text = fmt % result.test_name - if result.result == TIMEOUT: - text = '%s (%s)' % (text, format_duration(result.test_time)) - return text + return isinstance(result, Failed) def findtestdir(path=None): @@ -101,7 +165,7 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): return stdtests + sorted(tests) -def get_abs_module(ns, test_name): +def get_abs_module(ns: Namespace, test_name: str) -> str: if test_name.startswith('test.') or ns.testdir: return test_name else: @@ -109,10 +173,7 @@ def get_abs_module(ns, test_name): return 'test.' + test_name -TestResult = collections.namedtuple('TestResult', - 'test_name result test_time xml_data') - -def _runtest(ns, test_name): +def _runtest(ns: Namespace, test_name: str) -> TestResult: # Handle faulthandler timeout, capture stdout+stderr, XML serialization # and measure time. @@ -140,7 +201,7 @@ def _runtest(ns, test_name): sys.stderr = stream result = _runtest_inner(ns, test_name, display_failure=False) - if result != PASSED: + if not isinstance(result, Passed): output = stream.getvalue() orig_stderr.write(output) orig_stderr.flush() @@ -156,36 +217,26 @@ def _runtest(ns, test_name): if xml_list: import xml.etree.ElementTree as ET - xml_data = [ET.tostring(x).decode('us-ascii') for x in xml_list] - else: - xml_data = None - - test_time = time.perf_counter() - start_time + result.xml_data = [ + ET.tostring(x).decode('us-ascii') + for x in xml_list + ] - return TestResult(test_name, result, test_time, xml_data) + result.duration_sec = time.perf_counter() - start_time + return result finally: if use_timeout: faulthandler.cancel_dump_traceback_later() support.junit_xml_list = None -def runtest(ns, test_name): +def runtest(ns: Namespace, test_name: str) -> TestResult: """Run a single test. ns -- regrtest namespace of options test_name -- the name of the test - Returns the tuple (result, test_time, xml_data), where result is one - of the constants: - - INTERRUPTED KeyboardInterrupt - RESOURCE_DENIED test skipped because resource denied - SKIPPED test skipped for some other reason - ENV_CHANGED test failed because it changed the execution environment - FAILED test failed - PASSED test passed - EMPTY_TEST_SUITE test ran no subtests. - TIMEOUT test timed out. + Returns a TestResult sub-class depending on the kind of result received. If ns.xmlpath is not None, xml_data is a list containing each generated testsuite element. @@ -197,7 +248,7 @@ def runtest(ns, test_name): msg = traceback.format_exc() print(f"test {test_name} crashed -- {msg}", file=sys.stderr, flush=True) - return TestResult(test_name, FAILED, 0.0, None) + return Failed(test_name) def _test_module(the_module): @@ -210,11 +261,11 @@ def _test_module(the_module): support.run_unittest(tests) -def save_env(ns, test_name): +def save_env(ns: Namespace, test_name: str): return saved_test_environment(test_name, ns.verbose, ns.quiet, pgo=ns.pgo) -def _runtest_inner2(ns, test_name): +def _runtest_inner2(ns: Namespace, test_name: str) -> bool: # Load the test function, run the test function, handle huntrleaks # and findleaks to detect leaks @@ -265,7 +316,9 @@ def _runtest_inner2(ns, test_name): return refleak -def _runtest_inner(ns, test_name, display_failure=True): +def _runtest_inner( + ns: Namespace, test_name: str, display_failure: bool = True +) -> TestResult: # Detect environment changes, handle exceptions. # Reset the environment_altered flag to detect if a test altered @@ -283,37 +336,43 @@ def _runtest_inner(ns, test_name, display_failure=True): except support.ResourceDenied as msg: if not ns.quiet and not ns.pgo: print(f"{test_name} skipped -- {msg}", flush=True) - return RESOURCE_DENIED + return ResourceDenied(test_name) except unittest.SkipTest as msg: if not ns.quiet and not ns.pgo: print(f"{test_name} skipped -- {msg}", flush=True) - return SKIPPED + return Skipped(test_name) + except support.TestFailedWithDetails as exc: + msg = f"test {test_name} failed" + if display_failure: + msg = f"{msg} -- {exc}" + print(msg, file=sys.stderr, flush=True) + return Failed(test_name, errors=exc.errors, failures=exc.failures) except support.TestFailed as exc: msg = f"test {test_name} failed" if display_failure: msg = f"{msg} -- {exc}" print(msg, file=sys.stderr, flush=True) - return FAILED + return Failed(test_name) except support.TestDidNotRun: - return TEST_DID_NOT_RUN + return DidNotRun(test_name) except KeyboardInterrupt: print() - return INTERRUPTED + return Interrupted(test_name) except: if not ns.pgo: msg = traceback.format_exc() print(f"test {test_name} crashed -- {msg}", file=sys.stderr, flush=True) - return FAILED + return UncaughtException(test_name) if refleak: - return FAILED + return RefLeak(test_name) if support.environment_altered: - return ENV_CHANGED - return PASSED + return EnvChanged(test_name) + return Passed(test_name) -def cleanup_test_droppings(test_name, verbose): +def cleanup_test_droppings(test_name: str, verbose: int) -> None: # First kill any dangling references to open files etc. # This can also issue some ResourceWarnings which would otherwise get # triggered during the following test run, and possibly produce failures. diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 3d503af23b6a76..d0d63ef8afe91a 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -9,13 +9,15 @@ import threading import time import traceback -import types +from typing import NamedTuple, NoReturn, Literal, Any + from test import support from test.support import os_helper +from test.libregrtest.cmdline import Namespace +from test.libregrtest.main import Regrtest from test.libregrtest.runtest import ( - runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, - format_test_result, TestResult, is_failed, TIMEOUT) + runtest, is_failed, TestResult, Interrupted, Timeout, ChildError, PROGRESS_MIN_TIME) from test.libregrtest.setup import setup_tests from test.libregrtest.utils import format_duration, print_warning @@ -36,21 +38,21 @@ USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg")) -def must_stop(result, ns): - if result.result == INTERRUPTED: +def must_stop(result: TestResult, ns: Namespace) -> bool: + if isinstance(result, Interrupted): return True if ns.failfast and is_failed(result, ns): return True return False -def parse_worker_args(worker_args): +def parse_worker_args(worker_args) -> tuple[Namespace, str]: ns_dict, test_name = json.loads(worker_args) - ns = types.SimpleNamespace(**ns_dict) + ns = Namespace(**ns_dict) return (ns, test_name) -def run_test_in_subprocess(testname, ns): +def run_test_in_subprocess(testname: str, ns: Namespace) -> subprocess.Popen: ns_dict = vars(ns) worker_args = (ns_dict, testname) worker_args = json.dumps(worker_args) @@ -75,15 +77,15 @@ def run_test_in_subprocess(testname, ns): **kw) -def run_tests_worker(ns, test_name): +def run_tests_worker(ns: Namespace, test_name: str) -> NoReturn: setup_tests(ns) result = runtest(ns, test_name) print() # Force a newline (just in case) - # Serialize TestResult as list in JSON - print(json.dumps(list(result)), flush=True) + # Serialize TestResult as dict in JSON + print(json.dumps(result, cls=EncodeTestResult), flush=True) sys.exit(0) @@ -110,15 +112,23 @@ def stop(self): self.tests_iter = None -MultiprocessResult = collections.namedtuple('MultiprocessResult', - 'result stdout stderr error_msg') +class MultiprocessResult(NamedTuple): + result: TestResult + stdout: str + stderr: str + error_msg: str + + +ExcStr = str +QueueOutput = tuple[Literal[False], MultiprocessResult] | tuple[Literal[True], ExcStr] + class ExitThread(Exception): pass class TestWorkerProcess(threading.Thread): - def __init__(self, worker_id, runner): + def __init__(self, worker_id: int, runner: "MultiprocessTestRunner") -> None: super().__init__() self.worker_id = worker_id self.pending = runner.pending @@ -132,7 +142,7 @@ def __init__(self, worker_id, runner): self._killed = False self._stopped = False - def __repr__(self): + def __repr__(self) -> str: info = [f'TestWorkerProcess #{self.worker_id}'] if self.is_alive(): info.append("running") @@ -148,7 +158,7 @@ def __repr__(self): f'time={format_duration(dt)}')) return '<%s>' % ' '.join(info) - def _kill(self): + def _kill(self) -> None: popen = self._popen if popen is None: return @@ -176,18 +186,22 @@ def _kill(self): except OSError as exc: print_warning(f"Failed to kill {what}: {exc!r}") - def stop(self): + def stop(self) -> None: # Method called from a different thread to stop this thread self._stopped = True self._kill() - def mp_result_error(self, test_name, error_type, stdout='', stderr='', - err_msg=None): - test_time = time.monotonic() - self.start_time - result = TestResult(test_name, error_type, test_time, None) - return MultiprocessResult(result, stdout, stderr, err_msg) - - def _run_process(self, test_name): + def mp_result_error( + self, + test_result: TestResult, + stdout: str = '', + stderr: str = '', + err_msg=None + ) -> MultiprocessResult: + test_result.duration_sec = time.monotonic() - self.start_time + return MultiprocessResult(test_result, stdout, stderr, err_msg) + + def _run_process(self, test_name: str) -> tuple[int, str, str]: self.start_time = time.monotonic() self.current_test_name = test_name @@ -246,11 +260,11 @@ def _run_process(self, test_name): self._popen = None self.current_test_name = None - def _runtest(self, test_name): + def _runtest(self, test_name: str) -> MultiprocessResult: retcode, stdout, stderr = self._run_process(test_name) if retcode is None: - return self.mp_result_error(test_name, TIMEOUT, stdout, stderr) + return self.mp_result_error(Timeout(test_name), stdout, stderr) err_msg = None if retcode != 0: @@ -263,18 +277,17 @@ def _runtest(self, test_name): else: try: # deserialize run_tests_worker() output - result = json.loads(result) - result = TestResult(*result) + result = json.loads(result, object_hook=decode_test_result) except Exception as exc: err_msg = "Failed to parse worker JSON: %s" % exc if err_msg is not None: - return self.mp_result_error(test_name, CHILD_ERROR, + return self.mp_result_error(ChildError(test_name), stdout, stderr, err_msg) return MultiprocessResult(result, stdout, stderr, err_msg) - def run(self): + def run(self) -> None: while not self._stopped: try: try: @@ -293,7 +306,7 @@ def run(self): self.output.put((True, traceback.format_exc())) break - def _wait_completed(self): + def _wait_completed(self) -> None: popen = self._popen # stdout and stderr must be closed to ensure that communicate() @@ -308,7 +321,7 @@ def _wait_completed(self): f"(timeout={format_duration(JOIN_TIMEOUT)}): " f"{exc!r}") - def wait_stopped(self, start_time): + def wait_stopped(self, start_time: float) -> None: # bpo-38207: MultiprocessTestRunner.stop_workers() called self.stop() # which killed the process. Sometimes, killing the process from the # main thread does not interrupt popen.communicate() in @@ -332,7 +345,7 @@ def wait_stopped(self, start_time): break -def get_running(workers): +def get_running(workers: list[TestWorkerProcess]) -> list[TestWorkerProcess]: running = [] for worker in workers: current_test_name = worker.current_test_name @@ -346,11 +359,11 @@ def get_running(workers): class MultiprocessTestRunner: - def __init__(self, regrtest): + def __init__(self, regrtest: Regrtest) -> None: self.regrtest = regrtest self.log = self.regrtest.log self.ns = regrtest.ns - self.output = queue.Queue() + self.output: queue.Queue[QueueOutput] = queue.Queue() self.pending = MultiprocessIterator(self.regrtest.tests) if self.ns.timeout is not None: # Rely on faulthandler to kill a worker process. This timouet is @@ -362,7 +375,7 @@ def __init__(self, regrtest): self.worker_timeout = None self.workers = None - def start_workers(self): + def start_workers(self) -> None: self.workers = [TestWorkerProcess(index, self) for index in range(1, self.ns.use_mp + 1)] msg = f"Run tests in parallel using {len(self.workers)} child processes" @@ -374,24 +387,20 @@ def start_workers(self): for worker in self.workers: worker.start() - def stop_workers(self): + def stop_workers(self) -> None: start_time = time.monotonic() for worker in self.workers: worker.stop() for worker in self.workers: worker.wait_stopped(start_time) - def _get_result(self): - if not any(worker.is_alive() for worker in self.workers): - # all worker threads are done: consume pending results - try: - return self.output.get(timeout=0) - except queue.Empty: - return None - + def _get_result(self) -> QueueOutput | None: use_faulthandler = (self.ns.timeout is not None) timeout = PROGRESS_UPDATE - while True: + + # bpo-46205: check the status of workers every iteration to avoid + # waiting forever on an empty queue. + while any(worker.is_alive() for worker in self.workers): if use_faulthandler: faulthandler.dump_traceback_later(MAIN_PROCESS_TIMEOUT, exit=True) @@ -407,21 +416,28 @@ def _get_result(self): if running and not self.ns.pgo: self.log('running: %s' % ', '.join(running)) - def display_result(self, mp_result): + # all worker threads are done: consume pending results + try: + return self.output.get(timeout=0) + except queue.Empty: + return None + + def display_result(self, mp_result: MultiprocessResult) -> None: result = mp_result.result - text = format_test_result(result) + text = str(result) if mp_result.error_msg is not None: # CHILD_ERROR text += ' (%s)' % mp_result.error_msg - elif (result.test_time >= PROGRESS_MIN_TIME and not self.ns.pgo): - text += ' (%s)' % format_duration(result.test_time) + elif (result.duration_sec >= PROGRESS_MIN_TIME and not self.ns.pgo): + text += ' (%s)' % format_duration(result.duration_sec) running = get_running(self.workers) if running and not self.ns.pgo: text += ' -- running: %s' % ', '.join(running) self.regrtest.display_progress(self.test_index, text) - def _process_result(self, item): + def _process_result(self, item: QueueOutput) -> bool: + """Returns True if test runner must stop.""" if item[0]: # Thread got an exception format_exc = item[1] @@ -443,7 +459,7 @@ def _process_result(self, item): return False - def run_tests(self): + def run_tests(self) -> None: self.start_workers() self.test_index = 0 @@ -469,5 +485,41 @@ def run_tests(self): self.stop_workers() -def run_tests_multiprocess(regrtest): +def run_tests_multiprocess(regrtest: Regrtest) -> None: MultiprocessTestRunner(regrtest).run_tests() + + +class EncodeTestResult(json.JSONEncoder): + """Encode a TestResult (sub)class object into a JSON dict.""" + + def default(self, o: Any) -> dict[str, Any]: + if isinstance(o, TestResult): + result = vars(o) + result["__test_result__"] = o.__class__.__name__ + return result + + return super().default(o) + + +def decode_test_result(d: dict[str, Any]) -> TestResult | dict[str, Any]: + """Decode a TestResult (sub)class object from a JSON dict.""" + + if "__test_result__" not in d: + return d + + cls_name = d.pop("__test_result__") + for cls in get_all_test_result_classes(): + if cls.__name__ == cls_name: + return cls(**d) + + +def get_all_test_result_classes() -> set[type[TestResult]]: + prev_count = 0 + classes = {TestResult} + while len(classes) > prev_count: + prev_count = len(classes) + to_add = [] + for cls in classes: + to_add.extend(cls.__subclasses__()) + classes.update(to_add) + return classes diff --git a/Lib/test/libregrtest/setup.py b/Lib/test/libregrtest/setup.py index 83ce2f73f4e5a6..b79175944d2bdf 100644 --- a/Lib/test/libregrtest/setup.py +++ b/Lib/test/libregrtest/setup.py @@ -14,6 +14,9 @@ setup_threading_excepthook) +UNICODE_GUARD_ENV = "PYTHONREGRTEST_UNICODE_GUARD" + + def setup_tests(ns): try: stderr_fd = sys.__stderr__.fileno() @@ -36,6 +39,7 @@ def setup_tests(ns): for signum in signals: faulthandler.register(signum, chain=True, file=stderr_fd) + _adjust_resource_limits() replace_stdout() support.record_original_stdout(sys.stdout) @@ -99,6 +103,13 @@ def _test_audit_hook(name, args): from test.support.testresult import RegressionTestResult RegressionTestResult.USE_XML = True + # Ensure there's a non-ASCII character in env vars at all times to force + # tests consider this case. See BPO-44647 for details. + os.environ.setdefault( + UNICODE_GUARD_ENV, + "\N{SMILING FACE WITH SUNGLASSES}", + ) + def replace_stdout(): """Set stdout encoder error handler to backslashreplace (as stderr error @@ -124,3 +135,26 @@ def restore_stdout(): sys.stdout.close() sys.stdout = stdout atexit.register(restore_stdout) + + +def _adjust_resource_limits(): + """Adjust the system resource limits (ulimit) if needed.""" + try: + import resource + from resource import RLIMIT_NOFILE, RLIM_INFINITY + except ImportError: + return + fd_limit, max_fds = resource.getrlimit(RLIMIT_NOFILE) + # On macOS the default fd limit is sometimes too low (256) for our + # test suite to succeed. Raise it to something more reasonable. + # 1024 is a common Linux default. + desired_fds = 1024 + if fd_limit < desired_fds and fd_limit < max_fds: + new_fd_limit = min(desired_fds, max_fds) + try: + resource.setrlimit(RLIMIT_NOFILE, (new_fd_limit, max_fds)) + print(f"Raised RLIMIT_NOFILE: {fd_limit} -> {new_fd_limit}") + except (ValueError, OSError) as err: + print(f"Unable to raise RLIMIT_NOFILE from {fd_limit} to " + f"{new_fd_limit}: {err}.") + diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index d69bcc9496843f..dffb7d4418dfe6 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -3,6 +3,7 @@ """ import os +import gc import sys import time from _thread import start_new_thread, TIMEOUT_MAX @@ -221,6 +222,7 @@ def test_weakref_deleted(self): lock = self.locktype() ref = weakref.ref(lock) del lock + gc.collect() # For PyPy or other GCs. self.assertIsNone(ref()) diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py index c62896f861dab6..94a35a64ab1abe 100644 --- a/Lib/test/make_ssl_certs.py +++ b/Lib/test/make_ssl_certs.py @@ -307,6 +307,6 @@ def print_cert(path): f.write(cert) unmake_ca() - print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/util.py") + print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py") print_cert('keycert.pem') print_cert('keycert3.pem') diff --git a/Lib/test/mime.types b/Lib/test/mime.types index 68724430c8a3fd..eb39a17b6bf4b2 100644 --- a/Lib/test/mime.types +++ b/Lib/test/mime.types @@ -1,11 +1,11 @@ # This is a comment. I love comments. -*- indent-tabs-mode: t -*- -# This file controls what Internet media types are sent to the client for +# This file controls what internet media types are sent to the client for # given file extension(s). Sending the correct media type to the client # is important so they know how to handle the content of the file. # Extra types can either be added here or by using an AddType directive -# in your config files. For more information about Internet media types, -# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type +# in your config files. For more information about internet media types, +# please read RFC 2045, 2046, 2047, 2048, and 2077. The internet media type # registry is at . # IANA types diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 8e01d311360e35..f13d42f664880b 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -828,7 +828,7 @@ def create_data(): return x -class AbstractUnpickleTests(unittest.TestCase): +class AbstractUnpickleTests: # Subclass must define self.loads. _testdata = create_data() @@ -1441,7 +1441,7 @@ def t(): -class AbstractPickleTests(unittest.TestCase): +class AbstractPickleTests: # Subclass must define self.dumps, self.loads. optimized = False @@ -2383,7 +2383,8 @@ def test_bad_getattr(self): # Issue #3514: crash when there is an infinite loop in __getattr__ x = BadGetattr() for proto in protocols: - self.assertRaises(RuntimeError, self.dumps, x, proto) + with support.infinite_recursion(): + self.assertRaises(RuntimeError, self.dumps, x, proto) def test_reduce_bad_iterator(self): # Issue4176: crash when 4th and 5th items of __reduce__() @@ -3032,7 +3033,7 @@ def check_array(arr): check_array(arr[::2]) -class BigmemPickleTests(unittest.TestCase): +class BigmemPickleTests: # Binary protocols can serialize longs of up to 2 GiB-1 @@ -3305,7 +3306,7 @@ def __getattr__(self, key): self.foo -class AbstractPickleModuleTests(unittest.TestCase): +class AbstractPickleModuleTests: def test_dump_closed_file(self): f = open(TESTFN, "wb") @@ -3412,7 +3413,7 @@ def loads(data, **kwargs): self.check_dumps_loads_oob_buffers(dumps, loads) -class AbstractPersistentPicklerTests(unittest.TestCase): +class AbstractPersistentPicklerTests: # This class defines persistent_id() and persistent_load() # functions that should be used by the pickler. All even integers @@ -3452,7 +3453,7 @@ def test_persistence(self): self.assertEqual(self.load_false_count, 1) -class AbstractIdentityPersistentPicklerTests(unittest.TestCase): +class AbstractIdentityPersistentPicklerTests: def persistent_id(self, obj): return obj @@ -3481,7 +3482,7 @@ def test_protocol0_is_ascii_only(self): self.assertRaises(pickle.UnpicklingError, self.loads, pickled) -class AbstractPicklerUnpicklerObjectTests(unittest.TestCase): +class AbstractPicklerUnpicklerObjectTests: pickler_class = None unpickler_class = None @@ -3695,7 +3696,7 @@ def reducer_override(self, obj): return NotImplemented -class AbstractHookTests(unittest.TestCase): +class AbstractHookTests: def test_pickler_hook(self): # test the ability of a custom, user-defined CPickler subclass to # override the default reducing routines of any type using the method @@ -3723,7 +3724,7 @@ class MyClass: self.assertEqual(new_f, 5) self.assertEqual(some_str, 'some str') - # math.log does not have its usual reducer overriden, so the + # math.log does not have its usual reducer overridden, so the # custom reduction callback should silently direct the pickler # to the default pickling by attribute, by returning # NotImplemented @@ -3740,7 +3741,7 @@ class MyClass: def test_reducer_override_no_reference_cycle(self): # bpo-39492: reducer_override used to induce a spurious reference cycle # inside the Pickler object, that could prevent all serialized objects - # from being garbage-collected without explicity invoking gc.collect. + # from being garbage-collected without explicitly invoking gc.collect. for proto in range(0, pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): @@ -3761,7 +3762,7 @@ def f(): self.assertIsNone(wr()) -class AbstractDispatchTableTests(unittest.TestCase): +class AbstractDispatchTableTests: def test_default_dispatch_table(self): # No dispatch_table attribute by default diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 278dfe7f7da7ac..39ee9e1d769f8d 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -96,6 +96,7 @@ def collect_sys(info_add): 'maxunicode', 'path', 'platform', + 'platlibdir', 'prefix', 'thread_info', 'version', diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 80f3a04fcc6180..44c5bd5820a75e 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -13,6 +13,7 @@ import time import types import unittest +import warnings from .testresult import get_test_runner @@ -40,6 +41,7 @@ "requires_IEEE_754", "requires_zlib", "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "skip_if_buggy_ucrt_strfptime", + "check_disallow_instantiation", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", "setswitchinterval", @@ -73,8 +75,8 @@ elif sys.platform == 'vxworks': LOOPBACK_TIMEOUT = 10 -# Timeout in seconds for network requests going to the Internet. The timeout is -# short enough to prevent a test to wait for too long if the Internet request +# Timeout in seconds for network requests going to the internet. The timeout is +# short enough to prevent a test to wait for too long if the internet request # is blocked for whatever reason. # # Usually, a timeout using INTERNET_TIMEOUT should not mark a test as failed, @@ -104,6 +106,17 @@ class Error(Exception): class TestFailed(Error): """Test failed.""" +class TestFailedWithDetails(TestFailed): + """Test failed.""" + def __init__(self, msg, errors, failures): + self.msg = msg + self.errors = errors + self.failures = failures + super().__init__(msg, errors, failures) + + def __str__(self): + return self.msg + class TestDidNotRun(Error): """Test did not run any subtests.""" @@ -377,8 +390,8 @@ def dec(*args, **kwargs): # A constant likely larger than the underlying OS socket buffer size, to make # writes blocking. # The socket buffer sizes can usually be tuned system-wide (e.g. through sysctl -# on Linux), or on a per-socket basis (SO_SNDBUF/SO_RCVBUF). See issue #18643 -# for a discussion of this number). +# on Linux), or on a per-socket basis (SO_SNDBUF/SO_RCVBUF). See issue #18643 +# for a discussion of this number. SOCK_MAX_SIZE = 16 * 1024 * 1024 + 1 # decorator for skipping tests on non-IEEE 754 platforms @@ -447,6 +460,24 @@ def requires_lzma(reason='requires lzma'): TEST_DATA_DIR = os.path.join(TEST_HOME_DIR, "data") +def darwin_malloc_err_warning(test_name): + """Assure user that loud errors generated by macOS libc's malloc are + expected.""" + if sys.platform != 'darwin': + return + + import shutil + msg = ' NOTICE ' + detail = (f'{test_name} may generate "malloc can\'t allocate region"\n' + 'warnings on macOS systems. This behavior is known. Do not\n' + 'report a bug unless tests are also failing. See bpo-40928.') + + padding, _ = shutil.get_terminal_size() + print(msg.center(padding, '-')) + print(detail) + print('-' * padding) + + def findfile(filename, subdir=None): """Try to find a file on sys.path or in the test directory. If it is not found the argument passed to the function is returned (this does not @@ -656,9 +687,8 @@ def check_sizeof(test, o, size): # Decorator for running a function in a different locale, correctly resetting # it afterwards. +@contextlib.contextmanager def run_with_locale(catstr, *locales): - def decorator(func): - def inner(*args, **kwds): try: import locale category = getattr(locale, catstr) @@ -677,16 +707,11 @@ def inner(*args, **kwds): except: pass - # now run the function, resetting the locale on exceptions try: - return func(*args, **kwds) + yield finally: if locale and orig_locale: locale.setlocale(category, orig_locale) - inner.__name__ = func.__name__ - inner.__doc__ = func.__doc__ - return inner - return decorator #======================================================================= # Decorator for running a function in a specific timezone, correctly @@ -971,7 +996,9 @@ def _run_suite(suite): else: err = "multiple errors occurred" if not verbose: err += "; run in verbose mode for details" - raise TestFailed(err) + errors = [(str(tc), exc_str) for tc, exc_str in result.errors] + failures = [(str(tc), exc_str) for tc, exc_str in result.failures] + raise TestFailedWithDetails(err, errors, failures) # By default, don't filter tests @@ -1982,3 +2009,60 @@ def skip_if_broken_multiprocessing_synchronize(): synchronize.Lock(ctx=None) except OSError as exc: raise unittest.SkipTest(f"broken multiprocessing SemLock: {exc!r}") + + +@contextlib.contextmanager +def infinite_recursion(max_depth=75): + original_depth = sys.getrecursionlimit() + try: + sys.setrecursionlimit(max_depth) + yield + finally: + sys.setrecursionlimit(original_depth) + + +def check_disallow_instantiation(testcase, tp, *args, **kwds): + """ + Check that given type cannot be instantiated using *args and **kwds. + + See bpo-43916: Add Py_TPFLAGS_DISALLOW_INSTANTIATION type flag. + """ + mod = tp.__module__ + name = tp.__name__ + if mod != 'builtins': + qualname = f"{mod}.{name}" + else: + qualname = f"{name}" + msg = f"cannot create '{re.escape(qualname)}' instances" + testcase.assertRaisesRegex(TypeError, msg, tp, *args, **kwds) + + +def ignore_deprecations_from(module: str, *, like: str) -> object: + token = object() + warnings.filterwarnings( + "ignore", + category=DeprecationWarning, + module=module, + message=like + fr"(?#support{id(token)})", + ) + return token + + +def clear_ignored_deprecations(*tokens: object) -> None: + if not tokens: + raise ValueError("Provide token or tokens returned by ignore_deprecations_from") + + new_filters = [] + endswith = tuple(rf"(?#support{id(token)})" for token in tokens) + for action, message, category, module, lineno in warnings.filters: + if action == "ignore" and category is DeprecationWarning: + if isinstance(message, re.Pattern): + msg = message.pattern + else: + msg = message or "" + if msg.endswith(endswith): + continue + new_filters.append((action, message, category, module, lineno)) + if warnings.filters != new_filters: + warnings.filters[:] = new_filters + warnings._filters_mutated() diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py index a28132a565a0b5..a4e6c92203ab50 100644 --- a/Lib/test/support/hashlib_helper.py +++ b/Lib/test/support/hashlib_helper.py @@ -21,8 +21,21 @@ def requires_hashdigest(digestname, openssl=None, usedforsecurity=True): ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS ValueError: unsupported hash type md4 """ - def decorator(func): - @functools.wraps(func) + def decorator(func_or_class): + if isinstance(func_or_class, type): + setUpClass = func_or_class.__dict__.get('setUpClass') + if setUpClass is None: + def setUpClass(cls): + super(func_or_class, cls).setUpClass() + setUpClass.__qualname__ = func_or_class.__qualname__ + '.setUpClass' + setUpClass.__module__ = func_or_class.__module__ + else: + setUpClass = setUpClass.__func__ + setUpClass = classmethod(decorator(setUpClass)) + func_or_class.setUpClass = setUpClass + return func_or_class + + @functools.wraps(func_or_class) def wrapper(*args, **kwargs): try: if openssl and _hashlib is not None: @@ -33,6 +46,6 @@ def wrapper(*args, **kwargs): raise unittest.SkipTest( f"hash digest '{digestname}' is not available." ) - return func(*args, **kwargs) + return func_or_class(*args, **kwargs) return wrapper return decorator diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 5d1e9406879cc6..43ae31483420de 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -80,33 +80,13 @@ def import_module(name, deprecated=False, *, required_on=()): raise unittest.SkipTest(str(msg)) -def _save_and_remove_module(name, orig_modules): - """Helper function to save and remove a module from sys.modules - - Raise ImportError if the module can't be imported. - """ - # try to import the module and raise an error if it can't be imported - if name not in sys.modules: - __import__(name) - del sys.modules[name] +def _save_and_remove_modules(names): + orig_modules = {} + prefixes = tuple(name + '.' for name in names) for modname in list(sys.modules): - if modname == name or modname.startswith(name + '.'): - orig_modules[modname] = sys.modules[modname] - del sys.modules[modname] - - -def _save_and_block_module(name, orig_modules): - """Helper function to save and block a module in sys.modules - - Return True if the module was in sys.modules, False otherwise. - """ - saved = True - try: - orig_modules[name] = sys.modules[name] - except KeyError: - saved = False - sys.modules[name] = None - return saved + if modname in names or modname.startswith(prefixes): + orig_modules[modname] = sys.modules.pop(modname) + return orig_modules def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): @@ -118,7 +98,8 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): this operation. *fresh* is an iterable of additional module names that are also removed - from the sys.modules cache before doing the import. + from the sys.modules cache before doing the import. If one of these + modules can't be imported, None is returned. *blocked* is an iterable of module names that are replaced with None in the module cache during the import to ensure that attempts to import @@ -139,24 +120,24 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): with _ignore_deprecated_imports(deprecated): # Keep track of modules saved for later restoration as well # as those which just need a blocking entry removed - orig_modules = {} - names_to_remove = [] - _save_and_remove_module(name, orig_modules) + fresh = list(fresh) + blocked = list(blocked) + names = {name, *fresh, *blocked} + orig_modules = _save_and_remove_modules(names) + for modname in blocked: + sys.modules[modname] = None + try: - for fresh_name in fresh: - _save_and_remove_module(fresh_name, orig_modules) - for blocked_name in blocked: - if not _save_and_block_module(blocked_name, orig_modules): - names_to_remove.append(blocked_name) - fresh_module = importlib.import_module(name) - except ImportError: - fresh_module = None + # Return None when one of the "fresh" modules can not be imported. + try: + for modname in fresh: + __import__(modname) + except ImportError: + return None + return importlib.import_module(name) finally: - for orig_name, module in orig_modules.items(): - sys.modules[orig_name] = module - for name_to_remove in names_to_remove: - del sys.modules[name_to_remove] - return fresh_module + _save_and_remove_modules(names) + sys.modules.update(orig_modules) class CleanImport(object): diff --git a/Lib/test/support/socket_helper.py b/Lib/test/support/socket_helper.py index e78712b74b1377..b51677383ebc53 100644 --- a/Lib/test/support/socket_helper.py +++ b/Lib/test/support/socket_helper.py @@ -189,7 +189,7 @@ def get_socket_conn_refused_errs(): @contextlib.contextmanager def transient_internet(resource_name, *, timeout=_NOT_SET, errnos=()): """Return a context manager that raises ResourceDenied when various issues - with the Internet connection manifest themselves as exceptions.""" + with the internet connection manifest themselves as exceptions.""" import nntplib import urllib.error if timeout is _NOT_SET: diff --git a/Lib/test/support/testresult.py b/Lib/test/support/testresult.py index 670afbea2659de..6f2edda0f580ab 100644 --- a/Lib/test/support/testresult.py +++ b/Lib/test/support/testresult.py @@ -10,12 +10,11 @@ import unittest class RegressionTestResult(unittest.TextTestResult): - separator1 = '=' * 70 + '\n' - separator2 = '-' * 70 + '\n' USE_XML = False def __init__(self, stream, descriptions, verbosity): - super().__init__(stream=stream, descriptions=descriptions, verbosity=0) + super().__init__(stream=stream, descriptions=descriptions, + verbosity=2 if verbosity else 0) self.buffer = True if self.USE_XML: from xml.etree import ElementTree as ET @@ -25,8 +24,6 @@ def __init__(self, stream, descriptions, verbosity): self.__suite.set('start', datetime.utcnow().isoformat(' ')) self.__e = None self.__start_time = None - self.__results = [] - self.__verbose = bool(verbosity) @classmethod def __getId(cls, test): @@ -45,9 +42,6 @@ def startTest(self, test): if self.USE_XML: self.__e = e = self.__ET.SubElement(self.__suite, 'testcase') self.__start_time = time.perf_counter() - if self.__verbose: - self.stream.write(f'{self.getDescription(test)} ... ') - self.stream.flush() def _add_result(self, test, capture=False, **args): if not self.USE_XML: @@ -85,10 +79,6 @@ def _add_result(self, test, capture=False, **args): else: e2.text = str(v) - def __write(self, c, word): - if self.__verbose: - self.stream.write(f'{word}\n') - @classmethod def __makeErrorDict(cls, err_type, err_value, err_tb): if isinstance(err_type, type): @@ -111,45 +101,26 @@ def __makeErrorDict(cls, err_type, err_value, err_tb): def addError(self, test, err): self._add_result(test, True, error=self.__makeErrorDict(*err)) super().addError(test, err) - self.__write('E', 'ERROR') def addExpectedFailure(self, test, err): self._add_result(test, True, output=self.__makeErrorDict(*err)) super().addExpectedFailure(test, err) - self.__write('x', 'expected failure') def addFailure(self, test, err): self._add_result(test, True, failure=self.__makeErrorDict(*err)) super().addFailure(test, err) - self.__write('F', 'FAIL') def addSkip(self, test, reason): self._add_result(test, skipped=reason) super().addSkip(test, reason) - self.__write('S', f'skipped {reason!r}') def addSuccess(self, test): self._add_result(test) super().addSuccess(test) - self.__write('.', 'ok') def addUnexpectedSuccess(self, test): self._add_result(test, outcome='UNEXPECTED_SUCCESS') super().addUnexpectedSuccess(test) - self.__write('u', 'unexpected success') - - def printErrors(self): - if self.__verbose: - self.stream.write('\n') - self.printErrorList('ERROR', self.errors) - self.printErrorList('FAIL', self.failures) - - def printErrorList(self, flavor, errors): - for test, err in errors: - self.stream.write(self.separator1) - self.stream.write(f'{flavor}: {self.getDescription(test)}\n') - self.stream.write(self.separator2) - self.stream.write('%s\n' % err) def get_xml_element(self): if not self.USE_XML: diff --git a/Lib/test/support/threading_helper.py b/Lib/test/support/threading_helper.py index 0632577cdb303c..92a64e8354acbc 100644 --- a/Lib/test/support/threading_helper.py +++ b/Lib/test/support/threading_helper.py @@ -157,7 +157,7 @@ class catch_threading_exception: Context manager catching threading.Thread exception using threading.excepthook. - Attributes set when an exception is catched: + Attributes set when an exception is caught: * exc_type * exc_value diff --git a/Lib/test/support/warnings_helper.py b/Lib/test/support/warnings_helper.py index de23e6b452b28d..a024fbe5beaa02 100644 --- a/Lib/test/support/warnings_helper.py +++ b/Lib/test/support/warnings_helper.py @@ -187,3 +187,13 @@ def save_restore_warnings_filters(): yield finally: warnings.filters[:] = old_filters + + +def _warn_about_deprecation(): + warnings.warn( + "This is used in test_support test to ensure" + " support.ignore_deprecations_from() works as expected." + " You should not be seeing this.", + DeprecationWarning, + stacklevel=0, + ) diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 7baea69a4e5fa7..177a8a64a4329f 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -39,6 +39,20 @@ def _run_output(interp, request, shared=None): return rpipe.read() +def _wait_for_interp_to_run(interp, timeout=None): + # bpo-37224: Running this test file in multiprocesses will fail randomly. + # The failure reason is that the thread can't acquire the cpu to + # run subinterpreter eariler than the main thread in multiprocess. + if timeout is None: + timeout = support.SHORT_TIMEOUT + start_time = time.monotonic() + deadline = start_time + timeout + while not interpreters.is_running(interp): + if time.monotonic() > deadline: + raise RuntimeError('interp is not running') + time.sleep(0.010) + + @contextlib.contextmanager def _running(interp): r, w = os.pipe() @@ -51,6 +65,7 @@ def run(): t = threading.Thread(target=run) t.start() + _wait_for_interp_to_run(interp) yield @@ -1206,7 +1221,7 @@ def test_channel_list_interpreters_basic(self): import _xxsubinterpreters as _interpreters obj = _interpreters.channel_recv({cid}) """)) - # Test for channel that has boths ends associated to an interpreter. + # Test for channel that has both ends associated to an interpreter. send_interps = interpreters.channel_list_interpreters(cid, send=True) recv_interps = interpreters.channel_list_interpreters(cid, send=False) self.assertEqual(send_interps, [interp0]) diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index 3d603e7734d870..c1d750dba83f99 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -459,6 +459,24 @@ class S(metaclass=abc_ABCMeta): with self.assertRaisesRegex(Exception, exc_msg): issubclass(int, S) + def test_subclasshook(self): + class A(metaclass=abc.ABCMeta): + @classmethod + def __subclasshook__(cls, C): + if cls is A: + return 'foo' in C.__dict__ + return NotImplemented + self.assertFalse(issubclass(A, A)) + self.assertFalse(issubclass(A, (A,))) + class B: + foo = 42 + self.assertTrue(issubclass(B, A)) + self.assertTrue(issubclass(B, (A,))) + class C: + spam = 42 + self.assertFalse(issubclass(C, A)) + self.assertFalse(issubclass(C, (A,))) + def test_all_new_methods_are_called(self): class A(metaclass=abc_ABCMeta): pass diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 4d0316f73edcd2..c96a540a8b3156 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -12,7 +12,6 @@ from io import StringIO -from test import support from test.support import os_helper from unittest import mock class StdIOBuffer(StringIO): @@ -2060,6 +2059,30 @@ def test_required_subparsers_default(self): ret = parser.parse_args(()) self.assertIsNone(ret.command) + def test_required_subparsers_no_destination_error(self): + parser = ErrorRaisingArgumentParser() + subparsers = parser.add_subparsers(required=True) + subparsers.add_parser('foo') + subparsers.add_parser('bar') + with self.assertRaises(ArgumentParserError) as excinfo: + parser.parse_args(()) + self.assertRegex( + excinfo.exception.stderr, + 'error: the following arguments are required: {foo,bar}\n$' + ) + + def test_wrong_argument_subparsers_no_destination_error(self): + parser = ErrorRaisingArgumentParser() + subparsers = parser.add_subparsers(required=True) + subparsers.add_parser('foo') + subparsers.add_parser('bar') + with self.assertRaises(ArgumentParserError) as excinfo: + parser.parse_args(('baz',)) + self.assertRegex( + excinfo.exception.stderr, + r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from 'foo', 'bar'\)\n$" + ) + def test_optional_subparsers(self): parser = ErrorRaisingArgumentParser() subparsers = parser.add_subparsers(dest='command', required=False) @@ -2122,6 +2145,42 @@ def test_help_non_breaking_spaces(self): wrap\N{NO-BREAK SPACE}at non-breaking spaces ''')) + def test_help_blank(self): + # Issue 24444 + parser = ErrorRaisingArgumentParser( + prog='PROG', description='main description') + parser.add_argument( + 'foo', + help=' ') + self.assertEqual(parser.format_help(), textwrap.dedent('''\ + usage: PROG [-h] foo + + main description + + positional arguments: + foo + + options: + -h, --help show this help message and exit + ''')) + + parser = ErrorRaisingArgumentParser( + prog='PROG', description='main description') + parser.add_argument( + 'foo', choices=[], + help='%(choices)s') + self.assertEqual(parser.format_help(), textwrap.dedent('''\ + usage: PROG [-h] {} + + main description + + positional arguments: + {} + + options: + -h, --help show this help message and exit + ''')) + def test_help_alternate_prefix_chars(self): parser = self._get_parser(prefix_chars='+:/') self.assertEqual(parser.format_usage(), @@ -2523,6 +2582,13 @@ def test_help(self): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_empty_group(self): + # See issue 26952 + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group() + with self.assertRaises(ValueError): + parser.parse_args(['-h']) + class MEMixin(object): def test_failures_when_not_required(self): @@ -4238,6 +4304,9 @@ class TestHelpArgumentDefaults(HelpTestCase): argument_signatures = [ Sig('--foo', help='foo help - oh and by the way, %(default)s'), Sig('--bar', action='store_true', help='bar help'), + Sig('--taz', action=argparse.BooleanOptionalAction, + help='Whether to taz it', default=True), + Sig('--quux', help="Set the quux", default=42), Sig('spam', help='spam help'), Sig('badger', nargs='?', default='wooden', help='badger help'), ] @@ -4246,25 +4315,29 @@ class TestHelpArgumentDefaults(HelpTestCase): [Sig('--baz', type=int, default=42, help='baz help')]), ] usage = '''\ - usage: PROG [-h] [--foo FOO] [--bar] [--baz BAZ] spam [badger] + usage: PROG [-h] [--foo FOO] [--bar] [--taz | --no-taz] [--quux QUUX] + [--baz BAZ] + spam [badger] ''' help = usage + '''\ description positional arguments: - spam spam help - badger badger help (default: wooden) + spam spam help + badger badger help (default: wooden) options: - -h, --help show this help message and exit - --foo FOO foo help - oh and by the way, None - --bar bar help (default: False) + -h, --help show this help message and exit + --foo FOO foo help - oh and by the way, None + --bar bar help (default: False) + --taz, --no-taz Whether to taz it (default: True) + --quux QUUX Set the quux (default: 42) title: description - --baz BAZ baz help (default: 42) + --baz BAZ baz help (default: 42) ''' version = '' @@ -5360,13 +5433,11 @@ def test_exit_on_error_with_bad_args(self): self.parser.parse_args('--integers a'.split()) -def test_main(): - support.run_unittest(__name__) +def tearDownModule(): # Remove global references to avoid looking like we have refleaks. RFile.seen = {} WFile.seen = set() - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py old mode 100644 new mode 100755 index b18467fb889d8b..6a48c1cc975727 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -42,9 +42,10 @@ def test_bad_constructor(self): @support.cpython_only def test_disallow_instantiation(self): - # Ensure that the type disallows instantiation (bpo-43916) - tp = type(iter(array.array('I'))) - self.assertRaises(TypeError, tp) + my_array = array.array("I") + support.check_disallow_instantiation( + self, type(iter(my_array)), my_array + ) @support.cpython_only def test_immutable(self): @@ -1096,6 +1097,7 @@ def test_weakref(self): p = weakref.proxy(s) self.assertEqual(p.tobytes(), s.tobytes()) s = None + support.gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, len, p) @unittest.skipUnless(hasattr(sys, 'getrefcount'), diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 80d24e94040bcf..39fc7e96738164 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -1,7 +1,6 @@ import ast import builtins import dis -import enum import os import sys import types @@ -696,38 +695,9 @@ def test_constant_as_name(self): for constant in "True", "False", "None": expr = ast.Expression(ast.Name(constant, ast.Load())) ast.fix_missing_locations(expr) - with self.assertRaisesRegex(ValueError, f"Name node can't be used with '{constant}' constant"): + with self.assertRaisesRegex(ValueError, f"identifier field can't represent '{constant}' constant"): compile(expr, "", "eval") - def test_precedence_enum(self): - class _Precedence(enum.IntEnum): - """Precedence table that originated from python grammar.""" - TUPLE = enum.auto() - YIELD = enum.auto() # 'yield', 'yield from' - TEST = enum.auto() # 'if'-'else', 'lambda' - OR = enum.auto() # 'or' - AND = enum.auto() # 'and' - NOT = enum.auto() # 'not' - CMP = enum.auto() # '<', '>', '==', '>=', '<=', '!=', - # 'in', 'not in', 'is', 'is not' - EXPR = enum.auto() - BOR = EXPR # '|' - BXOR = enum.auto() # '^' - BAND = enum.auto() # '&' - SHIFT = enum.auto() # '<<', '>>' - ARITH = enum.auto() # '+', '-' - TERM = enum.auto() # '*', '@', '/', '%', '//' - FACTOR = enum.auto() # unary '+', '-', '~' - POWER = enum.auto() # '**' - AWAIT = enum.auto() # 'await' - ATOM = enum.auto() - def next(self): - try: - return self.__class__(self + 1) - except ValueError: - return self - enum._test_simple_enum(_Precedence, ast._Precedence) - class ASTHelpers_Test(unittest.TestCase): maxDiff = None @@ -1074,6 +1044,14 @@ def test_literal_eval_malformed_lineno(self): with self.assertRaisesRegex(ValueError, msg): ast.literal_eval(node) + def test_literal_eval_syntax_errors(self): + msg = "unexpected character after line continuation character" + with self.assertRaisesRegex(SyntaxError, msg): + ast.literal_eval(r''' + \ + (\ + \ ''') + def test_bad_integer(self): # issue13436: Bad error message with invalid numeric values body = [ast.ImportFrom(module='time', @@ -1097,6 +1075,22 @@ def test_level_as_none(self): exec(code, ns) self.assertIn('sleep', ns) + def test_recursion_direct(self): + e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0) + e.operand = e + with self.assertRaises(RecursionError): + with support.infinite_recursion(): + compile(ast.Expression(e), "", "eval") + + def test_recursion_indirect(self): + e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0) + f = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0) + e.operand = f + f.operand = e + with self.assertRaises(RecursionError): + with support.infinite_recursion(): + compile(ast.Expression(e), "", "eval") + class ASTValidatorTests(unittest.TestCase): @@ -1490,6 +1484,151 @@ def test_stdlib_validates(self): mod = ast.parse(source, fn) compile(mod, fn, "exec") + constant_1 = ast.Constant(1) + pattern_1 = ast.MatchValue(constant_1) + + constant_x = ast.Constant('x') + pattern_x = ast.MatchValue(constant_x) + + constant_true = ast.Constant(True) + pattern_true = ast.MatchSingleton(True) + + name_carter = ast.Name('carter', ast.Load()) + + _MATCH_PATTERNS = [ + ast.MatchValue( + ast.Attribute( + ast.Attribute( + ast.Name('x', ast.Store()), + 'y', ast.Load() + ), + 'z', ast.Load() + ) + ), + ast.MatchValue( + ast.Attribute( + ast.Attribute( + ast.Name('x', ast.Load()), + 'y', ast.Store() + ), + 'z', ast.Load() + ) + ), + ast.MatchValue( + ast.Constant(...) + ), + ast.MatchValue( + ast.Constant(True) + ), + ast.MatchValue( + ast.Constant((1,2,3)) + ), + ast.MatchSingleton('string'), + ast.MatchSequence([ + ast.MatchSingleton('string') + ]), + ast.MatchSequence( + [ + ast.MatchSequence( + [ + ast.MatchSingleton('string') + ] + ) + ] + ), + ast.MatchMapping( + [constant_1, constant_true], + [pattern_x] + ), + ast.MatchMapping( + [constant_true, constant_1], + [pattern_x, pattern_1], + rest='True' + ), + ast.MatchMapping( + [constant_true, ast.Starred(ast.Name('lol', ast.Load()), ast.Load())], + [pattern_x, pattern_1], + rest='legit' + ), + ast.MatchClass( + ast.Attribute( + ast.Attribute( + constant_x, + 'y', ast.Load()), + 'z', ast.Load()), + patterns=[], kwd_attrs=[], kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=['True'], + kwd_patterns=[pattern_1] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=[], + kwd_patterns=[pattern_1] + ), + ast.MatchClass( + name_carter, + patterns=[ast.MatchSingleton('string')], + kwd_attrs=[], + kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[ast.MatchStar()], + kwd_attrs=[], + kwd_patterns=[] + ), + ast.MatchClass( + name_carter, + patterns=[], + kwd_attrs=[], + kwd_patterns=[ast.MatchStar()] + ), + ast.MatchSequence( + [ + ast.MatchStar("True") + ] + ), + ast.MatchAs( + name='False' + ), + ast.MatchOr( + [] + ), + ast.MatchOr( + [pattern_1] + ), + ast.MatchOr( + [pattern_1, pattern_x, ast.MatchSingleton('xxx')] + ), + ast.MatchAs(name="_"), + ast.MatchStar(name="x"), + ast.MatchSequence([ast.MatchStar("_")]), + ast.MatchMapping([], [], rest="_"), + ] + + def test_match_validation_pattern(self): + name_x = ast.Name('x', ast.Load()) + for pattern in self._MATCH_PATTERNS: + with self.subTest(ast.dump(pattern, indent=4)): + node = ast.Match( + subject=name_x, + cases = [ + ast.match_case( + pattern=pattern, + body = [ast.Pass()] + ) + ] + ) + node = ast.fix_missing_locations(node) + module = ast.Module([node], []) + with self.assertRaises(ValueError): + compile(module, "", "exec") + class ConstantTests(unittest.TestCase): """Tests on the ast.Constant node type.""" diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py index 77c15c02bc8914..473bce484b47b0 100644 --- a/Lib/test/test_asyncgen.py +++ b/Lib/test/test_asyncgen.py @@ -1,11 +1,16 @@ import inspect import types import unittest +import contextlib from test.support.import_helper import import_module +from test.support import gc_collect asyncio = import_module("asyncio") +_no_default = object() + + class AwaitException(Exception): pass @@ -44,6 +49,37 @@ async def iterate(): return run_until_complete(iterate()) +def py_anext(iterator, default=_no_default): + """Pure-Python implementation of anext() for testing purposes. + + Closely matches the builtin anext() C implementation. + Can be used to compare the built-in implementation of the inner + coroutines machinery to C-implementation of __anext__() and send() + or throw() on the returned generator. + """ + + try: + __anext__ = type(iterator).__anext__ + except AttributeError: + raise TypeError(f'{iterator!r} is not an async iterator') + + if default is _no_default: + return __anext__(iterator) + + async def anext_impl(): + try: + # The C code is way more low-level than this, as it implements + # all methods of the iterator protocol. In this implementation + # we're relying on higher-level coroutine concepts, but that's + # exactly what we want -- crosstest pure-Python high-level + # implementation and low-level C anext() iterators. + return await __anext__(iterator) + except StopAsyncIteration: + return default + + return anext_impl() + + class AsyncGenSyntaxTest(unittest.TestCase): def test_async_gen_syntax_01(self): @@ -373,6 +409,12 @@ def tearDown(self): asyncio.set_event_loop_policy(None) def check_async_iterator_anext(self, ait_class): + with self.subTest(anext="pure-Python"): + self._check_async_iterator_anext(ait_class, py_anext) + with self.subTest(anext="builtin"): + self._check_async_iterator_anext(ait_class, anext) + + def _check_async_iterator_anext(self, ait_class, anext): g = ait_class() async def consume(): results = [] @@ -405,6 +447,24 @@ async def test_2(): result = self.loop.run_until_complete(test_2()) self.assertEqual(result, "completed") + def test_send(): + p = ait_class() + obj = anext(p, "completed") + with self.assertRaises(StopIteration): + with contextlib.closing(obj.__await__()) as g: + g.send(None) + + test_send() + + async def test_throw(): + p = ait_class() + obj = anext(p, "completed") + self.assertRaises(SyntaxError, obj.throw, SyntaxError) + return "completed" + + result = self.loop.run_until_complete(test_throw()) + self.assertEqual(result, "completed") + def test_async_generator_anext(self): async def agen(): yield 1 @@ -568,6 +628,119 @@ async def do_test(): result = self.loop.run_until_complete(do_test()) self.assertEqual(result, "completed") + def test_anext_iter(self): + @types.coroutine + def _async_yield(v): + return (yield v) + + class MyError(Exception): + pass + + async def agenfn(): + try: + await _async_yield(1) + except MyError: + await _async_yield(2) + return + yield + + def test1(anext): + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + self.assertEqual(g.send(None), 1) + self.assertEqual(g.throw(MyError, MyError(), None), 2) + try: + g.send(None) + except StopIteration as e: + err = e + else: + self.fail('StopIteration was not raised') + self.assertEqual(err.value, "default") + + def test2(anext): + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + self.assertEqual(g.send(None), 1) + self.assertEqual(g.throw(MyError, MyError(), None), 2) + with self.assertRaises(MyError): + g.throw(MyError, MyError(), None) + + def test3(anext): + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + self.assertEqual(g.send(None), 1) + g.close() + with self.assertRaisesRegex(RuntimeError, 'cannot reuse'): + self.assertEqual(g.send(None), 1) + + def test4(anext): + @types.coroutine + def _async_yield(v): + yield v * 10 + return (yield (v * 10 + 1)) + + async def agenfn(): + try: + await _async_yield(1) + except MyError: + await _async_yield(2) + return + yield + + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + self.assertEqual(g.send(None), 10) + self.assertEqual(g.throw(MyError, MyError(), None), 20) + with self.assertRaisesRegex(MyError, 'val'): + g.throw(MyError, MyError('val'), None) + + def test5(anext): + @types.coroutine + def _async_yield(v): + yield v * 10 + return (yield (v * 10 + 1)) + + async def agenfn(): + try: + await _async_yield(1) + except MyError: + return + yield 'aaa' + + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + self.assertEqual(g.send(None), 10) + with self.assertRaisesRegex(StopIteration, 'default'): + g.throw(MyError, MyError(), None) + + def test6(anext): + @types.coroutine + def _async_yield(v): + yield v * 10 + return (yield (v * 10 + 1)) + + async def agenfn(): + await _async_yield(1) + yield 'aaa' + + agen = agenfn() + with contextlib.closing(anext(agen, "default").__await__()) as g: + with self.assertRaises(MyError): + g.throw(MyError, MyError(), None) + + def run_test(test): + with self.subTest('pure-Python anext()'): + test(py_anext) + with self.subTest('builtin anext()'): + test(anext) + + run_test(test1) + run_test(test2) + run_test(test3) + run_test(test4) + run_test(test5) + run_test(test6) + def test_aiter_bad_args(self): async def gen(): yield 1 @@ -871,6 +1044,7 @@ async def run(): await g.__anext__() await g.__anext__() del g + gc_collect() # For PyPy or other GCs. await asyncio.sleep(0.1) @@ -1287,6 +1461,85 @@ async def wait(): self.assertEqual(finalized, 2) + def test_async_gen_asyncio_shutdown_02(self): + messages = [] + + def exception_handler(loop, context): + messages.append(context) + + async def async_iterate(): + yield 1 + yield 2 + + it = async_iterate() + async def main(): + loop = asyncio.get_running_loop() + loop.set_exception_handler(exception_handler) + + async for i in it: + break + + asyncio.run(main()) + + self.assertEqual(messages, []) + + def test_async_gen_asyncio_shutdown_exception_01(self): + messages = [] + + def exception_handler(loop, context): + messages.append(context) + + async def async_iterate(): + try: + yield 1 + yield 2 + finally: + 1/0 + + it = async_iterate() + async def main(): + loop = asyncio.get_running_loop() + loop.set_exception_handler(exception_handler) + + async for i in it: + break + + asyncio.run(main()) + + message, = messages + self.assertEqual(message['asyncgen'], it) + self.assertIsInstance(message['exception'], ZeroDivisionError) + self.assertIn('an error occurred during closing of asynchronous generator', + message['message']) + + def test_async_gen_asyncio_shutdown_exception_02(self): + messages = [] + + def exception_handler(loop, context): + messages.append(context) + + async def async_iterate(): + try: + yield 1 + yield 2 + finally: + 1/0 + + async def main(): + loop = asyncio.get_running_loop() + loop.set_exception_handler(exception_handler) + + async for i in async_iterate(): + break + gc_collect() + + asyncio.run(main()) + + message, = messages + self.assertIsInstance(message['exception'], ZeroDivisionError) + self.assertIn('unhandled exception during asyncio.run() shutdown', + message['message']) + def test_async_gen_expression_01(self): async def arange(n): for i in range(n): diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py index b32edddc7d5505..973ac1f7d97c9b 100644 --- a/Lib/test/test_asynchat.py +++ b/Lib/test/test_asynchat.py @@ -4,8 +4,6 @@ from test.support import socket_helper from test.support import threading_helper -import asynchat -import asyncore import errno import socket import sys @@ -14,6 +12,12 @@ import unittest import unittest.mock +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + HOST = socket_helper.HOST SERVER_QUIT = b'QUIT\n' diff --git a/Lib/test/test_asyncio/functional.py b/Lib/test/test_asyncio/functional.py index 74490a869de9d9..d19c7a612ccf86 100644 --- a/Lib/test/test_asyncio/functional.py +++ b/Lib/test/test_asyncio/functional.py @@ -29,10 +29,6 @@ def setUp(self): self.loop.set_exception_handler(self.loop_exception_handler) self.__unhandled_exceptions = [] - # Disable `_get_running_loop`. - self._old_get_running_loop = asyncio.events._get_running_loop - asyncio.events._get_running_loop = lambda: None - def tearDown(self): try: self.loop.close() @@ -43,7 +39,6 @@ def tearDown(self): self.fail('unexpected calls to loop.call_exception_handler()') finally: - asyncio.events._get_running_loop = self._old_get_running_loop asyncio.set_event_loop(None) self.loop = None diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 5691d4250aca9e..f7ef23e55090ec 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -643,7 +643,7 @@ def run_loop(): 'Exception in callback.*zero'), exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) - assert not mock_handler.called + self.assertFalse(mock_handler.called) def test_set_exc_handler_broken(self): def run_loop(): @@ -1003,22 +1003,26 @@ def __init__(self, create_future=False): if create_future: self.done = asyncio.get_running_loop().create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1033,20 +1037,24 @@ def __init__(self, create_future=False, loop=None): if create_future: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -1395,7 +1403,7 @@ def test_create_connection_bluetooth(self, m_socket): addr = ('00:01:02:03:04:05', 1) def getaddrinfo(host, port, *args, **kw): - assert (host, port) == addr + self.assertEqual((host, port), addr) return [(999, 1, 999, '', (addr, 1))] m_socket.getaddrinfo = getaddrinfo @@ -1694,7 +1702,7 @@ def test_create_datagram_endpoint_sock_unix(self): lambda: MyDatagramProto(create_future=True, loop=self.loop), family=socket.AF_UNIX) transport, protocol = self.loop.run_until_complete(fut) - assert transport._sock.family == socket.AF_UNIX + self.assertEqual(transport._sock.family, socket.AF_UNIX) transport.close() self.loop.run_until_complete(protocol.done) self.assertEqual('CLOSED', protocol.state) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 55fc266cb714b1..bed7b5d30b85a0 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -87,23 +87,27 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -124,20 +128,24 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'INITIALIZED' def datagram_received(self, data, addr): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.nbytes += len(data) def error_received(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') def connection_lost(self, exc): - assert self.state == 'INITIALIZED', self.state + self._assert_state('INITIALIZED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -153,23 +161,27 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == ['INITIAL'], self.state + self._assert_state(['INITIAL']) self.state.append('CONNECTED') def data_received(self, data): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.nbytes += len(data) def eof_received(self): - assert self.state == ['INITIAL', 'CONNECTED'], self.state + self._assert_state(['INITIAL', 'CONNECTED']) self.state.append('EOF') def connection_lost(self, exc): if 'EOF' not in self.state: self.state.append('EOF') # It is okay if EOF is missed. - assert self.state == ['INITIAL', 'CONNECTED', 'EOF'], self.state + self._assert_state(['INITIAL', 'CONNECTED', 'EOF']) self.state.append('CLOSED') if self.done: self.done.set_result(None) @@ -184,13 +196,17 @@ def __init__(self, loop=None): if loop is not None: self.done = loop.create_future() + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -209,31 +225,35 @@ def __init__(self, loop): self.got_data = {1: asyncio.Event(), 2: asyncio.Event()} + def _assert_state(self, expected): + if self.state != expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' self.connected.set_result(None) def connection_lost(self, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'CLOSED' self.completed.set_result(None) def pipe_data_received(self, fd, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.data[fd] += data self.got_data[fd].set() def pipe_connection_lost(self, fd, exc): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') if exc: self.disconnects[fd].set_exception(exc) else: self.disconnects[fd].set_result(exc) def process_exited(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.returncode = self.transport.get_returncode() @@ -1283,7 +1303,7 @@ def test_create_datagram_endpoint_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_datagram_endpoint( lambda: MyDatagramProto(loop=self.loop), sock=sock) @@ -1970,10 +1990,11 @@ def test_subprocess_wait_no_same_group(self): functools.partial(MySubprocessProtocol, self.loop), 'exit 7', stdin=None, stdout=None, stderr=None, start_new_session=True) - _, proto = yield self.loop.run_until_complete(connect) + transp, proto = self.loop.run_until_complete(connect) self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.completed) self.assertEqual(7, proto.returncode) + transp.close() def test_subprocess_exec_invalid_args(self): async def connect(**kwds): diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index fe3d44227c83cc..0c379e0fb0f956 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -54,30 +54,30 @@ def done(self): or self.__exception is not None) def result(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) if self.__exception is not None: raise self.__exception return self.__result def exception(self): - assert not self.cancelled() + self.assertFalse(self.cancelled()) return self.__exception def set_result(self, result): - assert not self.done() - assert result is not None + self.assertFalse(self.done()) + self.assertIsNotNone(result) self.__result = result def set_exception(self, exception): - assert not self.done() - assert exception is not None + self.assertFalse(self.done()) + self.assertIsNotNone(exception) self.__exception = exception def __iter__(self): if not self.done(): self._asyncio_future_blocking = True yield self - assert self.done() + self.assertTrue(self.done()) return self.result() @@ -91,12 +91,12 @@ def setUp(self): def test_wrap_future(self): f = DuckFuture() g = asyncio.wrap_future(f) - assert g is f + self.assertIs(g, f) def test_ensure_future(self): f = DuckFuture() g = asyncio.ensure_future(f) - assert g is f + self.assertIs(g, f) class BaseFutureTests: @@ -918,6 +918,8 @@ def _get_future_cls(self): return futures._PyFuture +@unittest.skipUnless(hasattr(futures, '_CFuture'), + 'requires the C _asyncio module') class CFutureInheritanceTests(BaseFutureInheritanceTests, test_utils.TestCase): def _get_future_cls(self): diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 6194cd06176dac..e2cd2ba0365fda 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -5,7 +5,6 @@ import re import asyncio -from test.test_asyncio import utils as test_utils STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
      .*?)' @@ -20,22 +19,18 @@ def tearDownModule(): asyncio.set_event_loop_policy(None) -class LockTests(test_utils.TestCase): +class LockTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_repr(self): + async def test_repr(self): lock = asyncio.Lock() self.assertTrue(repr(lock).endswith('[unlocked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(repr(lock).endswith('[locked]>')) self.assertTrue(RGX_REPR.match(repr(lock))) - def test_lock(self): + async def test_lock(self): lock = asyncio.Lock() with self.assertWarns(DeprecationWarning): @@ -47,11 +42,11 @@ def acquire_lock(): TypeError, "object is not iterable" ): - self.loop.run_until_complete(acquire_lock()) + await acquire_lock() self.assertFalse(lock.locked()) - def test_lock_doesnt_accept_loop_parameter(self): + async def test_lock_doesnt_accept_loop_parameter(self): primitives_cls = [ asyncio.Lock, asyncio.Condition, @@ -60,17 +55,17 @@ def test_lock_doesnt_accept_loop_parameter(self): asyncio.BoundedSemaphore, ] + loop = asyncio.get_running_loop() + for cls in primitives_cls: with self.assertRaisesRegex( TypeError, rf'As of 3.10, the \*loop\* parameter was removed from ' rf'{cls.__name__}\(\) since it is no longer necessary' ): - cls(loop=self.loop) + cls(loop=loop) - def test_lock_by_with_statement(self): - loop = asyncio.new_event_loop() # don't use TestLoop quirks - self.set_event_loop(loop) + async def test_lock_by_with_statement(self): primitives = [ asyncio.Lock(), asyncio.Condition(), @@ -91,15 +86,15 @@ def test(lock): pass self.assertFalse(lock.locked()) - for primitive in primitives: - loop.run_until_complete(test(primitive)) - self.assertFalse(primitive.locked()) + for lock in primitives: + await test(lock) + self.assertFalse(lock.locked()) - def test_acquire(self): + async def test_acquire(self): lock = asyncio.Lock() result = [] - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) async def c1(result): if await lock.acquire(): @@ -116,27 +111,27 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) lock.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -146,18 +141,17 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): lock = asyncio.Lock() - self.assertTrue(self.loop.run_until_complete(lock.acquire())) + self.assertTrue(await lock.acquire()) - task = self.loop.create_task(lock.acquire()) - self.loop.call_soon(task.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, task) + task = asyncio.create_task(lock.acquire()) + asyncio.get_running_loop().call_soon(task.cancel) + with self.assertRaises(asyncio.CancelledError): + await task self.assertFalse(lock._waiters) - def test_cancel_race(self): + async def test_cancel_race(self): # Several tasks: # - A acquires the lock # - B is blocked in acquire() @@ -182,15 +176,15 @@ async def lockit(name, blocker): finally: lock.release() - fa = self.loop.create_future() - ta = self.loop.create_task(lockit('A', fa)) - test_utils.run_briefly(self.loop) + fa = asyncio.get_running_loop().create_future() + ta = asyncio.create_task(lockit('A', fa)) + await asyncio.sleep(0) self.assertTrue(lock.locked()) - tb = self.loop.create_task(lockit('B', None)) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lockit('B', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) - tc = self.loop.create_task(lockit('C', None)) - test_utils.run_briefly(self.loop) + tc = asyncio.create_task(lockit('C', None)) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 2) # Create the race and check. @@ -198,16 +192,17 @@ async def lockit(name, blocker): fa.set_result(None) tb.cancel() self.assertTrue(lock._waiters[0].cancelled()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertFalse(lock.locked()) self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - self.assertTrue(tc.done()) + await tc - def test_cancel_release_race(self): + async def test_cancel_release_race(self): # Issue 32734 # Acquire 4 locks, cancel second, release first # and 2 locks are taken at once. + loop = asyncio.get_running_loop() lock = asyncio.Lock() lock_count = 0 call_count = 0 @@ -219,27 +214,23 @@ async def lockit(): await lock.acquire() lock_count += 1 - async def lockandtrigger(): - await lock.acquire() - self.loop.call_soon(trigger) - def trigger(): t1.cancel() lock.release() - t0 = self.loop.create_task(lockandtrigger()) - t1 = self.loop.create_task(lockit()) - t2 = self.loop.create_task(lockit()) - t3 = self.loop.create_task(lockit()) + await lock.acquire() - # First loop acquires all - test_utils.run_briefly(self.loop) - self.assertTrue(t0.done()) + t1 = asyncio.create_task(lockit()) + t2 = asyncio.create_task(lockit()) + t3 = asyncio.create_task(lockit()) - # Second loop calls trigger - test_utils.run_briefly(self.loop) - # Third loop calls cancellation - test_utils.run_briefly(self.loop) + # Start scheduled tasks + await asyncio.sleep(0) + + loop.call_soon(trigger) + with self.assertRaises(asyncio.CancelledError): + # Wait for cancellation + await t1 # Make sure only one lock was taken self.assertEqual(lock_count, 1) @@ -249,62 +240,56 @@ def trigger(): # Cleanup the task that is stuck on acquire. t3.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertTrue(t3.cancelled()) - def test_finished_waiter_cancelled(self): + async def test_finished_waiter_cancelled(self): lock = asyncio.Lock() - ta = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + await lock.acquire() self.assertTrue(lock.locked()) - tb = self.loop.create_task(lock.acquire()) - test_utils.run_briefly(self.loop) + tb = asyncio.create_task(lock.acquire()) + await asyncio.sleep(0) self.assertEqual(len(lock._waiters), 1) # Create a second waiter, wake up the first, and cancel it. # Without the fix, the second was not woken up. - tc = self.loop.create_task(lock.acquire()) - lock.release() + tc = asyncio.create_task(lock.acquire()) tb.cancel() - test_utils.run_briefly(self.loop) + lock.release() + await asyncio.sleep(0) self.assertTrue(lock.locked()) - self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) - def test_release_not_acquired(self): + # Cleanup + await tc + + async def test_release_not_acquired(self): lock = asyncio.Lock() self.assertRaises(RuntimeError, lock.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): lock = asyncio.Lock() - self.loop.run_until_complete(lock.acquire()) + await lock.acquire() self.assertTrue(lock.locked()) lock.release() self.assertFalse(lock.locked()) - def test_context_manager(self): - async def f(): - lock = asyncio.Lock() - self.assertFalse(lock.locked()) - - async with lock: - self.assertTrue(lock.locked()) - - self.assertFalse(lock.locked()) + async def test_context_manager(self): + lock = asyncio.Lock() + self.assertFalse(lock.locked()) - self.loop.run_until_complete(f()) + async with lock: + self.assertTrue(lock.locked()) + self.assertFalse(lock.locked()) -class EventTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class EventTests(unittest.IsolatedAsyncioTestCase): def test_repr(self): ev = asyncio.Event() @@ -320,7 +305,7 @@ def test_repr(self): self.assertTrue('waiters:1' in repr(ev)) self.assertTrue(RGX_REPR.match(repr(ev))) - def test_wait(self): + async def test_wait(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -338,16 +323,16 @@ async def c3(result): if await ev.wait(): result.append(3) - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - t3 = self.loop.create_task(c3(result)) + t3 = asyncio.create_task(c3(result)) ev.set() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([3, 1, 2], result) self.assertTrue(t1.done()) @@ -357,24 +342,23 @@ async def c3(result): self.assertTrue(t3.done()) self.assertIsNone(t3.result()) - def test_wait_on_set(self): + async def test_wait_on_set(self): ev = asyncio.Event() ev.set() - res = self.loop.run_until_complete(ev.wait()) + res = await ev.wait() self.assertTrue(res) - def test_wait_cancel(self): + async def test_wait_cancel(self): ev = asyncio.Event() - wait = self.loop.create_task(ev.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(ev.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(ev._waiters) - def test_clear(self): + async def test_clear(self): ev = asyncio.Event() self.assertFalse(ev.is_set()) @@ -384,7 +368,7 @@ def test_clear(self): ev.clear() self.assertFalse(ev.is_set()) - def test_clear_with_waiters(self): + async def test_clear_with_waiters(self): ev = asyncio.Event() result = [] @@ -393,8 +377,8 @@ async def c1(result): result.append(1) return True - t = self.loop.create_task(c1(result)) - test_utils.run_briefly(self.loop) + t = asyncio.create_task(c1(result)) + await asyncio.sleep(0) self.assertEqual([], result) ev.set() @@ -405,7 +389,7 @@ async def c1(result): ev.set() self.assertEqual(1, len(ev._waiters)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertEqual(0, len(ev._waiters)) @@ -413,13 +397,9 @@ async def c1(result): self.assertTrue(t.result()) -class ConditionTests(test_utils.TestCase): +class ConditionTests(unittest.IsolatedAsyncioTestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() - - def test_wait(self): + async def test_wait(self): cond = asyncio.Condition() result = [] @@ -441,37 +421,37 @@ async def c3(result): result.append(3) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertFalse(cond.locked()) - self.assertTrue(self.loop.run_until_complete(cond.acquire())) + self.assertTrue(await cond.acquire()) cond.notify() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.notify(2) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(cond.locked()) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(cond.locked()) @@ -482,49 +462,47 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_wait_cancel(self): + async def test_wait_cancel(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() - wait = self.loop.create_task(cond.wait()) - self.loop.call_soon(wait.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, wait) + wait = asyncio.create_task(cond.wait()) + asyncio.get_running_loop().call_soon(wait.cancel) + with self.assertRaises(asyncio.CancelledError): + await wait self.assertFalse(cond._waiters) self.assertTrue(cond.locked()) - def test_wait_cancel_contested(self): + async def test_wait_cancel_contested(self): cond = asyncio.Condition() - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) - wait_task = self.loop.create_task(cond.wait()) - test_utils.run_briefly(self.loop) + wait_task = asyncio.create_task(cond.wait()) + await asyncio.sleep(0) self.assertFalse(cond.locked()) # Notify, but contest the lock before cancelling - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue(cond.locked()) cond.notify() - self.loop.call_soon(wait_task.cancel) - self.loop.call_soon(cond.release) + asyncio.get_running_loop().call_soon(wait_task.cancel) + asyncio.get_running_loop().call_soon(cond.release) try: - self.loop.run_until_complete(wait_task) + await wait_task except asyncio.CancelledError: # Should not happen, since no cancellation points pass self.assertTrue(cond.locked()) - def test_wait_cancel_after_notify(self): + async def test_wait_cancel_after_notify(self): # See bpo-32841 waited = False cond = asyncio.Condition() - cond._loop = self.loop async def wait_on_cond(): nonlocal waited @@ -532,27 +510,26 @@ async def wait_on_cond(): waited = True # Make sure this area was reached await cond.wait() - waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) - test_utils.run_briefly(self.loop) # Start waiting + waiter = asyncio.create_task(wait_on_cond()) + await asyncio.sleep(0) # Start waiting - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() - test_utils.run_briefly(self.loop) # Get to acquire() + await asyncio.sleep(0) # Get to acquire() waiter.cancel() - test_utils.run_briefly(self.loop) # Activate cancellation + await asyncio.sleep(0) # Activate cancellation cond.release() - test_utils.run_briefly(self.loop) # Cancellation should occur + await asyncio.sleep(0) # Cancellation should occur self.assertTrue(waiter.cancelled()) self.assertTrue(waited) - def test_wait_unacquired(self): + async def test_wait_unacquired(self): cond = asyncio.Condition() - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, cond.wait()) + with self.assertRaises(RuntimeError): + await cond.wait() - def test_wait_for(self): + async def test_wait_for(self): cond = asyncio.Condition() presult = False @@ -568,40 +545,38 @@ async def c1(result): cond.release() return True - t = self.loop.create_task(c1(result)) + t = asyncio.create_task(c1(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) presult = True - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(t.done()) self.assertTrue(t.result()) - def test_wait_for_unacquired(self): + async def test_wait_for_unacquired(self): cond = asyncio.Condition() # predicate can return true immediately - res = self.loop.run_until_complete(cond.wait_for(lambda: [1, 2, 3])) + res = await cond.wait_for(lambda: [1, 2, 3]) self.assertEqual([1, 2, 3], res) - self.assertRaises( - RuntimeError, - self.loop.run_until_complete, - cond.wait_for(lambda: False)) + with self.assertRaises(RuntimeError): + await cond.wait_for(lambda: False) - def test_notify(self): + async def test_notify(self): cond = asyncio.Condition() result = [] @@ -626,24 +601,24 @@ async def c3(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify(1) cond.notify(2048) cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) @@ -653,7 +628,7 @@ async def c3(result): self.assertTrue(t3.done()) self.assertTrue(t3.result()) - def test_notify_all(self): + async def test_notify_all(self): cond = asyncio.Condition() result = [] @@ -672,16 +647,16 @@ async def c2(result): cond.release() return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([], result) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() cond.notify_all() cond.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1, 2], result) self.assertTrue(t1.done()) @@ -697,12 +672,12 @@ def test_notify_all_unacquired(self): cond = asyncio.Condition() self.assertRaises(RuntimeError, cond.notify_all) - def test_repr(self): + async def test_repr(self): cond = asyncio.Condition() self.assertTrue('unlocked' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - self.loop.run_until_complete(cond.acquire()) + await cond.acquire() self.assertTrue('locked' in repr(cond)) cond._waiters.append(mock.Mock()) @@ -713,65 +688,96 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - def test_context_manager(self): - async def f(): - cond = asyncio.Condition() + async def test_context_manager(self): + cond = asyncio.Condition() + self.assertFalse(cond.locked()) + async with cond: + self.assertTrue(cond.locked()) + self.assertFalse(cond.locked()) + + async def test_explicit_lock(self): + async def f(lock=None, cond=None): + if lock is None: + lock = asyncio.Lock() + if cond is None: + cond = asyncio.Condition(lock) + self.assertIs(cond._lock, lock) + self.assertFalse(lock.locked()) self.assertFalse(cond.locked()) async with cond: + self.assertTrue(lock.locked()) + self.assertTrue(cond.locked()) + self.assertFalse(lock.locked()) + self.assertFalse(cond.locked()) + async with lock: + self.assertTrue(lock.locked()) self.assertTrue(cond.locked()) + self.assertFalse(lock.locked()) self.assertFalse(cond.locked()) - self.loop.run_until_complete(f()) - - def test_explicit_lock(self): - lock = asyncio.Lock() - cond = asyncio.Condition(lock) - - self.assertIs(cond._lock, lock) - self.assertIs(cond._loop, lock._loop) - - def test_ambiguous_loops(self): - loop = self.new_test_loop() - self.addCleanup(loop.close) - + # All should work in the same way. + await f() + await f(asyncio.Lock()) lock = asyncio.Lock() - lock._loop = loop - - async def _create_condition(): - with self.assertRaises(ValueError): - asyncio.Condition(lock) + await f(lock, asyncio.Condition(lock)) - self.loop.run_until_complete(_create_condition()) - - def test_timeout_in_block(self): + async def test_ambiguous_loops(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) - async def task_timeout(): - condition = asyncio.Condition() - async with condition: - with self.assertRaises(asyncio.TimeoutError): - await asyncio.wait_for(condition.wait(), timeout=0.5) + async def wrong_loop_in_lock(): + with self.assertRaises(TypeError): + asyncio.Lock(loop=loop) # actively disallowed since 3.10 + lock = asyncio.Lock() + lock._loop = loop # use private API for testing + async with lock: + # acquired immediately via the fast-path + # without interaction with any event loop. + cond = asyncio.Condition(lock) + # cond.acquire() will trigger waiting on the lock + # and it will discover the event loop mismatch. + with self.assertRaisesRegex( + RuntimeError, + "is bound to a different event loop", + ): + await cond.acquire() + + async def wrong_loop_in_cond(): + # Same analogy here with the condition's loop. + lock = asyncio.Lock() + async with lock: + with self.assertRaises(TypeError): + asyncio.Condition(lock, loop=loop) + cond = asyncio.Condition(lock) + cond._loop = loop + with self.assertRaisesRegex( + RuntimeError, + "is bound to a different event loop", + ): + await cond.wait() - loop.run_until_complete(task_timeout()) + await wrong_loop_in_lock() + await wrong_loop_in_cond() + async def test_timeout_in_block(self): + condition = asyncio.Condition() + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5) -class SemaphoreTests(test_utils.TestCase): - def setUp(self): - super().setUp() - self.loop = self.new_test_loop() +class SemaphoreTests(unittest.IsolatedAsyncioTestCase): def test_initial_value_zero(self): sem = asyncio.Semaphore(0) self.assertTrue(sem.locked()) - def test_repr(self): + async def test_repr(self): sem = asyncio.Semaphore() self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) self.assertTrue(RGX_REPR.match(repr(sem))) - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(repr(sem).endswith('[locked]>')) self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) @@ -784,7 +790,7 @@ def test_repr(self): self.assertTrue('waiters:2' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - def test_semaphore(self): + async def test_semaphore(self): sem = asyncio.Semaphore() self.assertEqual(1, sem._value) @@ -797,7 +803,7 @@ def acquire_lock(): TypeError, "'Semaphore' object is not iterable", ): - self.loop.run_until_complete(acquire_lock()) + await acquire_lock() self.assertFalse(sem.locked()) self.assertEqual(1, sem._value) @@ -805,12 +811,12 @@ def acquire_lock(): def test_semaphore_value(self): self.assertRaises(ValueError, asyncio.Semaphore, -1) - def test_acquire(self): + async def test_acquire(self): sem = asyncio.Semaphore(3) result = [] - self.assertTrue(self.loop.run_until_complete(sem.acquire())) - self.assertTrue(self.loop.run_until_complete(sem.acquire())) + self.assertTrue(await sem.acquire()) + self.assertTrue(await sem.acquire()) self.assertFalse(sem.locked()) async def c1(result): @@ -833,23 +839,23 @@ async def c4(result): result.append(4) return True - t1 = self.loop.create_task(c1(result)) - t2 = self.loop.create_task(c2(result)) - t3 = self.loop.create_task(c3(result)) + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual([1], result) self.assertTrue(sem.locked()) self.assertEqual(2, len(sem._waiters)) self.assertEqual(0, sem._value) - t4 = self.loop.create_task(c4(result)) + t4 = asyncio.create_task(c4(result)) sem.release() sem.release() self.assertEqual(2, sem._value) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) self.assertEqual(0, sem._value) self.assertEqual(3, len(result)) self.assertTrue(sem.locked()) @@ -864,64 +870,64 @@ async def c4(result): # cleanup locked semaphore sem.release() - self.loop.run_until_complete(asyncio.gather(*race_tasks)) + await asyncio.gather(*race_tasks) - def test_acquire_cancel(self): + async def test_acquire_cancel(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() - acquire = self.loop.create_task(sem.acquire()) - self.loop.call_soon(acquire.cancel) - self.assertRaises( - asyncio.CancelledError, - self.loop.run_until_complete, acquire) + acquire = asyncio.create_task(sem.acquire()) + asyncio.get_running_loop().call_soon(acquire.cancel) + with self.assertRaises(asyncio.CancelledError): + await acquire self.assertTrue((not sem._waiters) or all(waiter.done() for waiter in sem._waiters)) - def test_acquire_cancel_before_awoken(self): + async def test_acquire_cancel_before_awoken(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) - t3 = self.loop.create_task(sem.acquire()) - t4 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + t3 = asyncio.create_task(sem.acquire()) + t4 = asyncio.create_task(sem.acquire()) - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - sem.release() t1.cancel() t2.cancel() + sem.release() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) num_done = sum(t.done() for t in [t3, t4]) self.assertEqual(num_done, 1) + self.assertTrue(t3.done()) + self.assertFalse(t4.done()) t3.cancel() t4.cancel() - test_utils.run_briefly(self.loop) + await asyncio.sleep(0) - def test_acquire_hang(self): + async def test_acquire_hang(self): sem = asyncio.Semaphore(value=0) - t1 = self.loop.create_task(sem.acquire()) - t2 = self.loop.create_task(sem.acquire()) + t1 = asyncio.create_task(sem.acquire()) + t2 = asyncio.create_task(sem.acquire()) + await asyncio.sleep(0) - test_utils.run_briefly(self.loop) - - sem.release() t1.cancel() - - test_utils.run_briefly(self.loop) + sem.release() + await asyncio.sleep(0) self.assertTrue(sem.locked()) + self.assertTrue(t2.done()) def test_release_not_acquired(self): sem = asyncio.BoundedSemaphore() self.assertRaises(ValueError, sem.release) - def test_release_no_waiters(self): + async def test_release_no_waiters(self): sem = asyncio.Semaphore() - self.loop.run_until_complete(sem.acquire()) + await sem.acquire() self.assertTrue(sem.locked()) sem.release() diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index 01c698653ec67e..0a5466a0af152b 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -36,25 +36,29 @@ def __init__(self, loop=None, close_after=0): self.data = bytearray() self.close_after = close_after + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) self.data.extend(data) super().data_received(data) diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py index d8a5df8ede1f84..ab022a357d205e 100644 --- a/Lib/test/test_asyncio/test_sock_lowlevel.py +++ b/Lib/test/test_asyncio/test_sock_lowlevel.py @@ -23,24 +23,28 @@ def __init__(self, loop=None): self.connected = loop.create_future() self.done = loop.create_future() + def _assert_state(self, *expected): + if self.state not in expected: + raise AssertionError(f'state: {self.state!r}, expected: {expected!r}') + def connection_made(self, transport): self.transport = transport - assert self.state == 'INITIAL', self.state + self._assert_state('INITIAL') self.state = 'CONNECTED' if self.connected: self.connected.set_result(None) transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.nbytes += len(data) def eof_received(self): - assert self.state == 'CONNECTED', self.state + self._assert_state('CONNECTED') self.state = 'EOF' def connection_lost(self, exc): - assert self.state in ('CONNECTED', 'EOF'), self.state + self._assert_state('CONNECTED', 'EOF') self.state = 'CLOSED' if self.done: self.done.set_result(None) @@ -451,7 +455,7 @@ def test_create_connection_sock(self): else: break else: - assert False, 'Can not create socket.' + self.fail('Can not create socket.') f = self.loop.create_connection( lambda: MyProto(loop=self.loop), sock=sock) diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index e87863eb712373..22a216a83e3f92 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -278,6 +278,7 @@ async def client(addr): # No garbage is left if SSL is closed uncleanly client_context = weakref.ref(client_context) + support.gc_collect() self.assertIsNone(client_context()) def test_create_connection_memory_leak(self): @@ -341,6 +342,7 @@ async def client(addr): # No garbage is left for SSL client from loop.create_connection, even # if user stores the SSLTransport in corresponding protocol instance client_context = weakref.ref(client_context) + support.gc_collect() self.assertIsNone(client_context()) def test_start_tls_client_buf_proto_1(self): @@ -381,9 +383,9 @@ def connection_made(self, tr): def get_buffer(self, sizehint): return self.buf - def buffer_updated(self, nsize): - assert nsize == 1 - self.on_data.set_result(bytes(self.buf[:nsize])) + def buffer_updated(slf, nsize): + self.assertEqual(nsize, 1) + slf.on_data.set_result(bytes(slf.buf[:nsize])) class ClientProtoSecond(asyncio.Protocol): def __init__(self, on_data, on_eof): @@ -640,6 +642,7 @@ async def client(addr): # The 10s handshake timeout should be cancelled to free related # objects without really waiting for 10s client_sslctx = weakref.ref(client_sslctx) + support.gc_collect() self.assertIsNone(client_sslctx()) def test_create_connection_ssl_slow_handshake(self): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 6eaa2899442184..227b2279e172c8 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -711,7 +711,7 @@ def test_read_all_from_pipe_reader(self): # See asyncio issue 168. This test is derived from the example # subprocess_attach_read_pipe.py, but we configure the # StreamReader's limit so that twice it is less than the size - # of the data writter. Also we must explicitly attach a child + # of the data writer. Also we must explicitly attach a child # watcher to the event loop. code = """\ @@ -987,10 +987,10 @@ def test_eof_feed_when_closing_writer(self): wr.close() f = wr.wait_closed() self.loop.run_until_complete(f) - assert rd.at_eof() + self.assertTrue(rd.at_eof()) f = rd.read() data = self.loop.run_until_complete(f) - assert data == b'' + self.assertEqual(data, b'') self.assertEqual(messages, []) diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 225a3babc844b8..14fa6dd76f9ca8 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -228,7 +228,7 @@ def prepare_broken_pipe_test(self): # buffer large enough to feed the whole pipe buffer large_data = b'x' * support.PIPE_MAX_SIZE - # the program ends before the stdin can be feeded + # the program ends before the stdin can be fed proc = self.loop.run_until_complete( asyncio.create_subprocess_exec( sys.executable, '-c', 'pass', @@ -665,6 +665,8 @@ class SubprocessThreadedWatcherTests(SubprocessWatcherMixin, Watcher = unix_events.ThreadedChildWatcher + @unittest.skip("bpo-38323: MultiLoopChildWatcher has a race condition \ + and these tests can hang the test suite") class SubprocessMultiLoopWatcherTests(SubprocessWatcherMixin, test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index a9e4cf53566ca9..1c05944c42d255 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -329,7 +329,7 @@ def coro(): self.set_event_loop(loop) fut = asyncio.ensure_future(Aw(coro()), loop=loop) loop.run_until_complete(fut) - assert fut.result() == 'ok' + self.assertEqual(fut.result(), 'ok') def test_ensure_future_neither(self): with self.assertRaises(TypeError): @@ -1148,20 +1148,16 @@ def gen(): self.assertEqual(res, "ok") def test_wait_for_cancellation_race_condition(self): - def gen(): - yield 0.1 - yield 0.1 - yield 0.1 - yield 0.1 + async def inner(): + with contextlib.suppress(asyncio.CancelledError): + await asyncio.sleep(1) + return 1 - loop = self.new_test_loop(gen) + async def main(): + result = await asyncio.wait_for(inner(), timeout=.01) + self.assertEqual(result, 1) - fut = self.new_future(loop) - loop.call_later(0.1, fut.set_result, "ok") - task = loop.create_task(asyncio.wait_for(fut, timeout=1)) - loop.call_later(0.1, task.cancel) - res = loop.run_until_complete(task) - self.assertEqual(res, "ok") + asyncio.run(main()) def test_wait_for_waits_for_task_cancellation(self): loop = asyncio.new_event_loop() @@ -1240,24 +1236,6 @@ async def inner(): with self.assertRaises(FooException): loop.run_until_complete(foo()) - def test_wait_for_raises_timeout_error_if_returned_during_cancellation(self): - loop = asyncio.new_event_loop() - self.addCleanup(loop.close) - - async def foo(): - async def inner(): - try: - await asyncio.sleep(0.2) - except asyncio.CancelledError: - return 42 - - inner_task = self.new_task(loop, inner()) - - await asyncio.wait_for(inner_task, timeout=_EPSILON) - - with self.assertRaises(asyncio.TimeoutError): - loop.run_until_complete(foo()) - def test_wait_for_self_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) @@ -2690,6 +2668,7 @@ def coro(): self.new_task(self.loop, gen) finally: gen.close() + gc.collect() # For PyPy or other GCs. self.assertTrue(m_log.error.called) message = m_log.error.call_args[0][0] @@ -3275,15 +3254,18 @@ class GenericTaskTests(test_utils.TestCase): def test_future_subclass(self): self.assertTrue(issubclass(asyncio.Task, asyncio.Future)) + @support.cpython_only def test_asyncio_module_compiled(self): # Because of circular imports it's easy to make _asyncio # module non-importable. This is a simple test that will # fail on systems where C modules were successfully compiled - # (hence the test for _functools), but _asyncio somehow didn't. + # (hence the test for _functools etc), but _asyncio somehow didn't. try: import _functools + import _json + import _pickle except ImportError: - pass + self.skipTest('C modules are not available') else: try: import _asyncio @@ -3669,7 +3651,7 @@ def test_run_coroutine_threadsafe_with_timeout(self): self.assertTrue(task.done()) def test_run_coroutine_threadsafe_task_cancelled(self): - """Test coroutine submission from a tread to an event loop + """Test coroutine submission from a thread to an event loop when the task is cancelled.""" callback = lambda: self.target(cancel=True) future = self.loop.run_in_executor(None, callback) @@ -3677,7 +3659,7 @@ def test_run_coroutine_threadsafe_task_cancelled(self): self.loop.run_until_complete(future) def test_run_coroutine_threadsafe_task_factory_exception(self): - """Test coroutine submission from a tread to an event loop + """Test coroutine submission from a thread to an event loop when the task factory raise an exception.""" def task_factory(loop, coro): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 643638564e342b..c3422850ce1b70 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -34,7 +34,8 @@ def EXITCODE(exitcode): def SIGNAL(signum): - assert 1 <= signum <= 68 + if not 1 <= signum <= 68: + raise AssertionError(f'invalid signum {signum}') return 32768 - signum diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 45c09bb4a2d3a0..eafa5be3829682 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -107,7 +107,8 @@ def test_popen(self): events = [ovin.event, ovout.event, overr.event] # Super-long timeout for slow buildbots. - res = _winapi.WaitForMultipleObjects(events, True, 10000) + res = _winapi.WaitForMultipleObjects(events, True, + int(support.SHORT_TIMEOUT * 1000)) self.assertEqual(res, _winapi.WAIT_OBJECT_0) self.assertFalse(ovout.pending) self.assertFalse(overr.pending) diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 3765194cd0dd27..0b9cde6878f37a 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -409,12 +409,13 @@ def _remove_writer(self, fd): return False def assert_writer(self, fd, callback, *args): - assert fd in self.writers, 'fd {} is not registered'.format(fd) + if fd not in self.writers: + raise AssertionError(f'fd {fd} is not registered') handle = self.writers[fd] - assert handle._callback == callback, '{!r} != {!r}'.format( - handle._callback, callback) - assert handle._args == args, '{!r} != {!r}'.format( - handle._args, args) + if handle._callback != callback: + raise AssertionError(f'{handle._callback!r} != {callback!r}') + if handle._args != args: + raise AssertionError(f'{handle._args!r} != {args!r}') def _ensure_fd_no_transport(self, fd): if not isinstance(fd, int): @@ -530,7 +531,8 @@ def close_loop(loop): thread.join() def set_event_loop(self, loop, *, cleanup=True): - assert loop is not None + if loop is None: + raise AssertionError('loop is None') # ensure that the event loop is passed explicitly in asyncio events.set_event_loop(None) if cleanup: diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 3bd904d1774bc3..ecd1e120ecb515 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -1,4 +1,3 @@ -import asyncore import unittest import select import os @@ -19,6 +18,11 @@ if support.PGO: raise unittest.SkipTest("test is not helpful for PGO") +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX') diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index 25ff34bb11298a..c5ce26323b5f9e 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -54,6 +54,11 @@ def test_block_add_hook(self): def test_block_add_hook_baseexception(self): self.do_test("test_block_add_hook_baseexception") + def test_marshal(self): + import_helper.import_module("marshal") + + self.do_test("test_marshal") + def test_pickle(self): import_helper.import_module("pickle") diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py index 4f62c4115f60aa..418492432a1676 100644 --- a/Lib/test/test_base64.py +++ b/Lib/test/test_base64.py @@ -714,6 +714,45 @@ def test_decode_nonascii_str(self): def test_ErrorHeritage(self): self.assertTrue(issubclass(binascii.Error, ValueError)) + def test_RFC4648_test_cases(self): + # test cases from RFC 4648 section 10 + b64encode = base64.b64encode + b32hexencode = base64.b32hexencode + b32encode = base64.b32encode + b16encode = base64.b16encode + + self.assertEqual(b64encode(b""), b"") + self.assertEqual(b64encode(b"f"), b"Zg==") + self.assertEqual(b64encode(b"fo"), b"Zm8=") + self.assertEqual(b64encode(b"foo"), b"Zm9v") + self.assertEqual(b64encode(b"foob"), b"Zm9vYg==") + self.assertEqual(b64encode(b"fooba"), b"Zm9vYmE=") + self.assertEqual(b64encode(b"foobar"), b"Zm9vYmFy") + + self.assertEqual(b32encode(b""), b"") + self.assertEqual(b32encode(b"f"), b"MY======") + self.assertEqual(b32encode(b"fo"), b"MZXQ====") + self.assertEqual(b32encode(b"foo"), b"MZXW6===") + self.assertEqual(b32encode(b"foob"), b"MZXW6YQ=") + self.assertEqual(b32encode(b"fooba"), b"MZXW6YTB") + self.assertEqual(b32encode(b"foobar"), b"MZXW6YTBOI======") + + self.assertEqual(b32hexencode(b""), b"") + self.assertEqual(b32hexencode(b"f"), b"CO======") + self.assertEqual(b32hexencode(b"fo"), b"CPNG====") + self.assertEqual(b32hexencode(b"foo"), b"CPNMU===") + self.assertEqual(b32hexencode(b"foob"), b"CPNMUOG=") + self.assertEqual(b32hexencode(b"fooba"), b"CPNMUOJ1") + self.assertEqual(b32hexencode(b"foobar"), b"CPNMUOJ1E8======") + + self.assertEqual(b16encode(b""), b"") + self.assertEqual(b16encode(b"f"), b"66") + self.assertEqual(b16encode(b"fo"), b"666F") + self.assertEqual(b16encode(b"foo"), b"666F6F") + self.assertEqual(b16encode(b"foob"), b"666F6F62") + self.assertEqual(b16encode(b"fooba"), b"666F6F6261") + self.assertEqual(b16encode(b"foobar"), b"666F6F626172") + class TestMain(unittest.TestCase): def tearDown(self): diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index 398698c79c16df..6ec59531fa88f0 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -57,7 +57,6 @@ import linecache from contextlib import contextmanager from itertools import islice, repeat -import test.support from test.support import import_helper from test.support import os_helper @@ -1193,13 +1192,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) -def test_main(): - test.support.run_unittest( - StateTestCase, - RunTestCase, - BreakpointTestCase, - IssuesTestCase, - ) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_bigaddrspace.py b/Lib/test/test_bigaddrspace.py index aa1f8ca75a9811..50272e99607fd3 100644 --- a/Lib/test/test_bigaddrspace.py +++ b/Lib/test/test_bigaddrspace.py @@ -92,10 +92,7 @@ def test_repeat(self): x = None -def test_main(): - support.run_unittest(BytesTest, StrTest) - if __name__ == '__main__': if len(sys.argv) > 1: support.set_memlimit(sys.argv[1]) - test_main() + unittest.main() diff --git a/Lib/test/test_bigmem.py b/Lib/test/test_bigmem.py index 6a244dd8c94800..859f1539e20b80 100644 --- a/Lib/test/test_bigmem.py +++ b/Lib/test/test_bigmem.py @@ -1247,11 +1247,8 @@ def test_sort(self, size): self.assertEqual(l[:10], [1] * 10) self.assertEqual(l[-10:], [5] * 10) -def test_main(): - support.run_unittest(StrTest, BytesTest, BytearrayTest, - TupleTest, ListTest) if __name__ == '__main__': if len(sys.argv) > 1: support.set_memlimit(sys.argv[1]) - test_main() + unittest.main() diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py index a3214c90ed61e4..4b32aad2419f4a 100644 --- a/Lib/test/test_bool.py +++ b/Lib/test/test_bool.py @@ -1,7 +1,6 @@ # Test properties of bool promised by PEP 285 import unittest -from test import support from test.support import os_helper import os @@ -370,8 +369,6 @@ def f(x): f(x) self.assertGreaterEqual(x.count, 1) -def test_main(): - support.run_unittest(BoolTest) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index bd8353d038b6fe..6dc4fa555021cc 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1861,7 +1861,7 @@ def test_warning_notimplemented(self): # be evaluated in a boolean context (virtually all such use cases # are a result of accidental misuse implementing rich comparison # operations in terms of one another). - # For the time being, it will continue to evaluate as truthy, but + # For the time being, it will continue to evaluate as a true value, but # issue a deprecation warning (with the eventual intent to make it # a TypeError). self.assertWarns(DeprecationWarning, bool, NotImplemented) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 381030fe0e8383..13ad238242d0c5 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1169,6 +1169,28 @@ class BufferBlocked(bytearray): self.assertEqual(bytes(ba), b'ab') self.assertRaises(TypeError, bytes, bb) + def test_repeat_id_preserving(self): + a = b'123abc1@' + b = b'456zyx-+' + self.assertEqual(id(a), id(a)) + self.assertNotEqual(id(a), id(b)) + self.assertNotEqual(id(a), id(a * -4)) + self.assertNotEqual(id(a), id(a * 0)) + self.assertEqual(id(a), id(a * 1)) + self.assertEqual(id(a), id(1 * a)) + self.assertNotEqual(id(a), id(a * 2)) + + class SubBytes(bytes): + pass + + s = SubBytes(b'qwerty()') + self.assertEqual(id(s), id(s)) + self.assertNotEqual(id(s), id(s * -4)) + self.assertNotEqual(id(s), id(s * 0)) + self.assertNotEqual(id(s), id(s * 1)) + self.assertNotEqual(id(s), id(1 * s)) + self.assertNotEqual(id(s), id(s * 2)) + class ByteArrayTest(BaseBytesTest, unittest.TestCase): type2test = bytearray diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index efed3a859ba217..9965c1fe2e5f17 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -1,6 +1,7 @@ from test import support from test.support import bigmemtest, _4G +import array import unittest from io import BytesIO, DEFAULT_BUFFER_SIZE import os @@ -620,6 +621,14 @@ def test_read_truncated(self): with BZ2File(BytesIO(truncated[:i])) as f: self.assertRaises(EOFError, f.read, 1) + def test_issue44439(self): + q = array.array('Q', [1, 2, 3, 4, 5]) + LENGTH = len(q) * q.itemsize + + with BZ2File(BytesIO(), 'w') as f: + self.assertEqual(f.write(q), LENGTH) + self.assertEqual(f.tell(), LENGTH) + class BZ2CompressorTest(BaseTest): def testCompress(self): @@ -996,15 +1005,9 @@ def test_newline(self): self.assertEqual(f.readlines(), [text]) -def test_main(): - support.run_unittest( - BZ2FileTest, - BZ2CompressorTest, - BZ2DecompressorTest, - CompressDecompressTest, - OpenTest, - ) +def tearDownModule(): support.reap_children() + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index fcc85992345dbc..71f934756e26a1 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -427,12 +427,9 @@ def test_PYTHONCOERCECLOCALE_set_to_one(self): self.assertEqual(cmd.stdout.rstrip(), loc) -def test_main(): - support.run_unittest( - LocaleConfigurationTests, - LocaleCoercionTests - ) +def tearDownModule(): support.reap_children() + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 1b18bfad553007..ccb9d5383d6bed 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -264,7 +264,7 @@ def test_return_result_with_error(self): def test_getitem_with_error(self): # Test _Py_CheckSlotResult(). Raise an exception and then calls - # PyObject_GetItem(): check that the assertion catchs the bug. + # PyObject_GetItem(): check that the assertion catches the bug. # PyObject_GetItem() must not be called with an exception set. code = textwrap.dedent(""" import _testcapi @@ -619,6 +619,26 @@ def test_fatal_error(self): ''') self.check_fatal_error(code, expected) + def test_pyobject_repr_from_null(self): + s = _testcapi.pyobject_repr_from_null() + self.assertEqual(s, '') + + def test_pyobject_str_from_null(self): + s = _testcapi.pyobject_str_from_null() + self.assertEqual(s, '') + + def test_pyobject_bytes_from_null(self): + s = _testcapi.pyobject_bytes_from_null() + self.assertEqual(s, b'') + + def test_Py_CompileString(self): + # Check that Py_CompileString respects the coding cookie + _compile = _testcapi.Py_CompileString + code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" + result = _compile(code) + expected = compile(code, "", "exec") + self.assertEqual(result.co_consts, expected.co_consts) + class TestPendingCalls(unittest.TestCase): @@ -635,11 +655,11 @@ def callback(): #unsuccessful. while True: if _testcapi._pending_threadfunc(callback): - break; + break def pendingcalls_wait(self, l, n, context = None): #now, stick around until l[0] has grown to 10 - count = 0; + count = 0 while len(l) != n: #this busy loop is where we expect to be interrupted to #run our callbacks. Note that callbacks are only run on the @@ -750,6 +770,37 @@ def test_mutate_exception(self): self.assertFalse(hasattr(binascii.Error, "foobar")) + def test_module_state_shared_in_global(self): + """ + bpo-44050: Extension module state should be shared between interpreters + when it doesn't support sub-interpreters. + """ + r, w = os.pipe() + self.addCleanup(os.close, r) + self.addCleanup(os.close, w) + + script = textwrap.dedent(f""" + import importlib.machinery + import importlib.util + import os + + fullname = '_test_module_state_shared' + origin = importlib.util.find_spec('_testmultiphase').origin + loader = importlib.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + attr_id = str(id(module.Error)).encode() + + os.write({w}, attr_id) + """) + exec(script) + main_attr_id = os.read(r, 100) + + ret = support.run_in_subinterp(script) + self.assertEqual(ret, 0) + subinterp_attr_id = os.read(r, 100) + self.assertEqual(main_attr_id, subinterp_attr_id) + class TestThreadState(unittest.TestCase): @@ -799,8 +850,13 @@ class PyMemDebugTests(unittest.TestCase): def check(self, code): with support.SuppressCrashReport(): - out = assert_python_failure('-c', code, - PYTHONMALLOC=self.PYTHONMALLOC) + out = assert_python_failure( + '-c', code, + PYTHONMALLOC=self.PYTHONMALLOC, + # FreeBSD: instruct jemalloc to not fill freed() memory + # with junk byte 0x5a, see JEMALLOC(3) + MALLOC_CONF="junk:false", + ) stderr = out.err return stderr.decode('ascii', 'replace') @@ -870,7 +926,11 @@ def check_pyobject_is_freed(self, func_name): except _testcapi.error: os._exit(1) ''') - assert_python_ok('-c', code, PYTHONMALLOC=self.PYTHONMALLOC) + assert_python_ok( + '-c', code, + PYTHONMALLOC=self.PYTHONMALLOC, + MALLOC_CONF="junk:false", + ) def test_pyobject_null_is_freed(self): self.check_pyobject_is_freed('check_pyobject_null_is_freed') diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index cbf9ff2a863c3c..d93e98f372532f 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -864,9 +864,10 @@ def test_tokenizer_error_with_stdin(self): def test_decoding_error_at_the_end_of_the_line(self): self.check_string(br"'\u1f'") -def test_main(): - support.run_unittest(CmdLineTest, IgnoreEnvironmentTest, SyntaxErrorTests) + +def tearDownModule(): support.reap_children() + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index af29c171d4282f..c93ed5be7fbde8 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -651,7 +651,7 @@ def test_syntaxerror_invalid_escape_sequence_multi_line(self): stderr.splitlines()[-3:], [ b' foo = """\\q"""', b' ^^^^^^^^', - b'SyntaxError: invalid escape sequence \\q' + b'SyntaxError: invalid escape sequence \'\\q\'' ], ) @@ -739,9 +739,9 @@ def test_nonexisting_script(self): self.assertNotEqual(proc.returncode, 0) -def test_main(): - support.run_unittest(CmdLineTest) +def tearDownModule(): support.reap_children() + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index 6aaf04ca6dde5e..b9c4f8bdcb382e 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -135,7 +135,7 @@ except ImportError: ctypes = None from test.support import (run_doctest, run_unittest, cpython_only, - check_impl_detail) + check_impl_detail, gc_collect) def consts(t): @@ -213,7 +213,7 @@ def func(): pass CodeType = type(co) # test code constructor - return CodeType(co.co_argcount, + CodeType(co.co_argcount, co.co_posonlyargcount, co.co_kwonlyargcount, co.co_nlocals, @@ -343,6 +343,7 @@ def callback(code): coderef = weakref.ref(f.__code__, callback) self.assertTrue(bool(coderef())) del f + gc_collect() # For PyPy or other GCs. self.assertFalse(bool(coderef())) self.assertTrue(self.called) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 328a47b2e37669..f7310fbb1474ae 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -114,7 +114,7 @@ def check_partial(self, input, partialresults): q = Queue(b"") r = codecs.getreader(self.encoding)(q) result = "" - for (c, partialresult) in zip(input.encode(self.encoding), partialresults): + for (c, partialresult) in zip(input.encode(self.encoding), partialresults, strict=True): q.write(bytes([c])) result += r.read() self.assertEqual(result, partialresult) @@ -125,7 +125,7 @@ def check_partial(self, input, partialresults): # do the check again, this time using an incremental decoder d = codecs.getincrementaldecoder(self.encoding)() result = "" - for (c, partialresult) in zip(input.encode(self.encoding), partialresults): + for (c, partialresult) in zip(input.encode(self.encoding), partialresults, strict=True): result += d.decode(bytes([c])) self.assertEqual(result, partialresult) # check that there's nothing left in the buffers @@ -135,7 +135,7 @@ def check_partial(self, input, partialresults): # Check whether the reset method works properly d.reset() result = "" - for (c, partialresult) in zip(input.encode(self.encoding), partialresults): + for (c, partialresult) in zip(input.encode(self.encoding), partialresults, strict=True): result += d.decode(bytes([c])) self.assertEqual(result, partialresult) # check that there's nothing left in the buffers @@ -2341,7 +2341,11 @@ def test_unicode_escape(self): (r"\x5c\x55\x30\x30\x31\x31\x30\x30\x30\x30", 10)) -class UnicodeEscapeTest(unittest.TestCase): +class UnicodeEscapeTest(ReadTest, unittest.TestCase): + encoding = "unicode-escape" + + test_lone_surrogates = None + def test_empty(self): self.assertEqual(codecs.unicode_escape_encode(""), (b"", 0)) self.assertEqual(codecs.unicode_escape_decode(b""), ("", 0)) @@ -2428,8 +2432,50 @@ def test_decode_errors(self): self.assertEqual(decode(br"\U00110000", "ignore"), ("", 10)) self.assertEqual(decode(br"\U00110000", "replace"), ("\ufffd", 10)) + def test_partial(self): + self.check_partial( + "\x00\t\n\r\\\xff\uffff\U00010000", + [ + '', + '', + '', + '\x00', + '\x00', + '\x00\t', + '\x00\t', + '\x00\t\n', + '\x00\t\n', + '\x00\t\n\r', + '\x00\t\n\r', + '\x00\t\n\r\\', + '\x00\t\n\r\\', + '\x00\t\n\r\\', + '\x00\t\n\r\\', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff\U00010000', + ] + ) + +class RawUnicodeEscapeTest(ReadTest, unittest.TestCase): + encoding = "raw-unicode-escape" + + test_lone_surrogates = None -class RawUnicodeEscapeTest(unittest.TestCase): def test_empty(self): self.assertEqual(codecs.raw_unicode_escape_encode(""), (b"", 0)) self.assertEqual(codecs.raw_unicode_escape_decode(b""), ("", 0)) @@ -2478,6 +2524,35 @@ def test_decode_errors(self): self.assertEqual(decode(br"\U00110000", "ignore"), ("", 10)) self.assertEqual(decode(br"\U00110000", "replace"), ("\ufffd", 10)) + def test_partial(self): + self.check_partial( + "\x00\t\n\r\\\xff\uffff\U00010000", + [ + '\x00', + '\x00\t', + '\x00\t\n', + '\x00\t\n\r', + '\x00\t\n\r', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff', + '\x00\t\n\r\\\xff\uffff\U00010000', + ] + ) + class EscapeEncodeTest(unittest.TestCase): diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index 07b46afbe1bd89..17376c7ed7537e 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -182,21 +182,21 @@ def test_incomplete(self): ai("from a import (b,c") ai("from a import (b,c,") - ai("["); - ai("[a"); - ai("[a,"); - ai("[a,b"); - ai("[a,b,"); - - ai("{"); - ai("{a"); - ai("{a:"); - ai("{a:b"); - ai("{a:b,"); - ai("{a:b,c"); - ai("{a:b,c:"); - ai("{a:b,c:d"); - ai("{a:b,c:d,"); + ai("[") + ai("[a") + ai("[a,") + ai("[a,b") + ai("[a,b,") + + ai("{") + ai("{a") + ai("{a:") + ai("{a:b") + ai("{a:b,") + ai("{a:b,c") + ai("{a:b,c:") + ai("{a:b,c:d") + ai("{a:b,c:d,") ai("a(") ai("a(b") diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index f98048b34a7a1d..3404b8ad1bcf73 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -668,6 +668,7 @@ class Point(namedtuple('_Point', ['x', 'y'])): a.w = 5 self.assertEqual(a.__dict__, {'w': 5}) + @support.cpython_only def test_field_descriptor(self): Point = namedtuple('Point', 'x y') p = Point(11, 22) @@ -1594,7 +1595,7 @@ def assertSameSet(self, s1, s2): self.assertSetEqual(set(s1), set(s2)) def test_Set_from_iterable(self): - """Verify _from_iterable overriden to an instance method works.""" + """Verify _from_iterable overridden to an instance method works.""" class SetUsingInstanceFromIterable(MutableSet): def __init__(self, values, created_by): if not created_by: @@ -1801,6 +1802,18 @@ def __repr__(self): self.assertTrue(f1 != l1) self.assertTrue(f1 != l2) + def test_Set_hash_matches_frozenset(self): + sets = [ + {}, {1}, {None}, {-1}, {0.0}, {"abc"}, {1, 2, 3}, + {10**100, 10**101}, {"a", "b", "ab", ""}, {False, True}, + {object(), object(), object()}, {float("nan")}, {frozenset()}, + {*range(1000)}, {*range(1000)} - {100, 200, 300}, + {*range(sys.maxsize - 10, sys.maxsize + 10)}, + ] + for s in sets: + fs = frozenset(s) + self.assertEqual(hash(fs), Set._hash(fs), msg=s) + def test_Mapping(self): for sample in [dict]: self.assertIsInstance(sample(), Mapping) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index d40347c3c6bb3e..5f80a583450eaa 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -162,7 +162,7 @@ def test_literals_with_leading_zeroes(self): for arg in ["077787", "0xj", "0x.", "0e", "090000000000000", "080000000000000", "000000000000009", "000000000000008", "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2", - "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0777", + "0b101j", "0o153j", "0b100e1", "0o777e1", "0777", "000777", "000000000000007"]: self.assertRaises(SyntaxError, eval, arg) @@ -502,6 +502,7 @@ def test_single_statement(self): self.compile_single("if x:\n f(x)") self.compile_single("if x:\n f(x)\nelse:\n g(x)") self.compile_single("class T:\n pass") + self.compile_single("c = '''\na=1\nb=2\nc=3\n'''") def test_bad_single_statement(self): self.assertInvalidSingle('1\n2') @@ -512,6 +513,7 @@ def test_bad_single_statement(self): self.assertInvalidSingle('f()\n# blah\nblah()') self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + self.assertInvalidSingle("c = '''\nd=1\n'''\na = 1\n\nb = 2\n") def test_particularly_evil_undecodable(self): # Issue 24022 @@ -648,6 +650,17 @@ def test_merge_code_attrs(self): self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable) self.assertIs(f1.__code__.co_code, f2.__code__.co_code) + # Stripping unused constants is not a strict requirement for the + # Python semantics, it's a more an implementation detail. + @support.cpython_only + def test_strip_unused_consts(self): + # Python 3.10rc1 appended None to co_consts when None is not used + # at all. See bpo-45056. + def f1(): + "docstring" + return 42 + self.assertEqual(f1.__code__.co_consts, ("docstring", 42)) + # This is a regression test for a CPython specific peephole optimizer # implementation bug present in a few releases. It's assertion verifies # that peephole optimization was actually done though that isn't an @@ -895,6 +908,31 @@ def aug_store_attr(): for (_, _, line) in func.__code__.co_lines() ] self.assertEqual(lines, code_lines) + def test_line_number_genexp(self): + + def return_genexp(): + return (1 + for + x + in + y) + genexp_lines = [None, 1, 3, 1] + + genexp_code = return_genexp.__code__.co_consts[1] + code_lines = [ None if line is None else line-return_genexp.__code__.co_firstlineno + for (_, _, line) in genexp_code.co_lines() ] + self.assertEqual(genexp_lines, code_lines) + + def test_line_number_implicit_return_after_async_for(self): + + async def test(aseq): + async for i in aseq: + body + + expected_lines = [None, 1, 2, 1] + code_lines = [ None if line is None else line-test.__code__.co_firstlineno + for (_, _, line) in test.__code__.co_lines() ] + self.assertEqual(expected_lines, code_lines) def test_big_dict_literal(self): # The compiler has a flushing point in "compiler_dict" that calls compiles diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 96a0f8f729aa4e..9e15ecf3aae299 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -80,9 +80,30 @@ def timestamp_metadata(self): with open(self.bc_path, 'rb') as file: data = file.read(12) mtime = int(os.stat(self.source_path).st_mtime) - compare = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, 0, mtime) + compare = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, 0, + mtime & 0xFFFF_FFFF) return data, compare + def test_year_2038_mtime_compilation(self): + # Test to make sure we can handle mtimes larger than what a 32-bit + # signed number can hold as part of bpo-34990 + try: + os.utime(self.source_path, (2**32 - 1, 2**32 - 1)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support timestamps near 2**32") + with contextlib.redirect_stdout(io.StringIO()): + self.assertTrue(compileall.compile_file(self.source_path)) + + def test_larger_than_32_bit_times(self): + # This is similar to the test above but we skip it if the OS doesn't + # support modification times larger than 32-bits. + try: + os.utime(self.source_path, (2**35, 2**35)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support large timestamps") + with contextlib.redirect_stdout(io.StringIO()): + self.assertTrue(compileall.compile_file(self.source_path)) + def recreation_check(self, metadata): """Check that compileall recreates bytecode when the new metadata is used.""" @@ -101,7 +122,7 @@ def recreation_check(self, metadata): def test_mtime(self): # Test a change in mtime leads to a new .pyc. - self.recreation_check(struct.pack('<4sll', importlib.util.MAGIC_NUMBER, + self.recreation_check(struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, 0, 1)) def test_magic_number(self): @@ -169,6 +190,14 @@ def test_no_pycache_in_non_package(self): compileall.compile_file(data_file) self.assertFalse(os.path.exists(os.path.join(data_dir, '__pycache__'))) + + def test_compile_file_encoding_fallback(self): + # Bug 44666 reported that compile_file failed when sys.stdout.encoding is None + self.add_bad_source_file() + with contextlib.redirect_stdout(io.StringIO()): + self.assertFalse(compileall.compile_file(self.bad_source_path)) + + def test_optimize(self): # make sure compiling with different optimization settings than the # interpreter's creates the correct file names diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index af39ee878dc913..c6a261b418b543 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -1,4 +1,5 @@ import unittest +import sys from test import support from test.test_grammar import (VALID_UNDERSCORE_LITERALS, INVALID_UNDERSCORE_LITERALS) @@ -248,6 +249,54 @@ def test_pow(self): b = 5.1+2.3j self.assertRaises(ValueError, pow, a, b, 0) + # Check some boundary conditions; some of these used to invoke + # undefined behaviour (https://bugs.python.org/issue44698). We're + # not actually checking the results of these operations, just making + # sure they don't crash (for example when using clang's + # UndefinedBehaviourSanitizer). + values = (sys.maxsize, sys.maxsize+1, sys.maxsize-1, + -sys.maxsize, -sys.maxsize+1, -sys.maxsize+1) + for real in values: + for imag in values: + with self.subTest(real=real, imag=imag): + c = complex(real, imag) + try: + c ** real + except OverflowError: + pass + try: + c ** c + except OverflowError: + pass + + def test_pow_with_small_integer_exponents(self): + # Check that small integer exponents are handled identically + # regardless of their type. + values = [ + complex(5.0, 12.0), + complex(5.0e100, 12.0e100), + complex(-4.0, INF), + complex(INF, 0.0), + ] + exponents = [-19, -5, -3, -2, -1, 0, 1, 2, 3, 5, 19] + for value in values: + for exponent in exponents: + with self.subTest(value=value, exponent=exponent): + try: + int_pow = value**exponent + except OverflowError: + int_pow = "overflow" + try: + float_pow = value**float(exponent) + except OverflowError: + float_pow = "overflow" + try: + complex_pow = value**complex(exponent) + except OverflowError: + complex_pow = "overflow" + self.assertEqual(str(float_pow), str(int_pow)) + self.assertEqual(str(complex_pow), str(int_pow)) + def test_boolcontext(self): for i in range(100): self.assertTrue(complex(random() + 1e-6, random() + 1e-6)) @@ -728,8 +777,6 @@ def test_format(self): self.assertEqual(format(complex(INF, 1), 'F'), 'INF+1.000000j') self.assertEqual(format(complex(INF, -1), 'F'), 'INF-1.000000j') -def test_main(): - support.run_unittest(ComplexTest) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 99651f5f4ed4da..29e041deeca57f 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -463,6 +463,7 @@ def test_thread_names_assigned(self): executor.map(abs, range(-5, 5)) threads = executor._threads del executor + support.gc_collect() # For PyPy or other GCs. for t in threads: self.assertRegex(t.name, r'^SpecialPool_[0-4]$') @@ -473,6 +474,7 @@ def test_thread_names_default(self): executor.map(abs, range(-5, 5)) threads = executor._threads del executor + support.gc_collect() # For PyPy or other GCs. for t in threads: # Ensure that our default name is reasonably sane and unique when @@ -535,6 +537,7 @@ def test_del_shutdown(self): call_queue = executor._call_queue executor_manager_thread = executor._executor_manager_thread del executor + support.gc_collect() # For PyPy or other GCs. # Make sure that all the executor resources were properly cleaned by # the shutdown process @@ -576,6 +579,14 @@ def test_shutdown_no_wait(self): class WaitTests: + def test_20369(self): + # See https://bugs.python.org/issue20369 + future = self.executor.submit(time.sleep, 1.5) + done, not_done = futures.wait([future, future], + return_when=futures.ALL_COMPLETED) + self.assertEqual({future}, done) + self.assertEqual(set(), not_done) + def test_first_completed(self): future1 = self.executor.submit(mul, 21, 2) @@ -759,6 +770,7 @@ def test_free_reference_yielded_future(self): futures_list.remove(future) wr = weakref.ref(future) del future + support.gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) futures_list[0].set_result("test") @@ -766,6 +778,7 @@ def test_free_reference_yielded_future(self): futures_list.remove(future) wr = weakref.ref(future) del future + support.gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) if futures_list: futures_list[0].set_result("test") @@ -865,6 +878,7 @@ def test_free_reference(self): for obj in self.executor.map(make_dummy_object, range(10)): wr = weakref.ref(obj) del obj + support.gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) @@ -905,6 +919,20 @@ def test_idle_thread_reuse(self): self.assertEqual(len(executor._threads), 1) executor.shutdown(wait=True) + @unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork') + def test_hang_global_shutdown_lock(self): + # bpo-45021: _global_shutdown_lock should be reinitialized in the child + # process, otherwise it will never exit + def submit(pool): + pool.submit(submit, pool) + + with futures.ThreadPoolExecutor(1) as pool: + pool.submit(submit, pool) + + for _ in range(50): + with futures.ProcessPoolExecutor(1, mp_context=get_context('fork')) as workers: + workers.submit(tuple) + class ProcessPoolExecutorTest(ExecutorTest): @@ -1509,16 +1537,10 @@ def test_multiple_set_exception(self): self.assertEqual(f.exception(), e) -_threads_key = None - def setUpModule(): - global _threads_key - _threads_key = threading_helper.threading_setup() - - -def tearDownModule(): - threading_helper.threading_cleanup(*_threads_key) - multiprocessing.util._cleanup_tests() + unittest.addModuleCleanup(multiprocessing.util._cleanup_tests) + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == "__main__": diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 9373a62072ef47..e9b03e6c62ef14 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -79,6 +79,7 @@ def basic_test(self, cf): 'Spacey Bar', 'Spacey Bar From The Beginning', 'Types', + 'This One Has A ] In It', ] if self.allow_no_value: @@ -130,6 +131,7 @@ def basic_test(self, cf): eq(cf.get('Types', 'float'), "0.44") eq(cf.getboolean('Types', 'boolean'), False) eq(cf.get('Types', '123'), 'strange but acceptable') + eq(cf.get('This One Has A ] In It', 'forks'), 'spoons') if self.allow_no_value: eq(cf.get('NoValue', 'option-without-value'), None) @@ -320,6 +322,8 @@ def test_basic(self): float {0[0]} 0.44 boolean {0[0]} NO 123 {0[1]} strange but acceptable +[This One Has A ] In It] + forks {0[0]} spoons """.format(self.delimiters, self.comment_prefixes) if self.allow_no_value: config_string += ( @@ -394,6 +398,9 @@ def test_basic_from_dict(self): "boolean": False, 123: "strange but acceptable", }, + "This One Has A ] In It": { + "forks": "spoons" + }, } if self.allow_no_value: config.update({ diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index 453ef6c9f0832f..fbaae2dd09fd95 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -126,19 +126,22 @@ def woohoo(): self.assertEqual(state, [1, 42, 999]) def test_contextmanager_except_stopiter(self): - stop_exc = StopIteration('spam') @contextmanager def woohoo(): yield - try: - with self.assertWarnsRegex(DeprecationWarning, - "StopIteration"): - with woohoo(): - raise stop_exc - except Exception as ex: - self.assertIs(ex, stop_exc) - else: - self.fail('StopIteration was suppressed') + + class StopIterationSubclass(StopIteration): + pass + + for stop_exc in (StopIteration('spam'), StopIterationSubclass('spam')): + with self.subTest(type=type(stop_exc)): + try: + with woohoo(): + raise stop_exc + except Exception as ex: + self.assertIs(ex, stop_exc) + else: + self.fail(f'{stop_exc} was suppressed') def test_contextmanager_except_pep479(self): code = """\ @@ -228,6 +231,8 @@ class A: def woohoo(a, b): a = weakref.ref(a) b = weakref.ref(b) + # Allow test to work with a non-refcounted GC + support.gc_collect() self.assertIsNone(a()) self.assertIsNone(b()) yield @@ -775,6 +780,40 @@ def suppress_exc(*exc_details): self.assertIsInstance(inner_exc, ValueError) self.assertIsInstance(inner_exc.__context__, ZeroDivisionError) + def test_exit_exception_explicit_none_context(self): + # Ensure ExitStack chaining matches actual nested `with` statements + # regarding explicit __context__ = None. + + class MyException(Exception): + pass + + @contextmanager + def my_cm(): + try: + yield + except BaseException: + exc = MyException() + try: + raise exc + finally: + exc.__context__ = None + + @contextmanager + def my_cm_with_exit_stack(): + with self.exit_stack() as stack: + stack.enter_context(my_cm()) + yield stack + + for cm in (my_cm, my_cm_with_exit_stack): + with self.subTest(): + try: + with cm(): + raise IndexError() + except MyException as exc: + self.assertIsNone(exc.__context__) + else: + self.fail("Expected IndexError, but no exception was raised") + def test_exit_exception_non_suppressing(self): # http://bugs.python.org/issue19092 def raise_exc(exc): diff --git a/Lib/test/test_contextlib_async.py b/Lib/test/test_contextlib_async.py index 290ef05b82a801..127d7500656a59 100644 --- a/Lib/test/test_contextlib_async.py +++ b/Lib/test/test_contextlib_async.py @@ -1,7 +1,7 @@ import asyncio from contextlib import ( asynccontextmanager, AbstractAsyncContextManager, - AsyncExitStack, nullcontext, aclosing) + AsyncExitStack, nullcontext, aclosing, contextmanager) import functools from test import support import unittest @@ -209,7 +209,18 @@ async def test_contextmanager_except_stopiter(self): async def woohoo(): yield - for stop_exc in (StopIteration('spam'), StopAsyncIteration('ham')): + class StopIterationSubclass(StopIteration): + pass + + class StopAsyncIterationSubclass(StopAsyncIteration): + pass + + for stop_exc in ( + StopIteration('spam'), + StopAsyncIteration('ham'), + StopIterationSubclass('spam'), + StopAsyncIterationSubclass('spam') + ): with self.subTest(type=type(stop_exc)): try: async with woohoo(): @@ -346,14 +357,17 @@ async def aclose(self): async def test_aclosing_bpo41229(self): state = [] - class Resource: - def __del__(self): + @contextmanager + def sync_resource(): + try: + yield + finally: state.append(1) async def agenfunc(): - r = Resource() - yield -1 - yield -2 + with sync_resource(): + yield -1 + yield -2 x = agenfunc() self.assertEqual(state, []) @@ -538,6 +552,41 @@ async def suppress_exc(*exc_details): self.assertIsInstance(inner_exc, ValueError) self.assertIsInstance(inner_exc.__context__, ZeroDivisionError) + @_async_test + async def test_async_exit_exception_explicit_none_context(self): + # Ensure AsyncExitStack chaining matches actual nested `with` statements + # regarding explicit __context__ = None. + + class MyException(Exception): + pass + + @asynccontextmanager + async def my_cm(): + try: + yield + except BaseException: + exc = MyException() + try: + raise exc + finally: + exc.__context__ = None + + @asynccontextmanager + async def my_cm_with_exit_stack(): + async with self.exit_stack() as stack: + await stack.enter_async_context(my_cm()) + yield stack + + for cm in (my_cm, my_cm_with_exit_stack): + with self.subTest(): + try: + async with cm(): + raise IndexError() + except MyException as exc: + self.assertIsNone(exc.__context__) + else: + self.fail("Expected IndexError, but no exception was raised") + class TestAsyncNullcontext(unittest.TestCase): @_async_test diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py index ba3d233f63d1c1..f1ca8cb254d188 100644 --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -7,6 +7,7 @@ from operator import le, lt, ge, gt, eq, ne import unittest +from test import support order_comparisons = le, lt, ge, gt equality_comparisons = eq, ne @@ -805,6 +806,7 @@ class C(object): self.assertEqual(v[c], d) self.assertEqual(len(v), 2) del c, d + support.gc_collect() # For PyPy or other GCs. self.assertEqual(len(v), 1) x, y = C(), C() # The underlying containers are decoupled @@ -834,6 +836,7 @@ def __init__(self, i): self.assertEqual(v[a].i, b.i) self.assertEqual(v[c].i, d.i) del c + support.gc_collect() # For PyPy or other GCs. self.assertEqual(len(v), 1) def test_deepcopy_weakvaluedict(self): @@ -857,6 +860,7 @@ def __init__(self, i): self.assertIs(t, d) del x, y, z, t del d + support.gc_collect() # For PyPy or other GCs. self.assertEqual(len(v), 1) def test_deepcopy_bound_method(self): diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 145adb67781701..a6a199e323c5f9 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -1205,41 +1205,47 @@ class CM: def __aenter__(self): pass - body_executed = False + body_executed = None async def foo(): + nonlocal body_executed + body_executed = False async with CM(): body_executed = True with self.assertRaisesRegex(AttributeError, '__aexit__'): run_async(foo()) - self.assertFalse(body_executed) + self.assertIs(body_executed, False) def test_with_3(self): class CM: def __aexit__(self): pass - body_executed = False + body_executed = None async def foo(): + nonlocal body_executed + body_executed = False async with CM(): body_executed = True with self.assertRaisesRegex(AttributeError, '__aenter__'): run_async(foo()) - self.assertFalse(body_executed) + self.assertIs(body_executed, False) def test_with_4(self): class CM: pass - body_executed = False + body_executed = None async def foo(): + nonlocal body_executed + body_executed = False async with CM(): body_executed = True with self.assertRaisesRegex(AttributeError, '__aenter__'): run_async(foo()) - self.assertFalse(body_executed) + self.assertIs(body_executed, False) def test_with_5(self): # While this test doesn't make a lot of sense, diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 2411a91110dd43..6e5dfc63d43cef 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -157,7 +157,7 @@ def test_write_arg_valid(self): self._write_error_test(OSError, BadIterable()) class BadList: def __len__(self): - return 10; + return 10 def __getitem__(self, i): if i > 2: raise OSError @@ -458,9 +458,15 @@ class testC(csv.excel): class testUni(csv.excel): delimiter = "\u039B" + class unspecified(): + # A class to pass as dialect but with no dialect attributes. + pass + csv.register_dialect('testC', testC) try: self.compare_dialect_123("1,2,3\r\n") + self.compare_dialect_123("1,2,3\r\n", dialect=None) + self.compare_dialect_123("1,2,3\r\n", dialect=unspecified) self.compare_dialect_123("1\t2\t3\r\n", testA) self.compare_dialect_123("1:2:3\r\n", dialect=testB()) self.compare_dialect_123("1|2|3\r\n", dialect='testC') @@ -891,7 +897,7 @@ class mydialect(csv.Dialect): with self.assertRaises(csv.Error) as cm: mydialect() self.assertEqual(str(cm.exception), - '"quotechar" must be string, not int') + '"quotechar" must be string or None, not int') def test_delimiter(self): class mydialect(csv.Dialect): @@ -928,6 +934,35 @@ class mydialect(csv.Dialect): self.assertEqual(str(cm.exception), '"delimiter" must be string, not int') + mydialect.delimiter = None + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + '"delimiter" must be string, not NoneType') + + def test_escapechar(self): + class mydialect(csv.Dialect): + delimiter = ";" + escapechar = '\\' + doublequote = False + skipinitialspace = True + lineterminator = '\r\n' + quoting = csv.QUOTE_NONE + d = mydialect() + self.assertEqual(d.escapechar, "\\") + + mydialect.escapechar = "**" + with self.assertRaisesRegex(csv.Error, '"escapechar" must be a 1-character string'): + mydialect() + + mydialect.escapechar = b"*" + with self.assertRaisesRegex(csv.Error, '"escapechar" must be string or None, not bytes'): + mydialect() + + mydialect.escapechar = 4 + with self.assertRaisesRegex(csv.Error, '"escapechar" must be string or None, not int'): + mydialect() + def test_lineterminator(self): class mydialect(csv.Dialect): delimiter = ";" @@ -1014,6 +1049,42 @@ class TestSniffer(unittest.TestCase): 'Stonecutters ''Seafood'' and Chop House'+ 'Lemont'+ 'IL'+ '12/19/02'+ 'Week Back' """ + sample10 = dedent(""" + abc,def + ghijkl,mno + ghi,jkl + """) + + sample11 = dedent(""" + abc,def + ghijkl,mnop + ghi,jkl + """) + + sample12 = dedent(""""time","forces" + 1,1.5 + 0.5,5+0j + 0,0 + 1+1j,6 + """) + + sample13 = dedent(""""time","forces" + 0,0 + 1,2 + a,b + """) + + def test_issue43625(self): + sniffer = csv.Sniffer() + self.assertTrue(sniffer.has_header(self.sample12)) + self.assertFalse(sniffer.has_header(self.sample13)) + + def test_has_header_strings(self): + "More to document existing (unexpected?) behavior than anything else." + sniffer = csv.Sniffer() + self.assertFalse(sniffer.has_header(self.sample10)) + self.assertFalse(sniffer.has_header(self.sample11)) + def test_has_header(self): sniffer = csv.Sniffer() self.assertIs(sniffer.has_header(self.sample1), False) @@ -1237,6 +1308,9 @@ def test__all__(self): extra = {'__doc__', '__version__'} support.check__all__(self, csv, ('csv', '_csv'), extra=extra) + def test_subclassable(self): + # issue 44089 + class Foo(csv.Error): ... if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 8bf48a6454d691..d3c152c42cf62f 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -6,7 +6,8 @@ import tempfile import unittest -from test.support import requires, verbose, SaveSignals, cpython_only +from test.support import (requires, verbose, SaveSignals, cpython_only, + check_disallow_instantiation) from test.support.import_helper import import_module # Optionally test curses module. This currently requires that the @@ -1052,7 +1053,7 @@ def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) w = curses.newwin(10, 10) panel = curses.panel.new_panel(w) - self.assertRaises(TypeError, type(panel)) + check_disallow_instantiation(self, type(panel)) @requires_curses_func('is_term_resized') def test_is_term_resized(self): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 8e645aeb4a7503..ef5009ab116776 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -8,9 +8,10 @@ import pickle import inspect import builtins +import types import unittest from unittest.mock import Mock -from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional +from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol from typing import get_type_hints from collections import deque, OrderedDict, namedtuple from functools import total_ordering @@ -1126,6 +1127,10 @@ def test_init_var_preserve_type(self): self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') self.assertEqual(repr(InitVar[List[int]]), 'dataclasses.InitVar[typing.List[int]]') + self.assertEqual(repr(InitVar[list[int]]), + 'dataclasses.InitVar[list[int]]') + self.assertEqual(repr(InitVar[int|str]), + 'dataclasses.InitVar[int | str]') def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not @@ -1350,6 +1355,17 @@ class B: with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): replace(obj, x=0) + def test_is_dataclass_genericalias(self): + @dataclass + class A(types.GenericAlias): + origin: type + args: type + self.assertTrue(is_dataclass(A)) + a = A(list, int) + self.assertTrue(is_dataclass(type(a))) + self.assertTrue(is_dataclass(a)) + + def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. @@ -1907,7 +1923,7 @@ class Parent(Generic[T]): # Check MRO resolution. self.assertEqual(Child.__mro__, (Child, Parent, Generic, object)) - def test_dataclassses_pickleable(self): + def test_dataclasses_pickleable(self): global P, Q, R @dataclass class P: @@ -2150,6 +2166,26 @@ def __init__(self, x): self.x = 2 * x self.assertEqual(C(5).x, 10) + def test_inherit_from_protocol(self): + # Dataclasses inheriting from protocol should preserve their own `__init__`. + # See bpo-45081. + + class P(Protocol): + a: int + + @dataclass + class C(P): + a: int + + self.assertEqual(C(5).a, 5) + + @dataclass + class D(P): + def __init__(self, a): + self.a = a * 2 + + self.assertEqual(D(5).a, 10) + class TestRepr(unittest.TestCase): def test_repr(self): @@ -2839,13 +2875,48 @@ class FrozenSlotsClass: foo: str bar: int + @dataclass(frozen=True) + class FrozenWithoutSlotsClass: + foo: str + bar: int + def test_frozen_pickle(self): # bpo-43999 - assert self.FrozenSlotsClass.__slots__ == ("foo", "bar") - p = pickle.dumps(self.FrozenSlotsClass("a", 1)) - assert pickle.loads(p) == self.FrozenSlotsClass("a", 1) + self.assertEqual(self.FrozenSlotsClass.__slots__, ("foo", "bar")) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + obj = self.FrozenSlotsClass("a", 1) + p = pickle.loads(pickle.dumps(obj, protocol=proto)) + self.assertIsNot(obj, p) + self.assertEqual(obj, p) + + obj = self.FrozenWithoutSlotsClass("a", 1) + p = pickle.loads(pickle.dumps(obj, protocol=proto)) + self.assertIsNot(obj, p) + self.assertEqual(obj, p) + + def test_slots_with_default_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default='b', init=False) + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') + + def test_slots_with_default_factory_no_init(self): + # Originally reported in bpo-44649. + @dataclass(slots=True) + class A: + a: str + b: str = field(default_factory=lambda:'b', init=False) + + obj = A("a") + self.assertEqual(obj.a, 'a') + self.assertEqual(obj.b, 'b') class TestDescriptors(unittest.TestCase): def test_set_name(self): @@ -3675,7 +3746,7 @@ class B: with self.assertRaisesRegex(TypeError, msg): B(3, 4, 5) - # Explicitely make a field that follows KW_ONLY be non-keyword-only. + # Explicitly make a field that follows KW_ONLY be non-keyword-only. @dataclass class C: a: int @@ -3831,5 +3902,16 @@ class A: c: int = 1 d: int + def test_make_dataclass(self): + A = make_dataclass("A", ['a'], kw_only=True) + self.assertTrue(fields(A)[0].kw_only) + + B = make_dataclass("B", + ['a', ('b', int, field(kw_only=False))], + kw_only=True) + self.assertTrue(fields(B)[0].kw_only) + self.assertFalse(fields(B)[1].kw_only) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index bdb9f02e5756a2..7f9094fa7bd4e6 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -1,59 +1,57 @@ import unittest import sys -from test.support import run_unittest from test.support.import_helper import import_fresh_module TESTS = 'test.datetimetester' -try: - pure_tests = import_fresh_module(TESTS, fresh=['datetime', '_strptime'], - blocked=['_datetime']) - fast_tests = import_fresh_module(TESTS, fresh=['datetime', - '_datetime', '_strptime']) -finally: - # XXX: import_fresh_module() is supposed to leave sys.module cache untouched, - # XXX: but it does not, so we have to cleanup ourselves. - for modname in ['datetime', '_datetime', '_strptime']: - sys.modules.pop(modname, None) -test_modules = [pure_tests, fast_tests] -test_suffixes = ["_Pure", "_Fast"] -# XXX(gb) First run all the _Pure tests, then all the _Fast tests. You might -# not believe this, but in spite of all the sys.modules trickery running a _Pure -# test last will leave a mix of pure and native datetime stuff lying around. -all_test_classes = [] +def load_tests(loader, tests, pattern): + try: + pure_tests = import_fresh_module(TESTS, fresh=['datetime', '_strptime'], + blocked=['_datetime']) + fast_tests = import_fresh_module(TESTS, fresh=['datetime', + '_datetime', '_strptime']) + finally: + # XXX: import_fresh_module() is supposed to leave sys.module cache untouched, + # XXX: but it does not, so we have to cleanup ourselves. + for modname in ['datetime', '_datetime', '_strptime']: + sys.modules.pop(modname, None) -for module, suffix in zip(test_modules, test_suffixes): - test_classes = [] - for name, cls in module.__dict__.items(): - if not isinstance(cls, type): - continue - if issubclass(cls, unittest.TestCase): - test_classes.append(cls) - elif issubclass(cls, unittest.TestSuite): - suit = cls() - test_classes.extend(type(test) for test in suit) - test_classes = sorted(set(test_classes), key=lambda cls: cls.__qualname__) - for cls in test_classes: - cls.__name__ += suffix - cls.__qualname__ += suffix - @classmethod - def setUpClass(cls_, module=module): - cls_._save_sys_modules = sys.modules.copy() - sys.modules[TESTS] = module - sys.modules['datetime'] = module.datetime_module - sys.modules['_strptime'] = module._strptime - @classmethod - def tearDownClass(cls_): - sys.modules.clear() - sys.modules.update(cls_._save_sys_modules) - cls.setUpClass = setUpClass - cls.tearDownClass = tearDownClass - all_test_classes.extend(test_classes) + test_modules = [pure_tests, fast_tests] + test_suffixes = ["_Pure", "_Fast"] + # XXX(gb) First run all the _Pure tests, then all the _Fast tests. You might + # not believe this, but in spite of all the sys.modules trickery running a _Pure + # test last will leave a mix of pure and native datetime stuff lying around. + for module, suffix in zip(test_modules, test_suffixes): + test_classes = [] + for name, cls in module.__dict__.items(): + if not isinstance(cls, type): + continue + if issubclass(cls, unittest.TestCase): + test_classes.append(cls) + elif issubclass(cls, unittest.TestSuite): + suit = cls() + test_classes.extend(type(test) for test in suit) + test_classes = sorted(set(test_classes), key=lambda cls: cls.__qualname__) + for cls in test_classes: + cls.__name__ += suffix + cls.__qualname__ += suffix + @classmethod + def setUpClass(cls_, module=module): + cls_._save_sys_modules = sys.modules.copy() + sys.modules[TESTS] = module + sys.modules['datetime'] = module.datetime_module + sys.modules['_strptime'] = module._strptime + @classmethod + def tearDownClass(cls_): + sys.modules.clear() + sys.modules.update(cls_._save_sys_modules) + cls.setUpClass = setUpClass + cls.tearDownClass = tearDownClass + tests.addTests(loader.loadTestsFromTestCase(cls)) + return tests -def test_main(): - run_unittest(*all_test_classes) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py index e02d1e16ae3da7..16a023084e984a 100644 --- a/Lib/test/test_dbm.py +++ b/Lib/test/test_dbm.py @@ -1,23 +1,21 @@ """Test script for the dbm.open function based on testdumbdbm.py""" import unittest -import glob +import dbm +import os from test.support import import_helper from test.support import os_helper -# Skip tests if dbm module doesn't exist. -dbm = import_helper.import_module('dbm') - try: from dbm import ndbm except ImportError: ndbm = None -_fname = os_helper.TESTFN +dirname = os_helper.TESTFN +_fname = os.path.join(dirname, os_helper.TESTFN) # -# Iterates over every database module supported by dbm currently available, -# setting dbm to use each in turn, and yielding that module +# Iterates over every database module supported by dbm currently available. # def dbm_iterator(): for name in dbm._names: @@ -31,11 +29,12 @@ def dbm_iterator(): # # Clean up all scratch databases we might have created during testing # -def delete_files(): - # we don't know the precise name the underlying database uses - # so we use glob to locate all names - for f in glob.glob(glob.escape(_fname) + "*"): - os_helper.unlink(f) +def cleaunup_test_dir(): + os_helper.rmtree(dirname) + +def setup_test_dir(): + cleaunup_test_dir() + os.mkdir(dirname) class AnyDBMTestCase: @@ -134,80 +133,67 @@ def read_helper(self, f): for key in self._dict: self.assertEqual(self._dict[key], f[key.encode("ascii")]) - def tearDown(self): - delete_files() + def test_keys(self): + with dbm.open(_fname, 'c') as d: + self.assertEqual(d.keys(), []) + a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')] + for k, v in a: + d[k] = v + self.assertEqual(sorted(d.keys()), sorted(k for (k, v) in a)) + for k, v in a: + self.assertIn(k, d) + self.assertEqual(d[k], v) + self.assertNotIn(b'xxx', d) + self.assertRaises(KeyError, lambda: d[b'xxx']) def setUp(self): + self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod) dbm._defaultmod = self.module - delete_files() + self.addCleanup(cleaunup_test_dir) + setup_test_dir() class WhichDBTestCase(unittest.TestCase): def test_whichdb(self): + self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod) for module in dbm_iterator(): # Check whether whichdb correctly guesses module name # for databases opened with "module" module. - # Try with empty files first name = module.__name__ - if name == 'dbm.dumb': - continue # whichdb can't support dbm.dumb - delete_files() - f = module.open(_fname, 'c') - f.close() + setup_test_dir() + dbm._defaultmod = module + # Try with empty files first + with module.open(_fname, 'c'): pass self.assertEqual(name, self.dbm.whichdb(_fname)) # Now add a key - f = module.open(_fname, 'w') - f[b"1"] = b"1" - # and test that we can find it - self.assertIn(b"1", f) - # and read it - self.assertEqual(f[b"1"], b"1") - f.close() + with module.open(_fname, 'w') as f: + f[b"1"] = b"1" + # and test that we can find it + self.assertIn(b"1", f) + # and read it + self.assertEqual(f[b"1"], b"1") self.assertEqual(name, self.dbm.whichdb(_fname)) @unittest.skipUnless(ndbm, reason='Test requires ndbm') def test_whichdb_ndbm(self): # Issue 17198: check that ndbm which is referenced in whichdb is defined - db_file = '{}_ndbm.db'.format(_fname) - with open(db_file, 'w'): - self.addCleanup(os_helper.unlink, db_file) - self.assertIsNone(self.dbm.whichdb(db_file[:-3])) - - def tearDown(self): - delete_files() + with open(_fname + '.db', 'wb'): pass + self.assertIsNone(self.dbm.whichdb(_fname)) def setUp(self): - delete_files() - self.filename = os_helper.TESTFN - self.d = dbm.open(self.filename, 'c') - self.d.close() + self.addCleanup(cleaunup_test_dir) + setup_test_dir() self.dbm = import_helper.import_fresh_module('dbm') - def test_keys(self): - self.d = dbm.open(self.filename, 'c') - self.assertEqual(self.d.keys(), []) - a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')] - for k, v in a: - self.d[k] = v - self.assertEqual(sorted(self.d.keys()), sorted(k for (k, v) in a)) - for k, v in a: - self.assertIn(k, self.d) - self.assertEqual(self.d[k], v) - self.assertNotIn(b'xxx', self.d) - self.assertRaises(KeyError, lambda: self.d[b'xxx']) - self.d.close() - - -def load_tests(loader, tests, pattern): - classes = [] - for mod in dbm_iterator(): - classes.append(type("TestCase-" + mod.__name__, - (AnyDBMTestCase, unittest.TestCase), - {'module': mod})) - suites = [unittest.makeSuite(c) for c in classes] - - tests.addTests(suites) - return tests + +for mod in dbm_iterator(): + assert mod.__name__.startswith('dbm.') + suffix = mod.__name__[4:] + testname = f'TestCase_{suffix}' + globals()[testname] = type(testname, + (AnyDBMTestCase, unittest.TestCase), + {'module': mod}) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py index b3e55728c8e70d..f39b0029373485 100644 --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -31,8 +31,7 @@ def tearDown(self): def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) self.g = gdbm.open(filename, 'c') - tp = type(self.g) - self.assertRaises(TypeError, tp) + support.check_disallow_instantiation(self, type(self.g)) def test_key_methods(self): self.g = gdbm.open(filename, 'c') diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 179a9ea7042fbf..b6173a5ffec96c 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -36,17 +36,33 @@ requires_IEEE_754, requires_docstrings, requires_legacy_unicode_capi) from test.support import (TestFailed, - run_with_locale, cpython_only) + run_with_locale, cpython_only, + darwin_malloc_err_warning) from test.support.import_helper import import_fresh_module from test.support import warnings_helper import random import inspect import threading +import sysconfig +_cflags = sysconfig.get_config_var('CFLAGS') or '' +_config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' +MEMORY_SANITIZER = ( + '-fsanitize=memory' in _cflags or + '--with-memory-sanitizer' in _config_args +) + +ADDRESS_SANITIZER = ( + '-fsanitize=address' in _cflags +) + + +if sys.platform == 'darwin': + darwin_malloc_err_warning('test_decimal') C = import_fresh_module('decimal', fresh=['_decimal']) P = import_fresh_module('decimal', blocked=['_decimal']) -orig_sys_decimal = sys.modules['decimal'] +import decimal as orig_sys_decimal # fractions module must import the correct decimal module. cfractions = import_fresh_module('fractions', fresh=['fractions']) @@ -1814,13 +1830,7 @@ def hashit(d): # check that hash(d) == hash(int(d)) for integral values for value in test_values: - self.assertEqual(hashit(value), hashit(int(value))) - - #the same hash that to an int - self.assertEqual(hashit(Decimal(23)), hashit(23)) - self.assertRaises(TypeError, hash, Decimal('sNaN')) - self.assertTrue(hashit(Decimal('Inf'))) - self.assertTrue(hashit(Decimal('-Inf'))) + self.assertEqual(hashit(value), hash(int(value))) # check that the hashes of a Decimal float match when they # represent exactly the same values @@ -1829,7 +1839,7 @@ def hashit(d): for s in test_strings: f = float(s) d = Decimal(s) - self.assertEqual(hashit(f), hashit(d)) + self.assertEqual(hashit(d), hash(f)) with localcontext() as c: # check that the value of the hash doesn't depend on the @@ -1850,6 +1860,19 @@ def hashit(d): x = 1100 ** 1248 self.assertEqual(hashit(Decimal(x)), hashit(x)) + def test_hash_method_nan(self): + Decimal = self.decimal.Decimal + self.assertRaises(TypeError, hash, Decimal('sNaN')) + value = Decimal('NaN') + self.assertEqual(hash(value), object.__hash__(value)) + class H: + def __hash__(self): + return 42 + class D(Decimal, H): + pass + value = D('NaN') + self.assertEqual(hash(value), object.__hash__(value)) + def test_min_and_max_methods(self): Decimal = self.decimal.Decimal @@ -5488,6 +5511,8 @@ def __abs__(self): # Issue 41540: @unittest.skipIf(sys.platform.startswith("aix"), "AIX: default ulimit: test is flaky because of extreme over-allocation") + @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing " + "instead of returning NULL for malloc failure.") def test_maxcontext_exact_arith(self): # Make sure that exact operations do not raise MemoryError due diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py index d4353457933f3d..57a741ffd29742 100644 --- a/Lib/test/test_decorators.py +++ b/Lib/test/test_decorators.py @@ -1,5 +1,6 @@ from test import support import unittest +from types import MethodType def funcattrs(**kwds): def decorate(func): @@ -329,6 +330,91 @@ def outer(cls): self.assertEqual(Class().inner(), 'spam') self.assertEqual(Class().outer(), 'eggs') + def test_wrapped_classmethod_inside_classmethod(self): + class MyClassMethod1: + def __init__(self, func): + self.func = func + + def __call__(self, cls): + if hasattr(self.func, '__get__'): + return self.func.__get__(cls, cls)() + return self.func(cls) + + def __get__(self, instance, owner=None): + if owner is None: + owner = type(instance) + return MethodType(self, owner) + + class MyClassMethod2: + def __init__(self, func): + if isinstance(func, classmethod): + func = func.__func__ + self.func = func + + def __call__(self, cls): + return self.func(cls) + + def __get__(self, instance, owner=None): + if owner is None: + owner = type(instance) + return MethodType(self, owner) + + for myclassmethod in [MyClassMethod1, MyClassMethod2]: + class A: + @myclassmethod + def f1(cls): + return cls + + @classmethod + @myclassmethod + def f2(cls): + return cls + + @myclassmethod + @classmethod + def f3(cls): + return cls + + @classmethod + @classmethod + def f4(cls): + return cls + + @myclassmethod + @MyClassMethod1 + def f5(cls): + return cls + + @myclassmethod + @MyClassMethod2 + def f6(cls): + return cls + + self.assertIs(A.f1(), A) + self.assertIs(A.f2(), A) + self.assertIs(A.f3(), A) + self.assertIs(A.f4(), A) + self.assertIs(A.f5(), A) + self.assertIs(A.f6(), A) + a = A() + self.assertIs(a.f1(), A) + self.assertIs(a.f2(), A) + self.assertIs(a.f3(), A) + self.assertIs(a.f4(), A) + self.assertIs(a.f5(), A) + self.assertIs(a.f6(), A) + + def f(cls): + return cls + + self.assertIs(myclassmethod(f).__get__(a)(), A) + self.assertIs(myclassmethod(f).__get__(a, A)(), A) + self.assertIs(myclassmethod(f).__get__(A, A)(), A) + self.assertIs(myclassmethod(f).__get__(A)(), type(A)) + self.assertIs(classmethod(f).__get__(a)(), A) + self.assertIs(classmethod(f).__get__(a, A)(), A) + self.assertIs(classmethod(f).__get__(A, A)(), A) + self.assertIs(classmethod(f).__get__(A)(), type(A)) class TestClassDecorators(unittest.TestCase): diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 93cc6ca4f44ecb..7886bbfea1f0d7 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -129,7 +129,8 @@ def __eq__(self, other): self.assertEqual(d.count(None), 16) def test_comparisons(self): - d = deque('xabc'); d.popleft() + d = deque('xabc') + d.popleft() for e in [d, deque('abc'), deque('ab'), deque(), list(d)]: self.assertEqual(d==e, type(d)==type(e) and list(d)==list(e)) self.assertEqual(d!=e, not(type(d)==type(e) and list(d)==list(e))) @@ -529,8 +530,8 @@ def test_repr(self): self.assertEqual(repr(d)[-20:], '7, 198, 199, [...]])') def test_init(self): - self.assertRaises(TypeError, deque, 'abc', 2, 3); - self.assertRaises(TypeError, deque, 1); + self.assertRaises(TypeError, deque, 'abc', 2, 3) + self.assertRaises(TypeError, deque, 1) def test_hash(self): self.assertRaises(TypeError, hash, deque('abc')) @@ -868,6 +869,7 @@ def test_weakref(self): p = weakref.proxy(d) self.assertEqual(str(p), str(d)) d = None + support.gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, str, p) def test_strange_subclass(self): diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 3cb923ed0520a3..f3dd1b32e2afa8 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1303,6 +1303,12 @@ class X(object): with self.assertRaises(AttributeError): del X().a + # Inherit from object on purpose to check some backwards compatibility paths + class X(object): + __slots__ = "a" + with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"): + X().a + def test_slots_special(self): # Testing __dict__ and __weakref__ in __slots__... class D(object): @@ -2539,10 +2545,8 @@ def getdict(self): m2instance.b = 2 m2instance.a = 1 self.assertEqual(m2instance.__dict__, "Not a dict!") - try: + with self.assertRaises(TypeError): dir(m2instance) - except TypeError: - pass # Two essentially featureless objects, (Ellipsis just inherits stuff # from object. @@ -4056,7 +4060,7 @@ class D(C): except TypeError: pass else: - assert 0, "best_base calculation found wanting" + self.fail("best_base calculation found wanting") def test_unsubclassable_types(self): with self.assertRaises(TypeError): @@ -4442,6 +4446,8 @@ def __getattr__(self, attr): print("Oops!") except RuntimeError: pass + else: + self.fail("Didn't raise RuntimeError") finally: sys.stdout = test_stdout @@ -4990,8 +4996,11 @@ def test_repr(self): self.assertIn('{!r}: {!r}'.format(k, v), r) -class PTypesLongInitTest(unittest.TestCase): +class AAAPTypesLongInitTest(unittest.TestCase): # This is in its own TestCase so that it can be run before any other tests. + # (Hence the 'AAA' in the test class name: to make it the first + # item in a list sorted by name, like + # unittest.TestLoader.getTestCaseNames() does.) def test_pytype_long_ready(self): # Testing SF bug 551412 ... @@ -5714,7 +5723,7 @@ class A(metaclass=M): def test_incomplete_super(self): """ - Attrubute lookup on a super object must be aware that + Attribute lookup on a super object must be aware that its target type can be uninitialized (type->tp_mro == NULL). """ class M(DebugHelperMeta): @@ -5729,12 +5738,5 @@ class A(metaclass=M): pass -def test_main(): - # Run all local test cases, with PTypesLongInitTest first. - support.run_unittest(PTypesLongInitTest, OperatorsTest, - ClassPropertiesAndMethods, DictProxyTests, - MiscTests, PicklingTests, SharedKeyTests, - MroTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_devpoll.py b/Lib/test/test_devpoll.py index 110c006862737b..85e0accb611b1d 100644 --- a/Lib/test/test_devpoll.py +++ b/Lib/test/test_devpoll.py @@ -6,7 +6,7 @@ import random import select import unittest -from test.support import run_unittest, cpython_only +from test.support import cpython_only if not hasattr(select, 'devpoll') : raise unittest.SkipTest('test works only on Solaris OS family') @@ -138,8 +138,5 @@ def test_events_mask_overflow_c_limits(self): self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) -def test_main(): - run_unittest(DevPollTests) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 666cd81e68d81a..54d100288cb627 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1051,7 +1051,7 @@ def test_splittable_pop(self): @support.cpython_only def test_splittable_pop_pending(self): - """pop a pending key in a splitted table should not crash""" + """pop a pending key in a split table should not crash""" a, b = self.make_shared_key_dict(2) a['a'] = 4 @@ -1398,7 +1398,7 @@ def test_reversed(self): self.assertRaises(StopIteration, next, r) def test_reverse_iterator_for_empty_dict(self): - # bpo-38525: revered iterator should work properly + # bpo-38525: reversed iterator should work properly # empty dict is directly used for reference count test self.assertEqual(list(reversed({})), []) diff --git a/Lib/test/test_dict_version.py b/Lib/test/test_dict_version.py index 8cdccad0d79ab6..243084c75c42bc 100644 --- a/Lib/test/test_dict_version.py +++ b/Lib/test/test_dict_version.py @@ -1,5 +1,5 @@ """ -Test implementation of the PEP 509: dictionary versionning. +Test implementation of the PEP 509: dictionary versioning. """ import unittest from test.support import import_helper diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index 9a24e00f64b4a4..6afd90af8442ad 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -1,5 +1,5 @@ import difflib -from test.support import run_unittest, findfile +from test.support import findfile import unittest import doctest import sys @@ -547,12 +547,14 @@ def test_longest_match_with_popular_chars(self): self.assertFalse(self.longer_match_exists(a, b, match.size)) -def test_main(): +def setUpModule(): difflib.HtmlDiff._default_prefix = 0 - Doctests = doctest.DocTestSuite(difflib) - run_unittest( - TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs, - TestOutputFormat, TestBytes, TestJunkAPIs, TestFindLongest, Doctests) + + +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite(difflib)) + return tests + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 21c68d488c33d3..000549f5b6f114 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -180,6 +180,23 @@ def bug42562(): 2 RETURN_VALUE """ +# Extended arg followed by NOP +code_bug_45757 = bytes([ + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x09, 0xFF, # NOP 0xFF + 0x90, 0x01, # EXTENDED_ARG 0x01 + 0x64, 0x29, # LOAD_CONST 0x29 + 0x53, 0x00, # RETURN_VALUE 0x00 + ]) + +dis_bug_45757 = """\ + 0 EXTENDED_ARG 1 + 2 NOP + 4 EXTENDED_ARG 1 + 6 LOAD_CONST 297 (297) + 8 RETURN_VALUE +""" + _BIG_LINENO_FORMAT = """\ %3d 0 LOAD_GLOBAL 0 (spam) 2 POP_TOP @@ -534,6 +551,10 @@ def test_bug_1333982(self): def test_bug_42562(self): self.do_disassembly_test(bug42562, dis_bug42562) + def test_bug_45757(self): + # Extended arg followed by NOP + self.do_disassembly_test(code_bug_45757, dis_bug_45757) + def test_big_linenos(self): def func(count): namespace = {} @@ -689,10 +710,7 @@ def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs): if sys.flags.optimize: code_info_consts = "0: None" else: - code_info_consts = ( - """0: 'Formatted details of methods, functions, or code.' - 1: None""" -) + code_info_consts = "0: 'Formatted details of methods, functions, or code.'" code_info_code_info = f"""\ Name: code_info @@ -816,7 +834,6 @@ def f(c=c): Constants: 0: 0 1: 1 - 2: None Names: 0: x""" @@ -1059,17 +1076,17 @@ def jumpy(): Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=98, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=102, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_FINALLY', opcode=122, arg=48, argval=202, argrepr='to 202', offset=104, starts_line=20, is_jump_target=True), + Instruction(opname='SETUP_FINALLY', opcode=122, arg=63, argval=232, argrepr='to 232', offset=104, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_FINALLY', opcode=122, arg=6, argval=120, argrepr='to 120', offset=106, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=108, starts_line=21, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=110, starts_line=None, is_jump_target=False), Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False), Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=144, argrepr='to 144', offset=118, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=146, argrepr='to 146', offset=118, starts_line=None, is_jump_target=False), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=120, starts_line=22, is_jump_target=True), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=122, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=106, argval=212, argrepr='to 212', offset=124, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=72, argval=144, argrepr='to 144', offset=124, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False), @@ -1078,42 +1095,56 @@ def jumpy(): Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=22, argval=188, argrepr='to 188', offset=142, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True), - Instruction(opname='SETUP_WITH', opcode=143, arg=12, argval=172, argrepr='to 172', offset=146, starts_line=None, is_jump_target=False), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=25, is_jump_target=False), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=30, argval=204, argrepr='to 204', offset=142, starts_line=None, is_jump_target=False), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=144, starts_line=22, is_jump_target=True), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True), + Instruction(opname='SETUP_WITH', opcode=143, arg=12, argval=174, argrepr='to 174', offset=148, starts_line=None, is_jump_target=False), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=162, starts_line=25, is_jump_target=False), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=8, argval=188, argrepr='to 188', offset=170, starts_line=None, is_jump_target=False), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=True), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=89, argval=178, argrepr='to 178', offset=174, starts_line=None, is_jump_target=False), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=176, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=True), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=168, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=22, argval=218, argrepr='to 218', offset=172, starts_line=None, is_jump_target=False), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=90, argval=180, argrepr='to 180', offset=176, starts_line=None, is_jump_target=False), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=192, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=194, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=198, starts_line=None, is_jump_target=False), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=202, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=204, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=210, starts_line=None, is_jump_target=False), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=212, starts_line=22, is_jump_target=True), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, starts_line=28, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=208, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=218, starts_line=25, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, starts_line=28, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=222, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=228, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=232, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=234, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=236, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=240, starts_line=None, is_jump_target=False), ] # One last piece of inspect fodder to check the default line number handling @@ -1234,5 +1265,46 @@ def test_assert_not_in_with_arg_in_bytecode(self): with self.assertRaises(AssertionError): self.assertNotInBytecode(code, "LOAD_CONST", 1) + +class TestDisTraceback(unittest.TestCase): + def setUp(self) -> None: + try: # We need to clean up existing tracebacks + del sys.last_traceback + except AttributeError: + pass + return super().setUp() + + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb) + return output.getvalue() + + def test_distb_empty(self): + with self.assertRaises(RuntimeError): + dis.distb() + + def test_distb_last_traceback(self): + # We need to have an existing last traceback in `sys`: + tb = get_tb() + sys.last_traceback = tb + + self.assertEqual(self.get_disassembly(None), dis_traceback) + + def test_distb_explicit_arg(self): + tb = get_tb() + + self.assertEqual(self.get_disassembly(tb), dis_traceback) + + +class TestDisTracebackWithFile(TestDisTraceback): + # Run the `distb` tests again, using the file arg instead of print + def get_disassembly(self, tb): + output = io.StringIO() + with contextlib.redirect_stdout(output): + dis.distb(tb, file=output) + return output.getvalue() + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_distutils.py b/Lib/test/test_distutils.py index 90bfc70a133ae1..4b40af0213234e 100644 --- a/Lib/test/test_distutils.py +++ b/Lib/test/test_distutils.py @@ -15,16 +15,14 @@ import distutils.tests -def test_main(): - # used by regrtest - support.run_unittest(distutils.tests.test_suite()) - support.reap_children() - - def load_tests(*_): # used by unittest return distutils.tests.test_suite() +def tearDownModule(): + support.reap_children() + + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 6f51b1bc4f0d1f..9703f871ad640c 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -15,6 +15,7 @@ import unittest import tempfile import shutil +import types import contextlib # NOTE: There are some additional tests relating to interaction with @@ -95,6 +96,17 @@ def a_classmethod(cls, v): 22 """) + a_class_attribute = 42 + + @classmethod + @property + def a_classmethod_property(cls): + """ + >>> print(SampleClass.a_classmethod_property) + 42 + """ + return cls.a_class_attribute + class NestedClass: """ >>> x = SampleClass.NestedClass(5) @@ -443,7 +455,7 @@ def basics(): r""" >>> tests = finder.find(sample_func) >>> print(tests) # doctest: +ELLIPSIS - [] + [] The exact name depends on how test_doctest was invoked, so allow for leading path components. @@ -500,6 +512,7 @@ def basics(): r""" 1 SampleClass.NestedClass.__init__ 1 SampleClass.__init__ 2 SampleClass.a_classmethod + 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -555,6 +568,7 @@ def basics(): r""" 1 some_module.SampleClass.NestedClass.__init__ 1 some_module.SampleClass.__init__ 2 some_module.SampleClass.a_classmethod + 1 some_module.SampleClass.a_classmethod_property 1 some_module.SampleClass.a_property 1 some_module.SampleClass.a_staticmethod 1 some_module.SampleClass.double @@ -596,6 +610,7 @@ def basics(): r""" 1 SampleClass.NestedClass.__init__ 1 SampleClass.__init__ 2 SampleClass.a_classmethod + 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -616,6 +631,7 @@ def basics(): r""" 0 SampleClass.NestedClass.square 1 SampleClass.__init__ 2 SampleClass.a_classmethod + 1 SampleClass.a_classmethod_property 1 SampleClass.a_property 1 SampleClass.a_staticmethod 1 SampleClass.double @@ -698,6 +714,18 @@ def non_Python_modules(): r""" class TestDocTestFinder(unittest.TestCase): + def test_issue35753(self): + # This import of `call` should trigger issue35753 when + # `support.run_doctest` is called due to unwrap failing, + # however with a patched doctest this should succeed. + from unittest.mock import call + dummy_module = types.ModuleType("dummy") + dummy_module.__dict__['inject_call'] = call + try: + support.run_doctest(dummy_module, verbosity=True) + except ValueError as e: + raise support.TestFailed("Doctest unwrap failed") from e + def test_empty_namespace_package(self): pkg_name = 'doctest_empty_pkg' with tempfile.TemporaryDirectory() as parent_dir: @@ -3097,20 +3125,11 @@ def test_no_trailing_whitespace_stripping(): patches that contain trailing whitespace. More info on Issue 24746. """ -###################################################################### -## Main -###################################################################### - -def test_main(): - # Check the doctest cases in doctest itself: - ret = support.run_doctest(doctest, verbosity=True) - # Check the doctest cases defined here: - from test import test_doctest - support.run_doctest(test_doctest, verbosity=True) - - # Run unittests - support.run_unittest(__name__) +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite(doctest)) + tests.addTest(doctest.DocTestSuite()) + return tests def test_coverage(coverdir): @@ -3123,8 +3142,9 @@ def test_coverage(coverdir): r.write_results(show_missing=True, summary=True, coverdir=coverdir) + if __name__ == '__main__': if '-c' in sys.argv: test_coverage('/tmp/doctest.cover') else: - test_main() + unittest.main() diff --git a/Lib/test/test_doctest2.py b/Lib/test/test_doctest2.py index 347a143641071d..ab8a0696736e23 100644 --- a/Lib/test/test_doctest2.py +++ b/Lib/test/test_doctest2.py @@ -13,7 +13,6 @@ import sys import unittest -from test import support if sys.flags.optimize >= 2: raise unittest.SkipTest("Cannot test docstrings with -O2") @@ -107,17 +106,21 @@ def clsm(cls, val): """ return val -def test_main(): - from test import test_doctest2 - EXPECTED = 19 - f, t = support.run_doctest(test_doctest2) - if t != EXPECTED: - raise support.TestFailed("expected %d tests to run, not %d" % - (EXPECTED, t)) + +class Test(unittest.TestCase): + def test_testmod(self): + import doctest, sys + EXPECTED = 19 + f, t = doctest.testmod(sys.modules[__name__]) + if f: + self.fail("%d of %d doctests failed" % (f, t)) + if t != EXPECTED: + self.fail("expected %d tests to run, not %d" % (EXPECTED, t)) + # Pollute the namespace with a bunch of imported functions and classes, # to make sure they don't get tested. from doctest import * if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py index 7d3e30cbee964a..77252502883112 100644 --- a/Lib/test/test_docxmlrpc.py +++ b/Lib/test/test_docxmlrpc.py @@ -133,7 +133,7 @@ def test_autolinking(self): self.assertIn( (b'
      add(x, y)
      ' b'Add two instances together. This ' - b'follows ' + b'follows ' b'PEP008, but has nothing
      \nto do ' b'with ' b'RFC1952. Case should matter: pEp008 ' diff --git a/Lib/test/test_dtrace.py b/Lib/test/test_dtrace.py index 8612e276d76588..3957077f5d6123 100644 --- a/Lib/test/test_dtrace.py +++ b/Lib/test/test_dtrace.py @@ -6,7 +6,7 @@ import types import unittest -from test.support import findfile, run_unittest +from test.support import findfile def abspath(filename): @@ -34,7 +34,7 @@ def normalize_trace_output(output): return "\n".join(result) except (IndexError, ValueError): raise AssertionError( - "tracer produced unparseable output:\n{}".format(output) + "tracer produced unparsable output:\n{}".format(output) ) @@ -97,7 +97,7 @@ class SystemTapBackend(TraceBackend): COMMAND = ["stap", "-g"] -class TraceTests(unittest.TestCase): +class TraceTests: # unittest.TestCase options maxDiff = None @@ -149,30 +149,25 @@ def test_line(self): self.run_case("line") -class DTraceNormalTests(TraceTests): +class DTraceNormalTests(TraceTests, unittest.TestCase): backend = DTraceBackend() optimize_python = 0 -class DTraceOptimizedTests(TraceTests): +class DTraceOptimizedTests(TraceTests, unittest.TestCase): backend = DTraceBackend() optimize_python = 2 -class SystemTapNormalTests(TraceTests): +class SystemTapNormalTests(TraceTests, unittest.TestCase): backend = SystemTapBackend() optimize_python = 0 -class SystemTapOptimizedTests(TraceTests): +class SystemTapOptimizedTests(TraceTests, unittest.TestCase): backend = SystemTapBackend() optimize_python = 2 -def test_main(): - run_unittest(DTraceNormalTests, DTraceOptimizedTests, SystemTapNormalTests, - SystemTapOptimizedTests) - - if __name__ == '__main__': test_main() diff --git a/Lib/test/test_email/test_contentmanager.py b/Lib/test/test_email/test_contentmanager.py index f4f6bb715acdce..694cef4ba7e413 100644 --- a/Lib/test/test_email/test_contentmanager.py +++ b/Lib/test/test_email/test_contentmanager.py @@ -776,6 +776,18 @@ def test_set_non_ascii_filename(self): foo """).encode('ascii')) + def test_set_content_bytes_cte_7bit(self): + m = self._make_message() + m.set_content(b'ASCII-only message.\n', + maintype='application', subtype='octet-stream', cte='7bit') + self.assertEqual(str(m), textwrap.dedent("""\ + Content-Type: application/octet-stream + Content-Transfer-Encoding: 7bit + MIME-Version: 1.0 + + ASCII-only message. + """)) + content_object_params = { 'text_plain': ('content', ()), 'text_html': ('content', ('html',)), diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index eed60142b19e3b..a3ccbbbabfb328 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -2743,6 +2743,20 @@ def test_multipart_custom_policy(self): self.assertEqual(str(cm.exception), 'There may be at most 1 To headers in a message') + +# Test the NonMultipart class +class TestNonMultipart(TestEmailBase): + def test_nonmultipart_is_not_multipart(self): + msg = MIMENonMultipart('text', 'plain') + self.assertFalse(msg.is_multipart()) + + def test_attach_raises_exception(self): + msg = Message() + msg['Subject'] = 'subpart 1' + r = MIMENonMultipart('text', 'plain') + self.assertRaises(errors.MultipartConversionError, r.attach, msg) + + # A general test of parser->model->generator idempotency. IOW, read a message # in, parse it into a message object tree, then without touching the tree, # regenerate the plain text. The original text and the transformed text @@ -3003,10 +3017,13 @@ def test_formatdate_usegmt(self): def test_parsedate_returns_None_for_invalid_strings(self): self.assertIsNone(utils.parsedate('')) self.assertIsNone(utils.parsedate_tz('')) + self.assertIsNone(utils.parsedate(' ')) + self.assertIsNone(utils.parsedate_tz(' ')) self.assertIsNone(utils.parsedate('0')) self.assertIsNone(utils.parsedate_tz('0')) self.assertIsNone(utils.parsedate('A Complete Waste of Time')) self.assertIsNone(utils.parsedate_tz('A Complete Waste of Time')) + self.assertIsNone(utils.parsedate_tz('Wed, 3 Apr 2002 12.34.56.78+0800')) # Not a part of the spec but, but this has historically worked: self.assertIsNone(utils.parsedate(None)) self.assertIsNone(utils.parsedate_tz(None)) @@ -3263,6 +3280,11 @@ def test_getaddresses_embedded_comment(self): addrs = utils.getaddresses(['User ((nested comment)) ']) eq(addrs[0][1], 'foo@bar.com') + def test_getaddresses_header_obj(self): + """Test the handling of a Header object.""" + addrs = utils.getaddresses([Header('Al Person ')]) + self.assertEqual(addrs[0][1], 'aperson@dom.ain') + def test_make_msgid_collisions(self): # Test make_msgid uniqueness, even with multiple threads class MsgidsThread(Thread): diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py index fab97d91882b8b..4c754bf40fc300 100644 --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -433,7 +433,7 @@ class TestEmailMessageBase: --=== Content-Type: text/plain - Your message has bounced, ser. + Your message has bounced, sir. --=== Content-Type: message/rfc822 @@ -487,10 +487,14 @@ def message_as_iter_attachment(self, body_parts, attachments, parts, msg): self.assertEqual(list(m.iter_attachments()), attachments) def message_as_iter_parts(self, body_parts, attachments, parts, msg): + def _is_multipart_msg(msg): + return 'Content-Type: multipart' in msg + m = self._str_msg(msg) allparts = list(m.walk()) parts = [allparts[n] for n in parts] - self.assertEqual(list(m.iter_parts()), parts) + iter_parts = list(m.iter_parts()) if _is_multipart_msg(msg) else [] + self.assertEqual(iter_parts, parts) class _TestContentManager: def get_content(self, msg, *args, **kw): @@ -775,6 +779,13 @@ def test_as_string_allows_maxheaderlen(self): self.assertEqual(len(m.as_string(maxheaderlen=34).strip().splitlines()), 6) + def test_as_string_unixform(self): + m = self._str_msg('test') + m.set_unixfrom('From foo@bar Thu Jan 1 00:00:00 1970') + self.assertEqual(m.as_string(unixfrom=True), + 'From foo@bar Thu Jan 1 00:00:00 1970\n\ntest') + self.assertEqual(m.as_string(unixfrom=False), '\ntest') + def test_str_defaults_to_policy_max_line_length(self): m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n') self.assertEqual(len(str(m).strip().splitlines()), 3) @@ -916,6 +927,34 @@ def test_folding_with_utf8_encoding_8(self): b'123456789-123456789\n 123456789 Hello ' b'=?utf-8?q?W=C3=B6rld!?= 123456789 123456789\n\n') + def test_get_body_malformed(self): + """test for bpo-42892""" + msg = textwrap.dedent("""\ + Message-ID: <674392CA.4347091@email.au> + Date: Wed, 08 Nov 2017 08:50:22 +0700 + From: Foo Bar + MIME-Version: 1.0 + To: email@email.com + Subject: Python Email + Content-Type: multipart/mixed; + boundary="------------879045806563892972123996" + X-Global-filter:Messagescannedforspamandviruses:passedalltests + + This is a multi-part message in MIME format. + --------------879045806563892972123996 + Content-Type: text/plain; charset=ISO-8859-1; format=flowed + Content-Transfer-Encoding: 7bit + + Your message is ready to be sent with the following file or link + attachments: + XU89 - 08.11.2017 + """) + m = self._str_msg(msg) + # In bpo-42892, this would raise + # AttributeError: 'str' object has no attribute 'is_attachment' + m.get_body() + + class TestMIMEPart(TestEmailMessageBase, TestEmailBase): # Doing the full test run here may seem a bit redundant, since the two # classes are almost identical. But what if they drift apart? So we do diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 23cf297d4ab624..503d4925c9402f 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -30,6 +30,7 @@ # _PyCoreConfig_InitIsolatedConfig() API_ISOLATED = 3 +INIT_LOOPS = 16 MAX_HASH_SEED = 4294967295 @@ -111,13 +112,13 @@ def run_repeated_init_and_subinterpreters(self): self.assertEqual(err, "") # The output from _testembed looks like this: - # --- Pass 0 --- + # --- Pass 1 --- # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728 # interp 1 <0x1d4f690>, thread state <0x1d35350>: id(modules) = 139650431165784 # interp 2 <0x1d5a690>, thread state <0x1d99ed0>: id(modules) = 139650413140368 # interp 3 <0x1d4f690>, thread state <0x1dc3340>: id(modules) = 139650412862200 # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728 - # --- Pass 1 --- + # --- Pass 2 --- # ... interp_pat = (r"^interp (\d+) <(0x[\dA-F]+)>, " @@ -125,7 +126,7 @@ def run_repeated_init_and_subinterpreters(self): r"id\(modules\) = ([\d]+)$") Interp = namedtuple("Interp", "id interp tstate modules") - numloops = 0 + numloops = 1 current_run = [] for line in out.splitlines(): if line == "--- Pass {} ---".format(numloops): @@ -159,6 +160,8 @@ def run_repeated_init_and_subinterpreters(self): class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase): + maxDiff = 100 * 50 + def test_subinterps_main(self): for run in self.run_repeated_init_and_subinterpreters(): main = run[0] @@ -194,6 +197,14 @@ def test_subinterps_distinct_state(self): self.assertNotEqual(sub.tstate, main.tstate) self.assertNotEqual(sub.modules, main.modules) + def test_repeated_init_and_inittab(self): + out, err = self.run_embedded_interpreter("test_repeated_init_and_inittab") + self.assertEqual(err, "") + + lines = [f"--- Pass {i} ---" for i in range(1, INIT_LOOPS+1)] + lines = "\n".join(lines) + "\n" + self.assertEqual(out, lines) + def test_forced_io_encoding(self): # Checks forced configuration of embedded interpreter IO streams env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape") @@ -239,7 +250,7 @@ def test_forced_io_encoding(self): def test_pre_initialization_api(self): """ - Checks some key parts of the C-API that need to work before the runtine + Checks some key parts of the C-API that need to work before the runtime is initialized (via Py_Initialize()). """ env = dict(os.environ, PYTHONPATH=os.pathsep.join(sys.path)) @@ -300,6 +311,14 @@ def test_run_main(self): self.assertEqual(out.rstrip(), "Py_RunMain(): sys.argv=['-c', 'arg2']") self.assertEqual(err, '') + def test_run_main_loop(self): + # bpo-40413: Calling Py_InitializeFromConfig()+Py_RunMain() multiple + # times must not crash. + nloop = 5 + out, err = self.run_embedded_interpreter("test_run_main_loop") + self.assertEqual(out, "Py_RunMain(): sys.argv=['-c', 'arg2']\n" * nloop) + self.assertEqual(err, '') + class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): maxDiff = 4096 @@ -569,7 +588,6 @@ def _get_expected_config(self): def get_expected_config(self, expected_preconfig, expected, expected_pathconfig, env, api, modify_path_cb=None): - cls = self.__class__ configs = self._get_expected_config() pre_config = configs['pre_config'] @@ -1138,7 +1156,7 @@ def test_init_setpath_config(self): 'base_prefix': '', 'exec_prefix': '', 'base_exec_prefix': '', - # overriden by PyConfig + # overridden by PyConfig 'program_name': 'conf_program_name', 'base_executable': 'conf_executable', 'executable': 'conf_executable', @@ -1216,7 +1234,6 @@ def test_init_setpythonhome(self): self.fail(f"Unable to find home in {paths!r}") prefix = exec_prefix = home - ver = sys.version_info expected_paths = self.module_search_paths(prefix=home, exec_prefix=home) config = { @@ -1486,8 +1503,7 @@ class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase): # "Set up a preliminary stderr printer until we have enough # infrastructure for the io module in place." - def get_stdout_fd(self): - return sys.__stdout__.fileno() + STDOUT_FD = 1 def create_printer(self, fd): ctypes = import_helper.import_module('ctypes') @@ -1499,7 +1515,7 @@ def create_printer(self, fd): def test_write(self): message = "unicode:\xe9-\u20ac-\udc80!\n" - stdout_fd = self.get_stdout_fd() + stdout_fd = self.STDOUT_FD stdout_fd_copy = os.dup(stdout_fd) self.addCleanup(os.close, stdout_fd_copy) @@ -1520,7 +1536,7 @@ def test_write(self): self.assertEqual(data, message.encode('utf8', 'backslashreplace')) def test_methods(self): - fd = self.get_stdout_fd() + fd = self.STDOUT_FD printer = self.create_printer(fd) self.assertEqual(printer.fileno(), fd) self.assertEqual(printer.isatty(), os.isatty(fd)) @@ -1528,11 +1544,9 @@ def test_methods(self): printer.close() # noop def test_disallow_instantiation(self): - fd = self.get_stdout_fd() + fd = self.STDOUT_FD printer = self.create_printer(fd) - PyStdPrinter_Type = type(printer) - with self.assertRaises(TypeError): - PyStdPrinter_Type(fd) + support.check_disallow_instantiation(self, type(printer)) if __name__ == "__main__": diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index e918b03cc6c520..03cf3533fc62d6 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1,32 +1,18 @@ import enum -import doctest import inspect -import os import pydoc import sys import unittest import threading from collections import OrderedDict -from enum import Enum, IntEnum, StrEnum, EnumType, Flag, IntFlag, unique, auto -from enum import STRICT, CONFORM, EJECT, KEEP, _simple_enum, _test_simple_enum +from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto from io import StringIO from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL -from test import support -from test.support import ALWAYS_EQ -from test.support import threading_helper +from test.support import ALWAYS_EQ, check__all__, threading_helper from datetime import timedelta python_version = sys.version_info[:2] -def load_tests(loader, tests, ignore): - tests.addTests(doctest.DocTestSuite(enum)) - if os.path.exists('Doc/library/enum.rst'): - tests.addTests(doctest.DocFileSuite( - '../../Doc/library/enum.rst', - optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, - )) - return tests - # for pickle tests try: class Stooges(Enum): @@ -61,9 +47,14 @@ class FlagStooges(Flag): FlagStooges = exc # for pickle test and subclass tests -class Name(StrEnum): - BDFL = 'Guido van Rossum' - FLUFL = 'Barry Warsaw' +try: + class StrEnum(str, Enum): + 'accepts only string values' + class Name(StrEnum): + BDFL = 'Guido van Rossum' + FLUFL = 'Barry Warsaw' +except Exception as exc: + Name = exc try: Question = Enum('Question', 'who what when where why', module=__name__) @@ -264,8 +255,11 @@ def test_enum(self): self.assertIn(e, Season) self.assertIs(type(e), Season) self.assertIsInstance(e, Season) - self.assertEqual(str(e), season) - self.assertEqual(repr(e), 'Season.{0}'.format(season)) + self.assertEqual(str(e), 'Season.' + season) + self.assertEqual( + repr(e), + ''.format(season, i), + ) def test_value_name(self): Season = self.Season @@ -457,13 +451,6 @@ def red(self): green = 2 blue = 3 - def test_reserved__sunder_(self): - with self.assertRaisesRegex( - ValueError, - '_sunder_ names, such as ._bad_., are reserved', - ): - class Bad(Enum): - _bad_ = 1 def test_enum_with_value_name(self): class Huh(Enum): @@ -508,7 +495,7 @@ class EnumWithFormatOverride(Enum): two = 2.0 def __format__(self, spec): return 'Format!!' - self.assertEqual(str(EnumWithFormatOverride.one), 'one') + self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one') self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!') def test_str_and_format_override_enum(self): @@ -548,31 +535,11 @@ class TestFloat(float, Enum): two = 2.0 def __format__(self, spec): return 'TestFloat success!' - self.assertEqual(str(TestFloat.one), 'one') + self.assertEqual(str(TestFloat.one), 'TestFloat.one') self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!') - @unittest.skipIf( - python_version < (3, 12), - 'mixin-format is still using member.value', - ) - def test_mixin_format_warning(self): - with self.assertWarns(DeprecationWarning): - self.assertEqual(f'{self.Grades.B}', 'Grades.B') - - @unittest.skipIf( - python_version >= (3, 12), - 'mixin-format now uses member instead of member.value', - ) - def test_mixin_format_warning(self): - with self.assertWarns(DeprecationWarning): - self.assertEqual(f'{self.Grades.B}', '4') - def assertFormatIsValue(self, spec, member): - if python_version < (3, 12) and (not spec or spec in ('{}','{:}')): - with self.assertWarns(DeprecationWarning): - self.assertEqual(spec.format(member), spec.format(member.value)) - else: - self.assertEqual(spec.format(member), spec.format(member.value)) + self.assertEqual(spec.format(member), spec.format(member.value)) def test_format_enum_date(self): Holiday = self.Holiday @@ -648,15 +615,49 @@ class Test2Enum(MyStrEnum, MyMethodEnum): def test_inherited_data_type(self): class HexInt(int): + __qualname__ = 'HexInt' def __repr__(self): return hex(self) class MyEnum(HexInt, enum.Enum): + __qualname__ = 'MyEnum' A = 1 B = 2 C = 3 - def __repr__(self): - return '<%s.%s: %r>' % (self.__class__.__name__, self._name_, self._value_) self.assertEqual(repr(MyEnum.A), '') + globals()['HexInt'] = HexInt + globals()['MyEnum'] = MyEnum + test_pickle_dump_load(self.assertIs, MyEnum.A) + test_pickle_dump_load(self.assertIs, MyEnum) + # + class SillyInt(HexInt): + __qualname__ = 'SillyInt' + pass + class MyOtherEnum(SillyInt, enum.Enum): + __qualname__ = 'MyOtherEnum' + D = 4 + E = 5 + F = 6 + self.assertIs(MyOtherEnum._member_type_, SillyInt) + globals()['SillyInt'] = SillyInt + globals()['MyOtherEnum'] = MyOtherEnum + test_pickle_dump_load(self.assertIs, MyOtherEnum.E) + test_pickle_dump_load(self.assertIs, MyOtherEnum) + # + class BrokenInt(int): + __qualname__ = 'BrokenInt' + def __new__(cls, value): + return int.__new__(cls, value) + class MyBrokenEnum(BrokenInt, Enum): + __qualname__ = 'MyBrokenEnum' + G = 7 + H = 8 + I = 9 + self.assertIs(MyBrokenEnum._member_type_, BrokenInt) + self.assertIs(MyBrokenEnum(7), MyBrokenEnum.G) + globals()['BrokenInt'] = BrokenInt + globals()['MyBrokenEnum'] = MyBrokenEnum + test_pickle_exception(self.assertRaises, TypeError, MyBrokenEnum.G) + test_pickle_exception(self.assertRaises, PicklingError, MyBrokenEnum) def test_too_many_data_types(self): with self.assertRaisesRegex(TypeError, 'too many data types'): @@ -716,13 +717,14 @@ class phy(str, Enum): tau = 'Tau' self.assertTrue(phy.pi < phy.tau) - def test_strenum_inherited_methods(self): + def test_strenum_inherited(self): + class StrEnum(str, Enum): + pass class phy(StrEnum): pi = 'Pi' tau = 'Tau' self.assertTrue(phy.pi < phy.tau) - self.assertEqual(phy.pi.upper(), 'PI') - self.assertEqual(phy.tau.count('a'), 1) + def test_intenum(self): class WeekDay(IntEnum): @@ -1254,11 +1256,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1273,8 +1273,7 @@ def __add__(self, other): if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), - temp, - ) + temp ) else: return temp @@ -1314,11 +1313,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1333,8 +1330,7 @@ def __add__(self, other): if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), - temp, - ) + temp ) else: return temp @@ -1374,11 +1370,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1393,8 +1387,7 @@ def __add__(self, other): if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), - temp, - ) + temp ) else: return temp @@ -1434,11 +1427,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1453,8 +1444,7 @@ def __add__(self, other): if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), - temp, - ) + temp ) else: return temp @@ -1463,6 +1453,7 @@ class NEI(NamedInt, Enum): x = ('the-x', 1) y = ('the-y', 2) + self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") globals()['NamedInt'] = NamedInt @@ -1491,11 +1482,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1546,11 +1535,9 @@ def __name__(self): return self._intname def __repr__(self): # repr() is updated to include the name and type info - return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -1565,8 +1552,7 @@ def __add__(self, other): if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( '({0} + {1})'.format(self.__name__, other.__name__), - temp, - ) + temp ) else: return temp @@ -1730,13 +1716,6 @@ def test(self): class Test(Base): test = 1 self.assertEqual(Test.test.test, 'dynamic') - class Base2(Enum): - @enum.property - def flash(self): - return 'flashy dynamic' - class Test(Base2): - flash = 1 - self.assertEqual(Test.flash.flash, 'flashy dynamic') def test_no_duplicates(self): class UniqueEnum(Enum): @@ -2033,7 +2012,7 @@ class Color(MaxMixin, Enum): self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 3) self.assertEqual(Color.MAX, 3) - self.assertEqual(str(Color.BLUE), 'BLUE') + self.assertEqual(str(Color.BLUE), 'Color.BLUE') class Color(MaxMixin, StrMixin, Enum): RED = auto() GREEN = auto() @@ -2104,6 +2083,13 @@ class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum): self.assertTrue(issubclass(ReformedColor, int)) def test_multiple_inherited_mixin(self): + class StrEnum(str, Enum): + def __new__(cls, *args, **kwargs): + for a in args: + if not isinstance(a, str): + raise TypeError("Enumeration '%s' (%s) is not" + " a string" % (a, type(a).__name__)) + return str.__new__(cls, *args, **kwargs) @unique class Decision1(StrEnum): REVERT = "REVERT" @@ -2152,90 +2138,6 @@ def test_empty_globals(self): local_ls = {} exec(code, global_ns, local_ls) - def test_strenum(self): - class GoodStrEnum(StrEnum): - one = '1' - two = '2' - three = b'3', 'ascii' - four = b'4', 'latin1', 'strict' - self.assertEqual(GoodStrEnum.one, '1') - self.assertEqual(str(GoodStrEnum.one), '1') - self.assertEqual(GoodStrEnum.one, str(GoodStrEnum.one)) - self.assertEqual(GoodStrEnum.one, '{}'.format(GoodStrEnum.one)) - # - class DumbMixin: - def __str__(self): - return "don't do this" - class DumbStrEnum(DumbMixin, StrEnum): - five = '5' - six = '6' - seven = '7' - self.assertEqual(DumbStrEnum.seven, '7') - self.assertEqual(str(DumbStrEnum.seven), "don't do this") - # - class EnumMixin(Enum): - def hello(self): - print('hello from %s' % (self, )) - class HelloEnum(EnumMixin, StrEnum): - eight = '8' - self.assertEqual(HelloEnum.eight, '8') - self.assertEqual(HelloEnum.eight, str(HelloEnum.eight)) - # - class GoodbyeMixin: - def goodbye(self): - print('%s wishes you a fond farewell') - class GoodbyeEnum(GoodbyeMixin, EnumMixin, StrEnum): - nine = '9' - self.assertEqual(GoodbyeEnum.nine, '9') - self.assertEqual(GoodbyeEnum.nine, str(GoodbyeEnum.nine)) - # - with self.assertRaisesRegex(TypeError, '1 is not a string'): - class FirstFailedStrEnum(StrEnum): - one = 1 - two = '2' - with self.assertRaisesRegex(TypeError, "2 is not a string"): - class SecondFailedStrEnum(StrEnum): - one = '1' - two = 2, - three = '3' - with self.assertRaisesRegex(TypeError, '2 is not a string'): - class ThirdFailedStrEnum(StrEnum): - one = '1' - two = 2 - with self.assertRaisesRegex(TypeError, 'encoding must be a string, not %r' % (sys.getdefaultencoding, )): - class ThirdFailedStrEnum(StrEnum): - one = '1' - two = b'2', sys.getdefaultencoding - with self.assertRaisesRegex(TypeError, 'errors must be a string, not 9'): - class ThirdFailedStrEnum(StrEnum): - one = '1' - two = b'2', 'ascii', 9 - - def test_missing_value_error(self): - with self.assertRaisesRegex(TypeError, "_value_ not set in __new__"): - class Combined(str, Enum): - # - def __new__(cls, value, sequence): - enum = str.__new__(cls, value) - if '(' in value: - fis_name, segment = value.split('(', 1) - segment = segment.strip(' )') - else: - fis_name = value - segment = None - enum.fis_name = fis_name - enum.segment = segment - enum.sequence = sequence - return enum - # - def __repr__(self): - return "<%s.%s>" % (self.__class__.__name__, self._name_) - # - key_type = 'An$(1,2)', 0 - company_id = 'An$(3,2)', 1 - code = 'An$(5,1)', 2 - description = 'Bn$', 3 - @unittest.skipUnless( python_version == (3, 9), 'private variables are now normal attributes', @@ -2252,70 +2154,6 @@ class Private(Enum): except ValueError: pass - def test_private_variable_is_normal_attribute(self): - class Private(Enum): - __corporal = 'Radar' - __major_ = 'Hoolihan' - self.assertEqual(Private._Private__corporal, 'Radar') - self.assertEqual(Private._Private__major_, 'Hoolihan') - - @unittest.skipUnless( - python_version < (3, 12), - 'member-member access now raises an exception', - ) - def test_warning_for_member_from_member_access(self): - with self.assertWarns(DeprecationWarning): - class Di(Enum): - YES = 1 - NO = 0 - nope = Di.YES.NO - self.assertIs(Di.NO, nope) - - @unittest.skipUnless( - python_version >= (3, 12), - 'member-member access currently issues a warning', - ) - def test_exception_for_member_from_member_access(self): - with self.assertRaisesRegex(AttributeError, "Di: no instance attribute .NO."): - class Di(Enum): - YES = 1 - NO = 0 - nope = Di.YES.NO - - def test_strenum_auto(self): - class Strings(StrEnum): - ONE = auto() - TWO = auto() - self.assertEqual([Strings.ONE, Strings.TWO], ['one', 'two']) - - - def test_dynamic_members_with_static_methods(self): - # - foo_defines = {'FOO_CAT': 'aloof', 'BAR_DOG': 'friendly', 'FOO_HORSE': 'big'} - class Foo(Enum): - vars().update({ - k: v - for k, v in foo_defines.items() - if k.startswith('FOO_') - }) - def upper(self): - return self.value.upper() - self.assertEqual(list(Foo), [Foo.FOO_CAT, Foo.FOO_HORSE]) - self.assertEqual(Foo.FOO_CAT.value, 'aloof') - self.assertEqual(Foo.FOO_HORSE.upper(), 'BIG') - # - with self.assertRaisesRegex(TypeError, "'FOO_CAT' already defined as: 'aloof'"): - class FooBar(Enum): - vars().update({ - k: v - for k, v in foo_defines.items() - if k.startswith('FOO_') - }, - **{'FOO_CAT': 'small'}, - ) - def upper(self): - return self.value.upper() - class TestOrder(unittest.TestCase): @@ -2395,71 +2233,68 @@ class Open(Flag): class Color(Flag): BLACK = 0 RED = 1 - ROJO = 1 GREEN = 2 BLUE = 4 PURPLE = RED|BLUE - WHITE = RED|GREEN|BLUE - BLANCO = RED|GREEN|BLUE def test_str(self): Perm = self.Perm - self.assertEqual(str(Perm.R), 'R') - self.assertEqual(str(Perm.W), 'W') - self.assertEqual(str(Perm.X), 'X') - self.assertEqual(str(Perm.R | Perm.W), 'R|W') - self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'R|W|X') - self.assertEqual(str(Perm(0)), 'Perm(0)') - self.assertEqual(str(~Perm.R), 'W|X') - self.assertEqual(str(~Perm.W), 'R|X') - self.assertEqual(str(~Perm.X), 'R|W') - self.assertEqual(str(~(Perm.R | Perm.W)), 'X') - self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)') - self.assertEqual(str(Perm(~0)), 'R|W|X') + self.assertEqual(str(Perm.R), 'Perm.R') + self.assertEqual(str(Perm.W), 'Perm.W') + self.assertEqual(str(Perm.X), 'Perm.X') + self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W') + self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X') + self.assertEqual(str(Perm(0)), 'Perm.0') + self.assertEqual(str(~Perm.R), 'Perm.W|X') + self.assertEqual(str(~Perm.W), 'Perm.R|X') + self.assertEqual(str(~Perm.X), 'Perm.R|W') + self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X') + self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0') + self.assertEqual(str(Perm(~0)), 'Perm.R|W|X') Open = self.Open - self.assertEqual(str(Open.RO), 'RO') - self.assertEqual(str(Open.WO), 'WO') - self.assertEqual(str(Open.AC), 'AC') - self.assertEqual(str(Open.RO | Open.CE), 'CE') - self.assertEqual(str(Open.WO | Open.CE), 'WO|CE') - self.assertEqual(str(~Open.RO), 'WO|RW|CE') - self.assertEqual(str(~Open.WO), 'RW|CE') - self.assertEqual(str(~Open.AC), 'CE') - self.assertEqual(str(~(Open.RO | Open.CE)), 'AC') - self.assertEqual(str(~(Open.WO | Open.CE)), 'RW') + self.assertEqual(str(Open.RO), 'Open.RO') + self.assertEqual(str(Open.WO), 'Open.WO') + self.assertEqual(str(Open.AC), 'Open.AC') + self.assertEqual(str(Open.RO | Open.CE), 'Open.CE') + self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO') + self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO') + self.assertEqual(str(~Open.WO), 'Open.CE|RW') + self.assertEqual(str(~Open.AC), 'Open.CE') + self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC') + self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW') def test_repr(self): Perm = self.Perm - self.assertEqual(repr(Perm.R), 'Perm.R') - self.assertEqual(repr(Perm.W), 'Perm.W') - self.assertEqual(repr(Perm.X), 'Perm.X') - self.assertEqual(repr(Perm.R | Perm.W), 'Perm.R|Perm.W') - self.assertEqual(repr(Perm.R | Perm.W | Perm.X), 'Perm.R|Perm.W|Perm.X') - self.assertEqual(repr(Perm(0)), '0x0') - self.assertEqual(repr(~Perm.R), 'Perm.W|Perm.X') - self.assertEqual(repr(~Perm.W), 'Perm.R|Perm.X') - self.assertEqual(repr(~Perm.X), 'Perm.R|Perm.W') - self.assertEqual(repr(~(Perm.R | Perm.W)), 'Perm.X') - self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '0x0') - self.assertEqual(repr(Perm(~0)), 'Perm.R|Perm.W|Perm.X') + self.assertEqual(repr(Perm.R), '') + self.assertEqual(repr(Perm.W), '') + self.assertEqual(repr(Perm.X), '') + self.assertEqual(repr(Perm.R | Perm.W), '') + self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '') + self.assertEqual(repr(Perm(0)), '') + self.assertEqual(repr(~Perm.R), '') + self.assertEqual(repr(~Perm.W), '') + self.assertEqual(repr(~Perm.X), '') + self.assertEqual(repr(~(Perm.R | Perm.W)), '') + self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '') + self.assertEqual(repr(Perm(~0)), '') Open = self.Open - self.assertEqual(repr(Open.RO), 'Open.RO') - self.assertEqual(repr(Open.WO), 'Open.WO') - self.assertEqual(repr(Open.AC), 'Open.AC') - self.assertEqual(repr(Open.RO | Open.CE), 'Open.CE') - self.assertEqual(repr(Open.WO | Open.CE), 'Open.WO|Open.CE') - self.assertEqual(repr(~Open.RO), 'Open.WO|Open.RW|Open.CE') - self.assertEqual(repr(~Open.WO), 'Open.RW|Open.CE') - self.assertEqual(repr(~Open.AC), 'Open.CE') - self.assertEqual(repr(~(Open.RO | Open.CE)), 'Open.AC') - self.assertEqual(repr(~(Open.WO | Open.CE)), 'Open.RW') + self.assertEqual(repr(Open.RO), '') + self.assertEqual(repr(Open.WO), '') + self.assertEqual(repr(Open.AC), '') + self.assertEqual(repr(Open.RO | Open.CE), '') + self.assertEqual(repr(Open.WO | Open.CE), '') + self.assertEqual(repr(~Open.RO), '') + self.assertEqual(repr(~Open.WO), '') + self.assertEqual(repr(~Open.AC), '') + self.assertEqual(repr(~(Open.RO | Open.CE)), '') + self.assertEqual(repr(~(Open.WO | Open.CE)), '') def test_format(self): Perm = self.Perm - self.assertEqual(format(Perm.R, ''), 'R') - self.assertEqual(format(Perm.R | Perm.X, ''), 'R|X') + self.assertEqual(format(Perm.R, ''), 'Perm.R') + self.assertEqual(format(Perm.R | Perm.X, ''), 'Perm.R|X') def test_or(self): Perm = self.Perm @@ -2528,49 +2363,6 @@ def test_bool(self): for f in Open: self.assertEqual(bool(f.value), bool(f)) - def test_boundary(self): - self.assertIs(enum.Flag._boundary_, STRICT) - class Iron(Flag, boundary=STRICT): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Iron._boundary_, STRICT) - # - class Water(Flag, boundary=CONFORM): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Water._boundary_, CONFORM) - # - class Space(Flag, boundary=EJECT): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Space._boundary_, EJECT) - # - class Bizarre(Flag, boundary=KEEP): - b = 3 - c = 4 - d = 6 - # - self.assertRaisesRegex(ValueError, 'invalid value: 7', Iron, 7) - # - self.assertIs(Water(7), Water.ONE|Water.TWO) - self.assertIs(Water(~9), Water.TWO) - # - self.assertEqual(Space(7), 7) - self.assertTrue(type(Space(7)) is int) - # - self.assertEqual(list(Bizarre), [Bizarre.c]) - self.assertIs(Bizarre(3), Bizarre.b) - self.assertIs(Bizarre(6), Bizarre.d) - - def test_iter(self): - Color = self.Color - Open = self.Open - self.assertEqual(list(Color), [Color.RED, Color.GREEN, Color.BLUE]) - self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE]) - def test_programatic_function_string(self): Perm = Flag('Perm', 'R W X') lst = list(Perm) @@ -2688,6 +2480,7 @@ def test_contains_tf(self): self.assertTrue(1 in Color) self.assertTrue(1 in Open) + def test_member_contains(self): Perm = self.Perm R, W, X = Perm @@ -2708,48 +2501,6 @@ def test_member_contains(self): self.assertFalse(W in RX) self.assertFalse(X in RW) - def test_member_iter(self): - Color = self.Color - self.assertEqual(list(Color.BLACK), []) - self.assertEqual(list(Color.PURPLE), [Color.RED, Color.BLUE]) - self.assertEqual(list(Color.BLUE), [Color.BLUE]) - self.assertEqual(list(Color.GREEN), [Color.GREEN]) - self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE]) - self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE]) - - def test_member_length(self): - self.assertEqual(self.Color.__len__(self.Color.BLACK), 0) - self.assertEqual(self.Color.__len__(self.Color.GREEN), 1) - self.assertEqual(self.Color.__len__(self.Color.PURPLE), 2) - self.assertEqual(self.Color.__len__(self.Color.BLANCO), 3) - - def test_number_reset_and_order_cleanup(self): - class Confused(Flag): - _order_ = 'ONE TWO FOUR DOS EIGHT SIXTEEN' - ONE = auto() - TWO = auto() - FOUR = auto() - DOS = 2 - EIGHT = auto() - SIXTEEN = auto() - self.assertEqual( - list(Confused), - [Confused.ONE, Confused.TWO, Confused.FOUR, Confused.EIGHT, Confused.SIXTEEN]) - self.assertIs(Confused.TWO, Confused.DOS) - self.assertEqual(Confused.DOS._value_, 2) - self.assertEqual(Confused.EIGHT._value_, 8) - self.assertEqual(Confused.SIXTEEN._value_, 16) - - def test_aliases(self): - Color = self.Color - self.assertEqual(Color(1).name, 'RED') - self.assertEqual(Color['ROJO'].name, 'RED') - self.assertEqual(Color(7).name, 'WHITE') - self.assertEqual(Color['BLANCO'].name, 'WHITE') - self.assertIs(Color.BLANCO, Color.WHITE) - Open = self.Open - self.assertIs(Open['AC'], Open.AC) - def test_auto_number(self): class Color(Flag): red = auto() @@ -2767,6 +2518,20 @@ class Color(Flag): red = 'not an int' blue = auto() + def test_cascading_failure(self): + class Bizarre(Flag): + c = 3 + d = 4 + f = 6 + # Bizarre.c | Bizarre.d + name = "TestFlag.test_cascading_failure..Bizarre" + self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5) + self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5) + self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2) + self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2) + self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1) + self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1) + def test_duplicate_auto(self): class Dupes(Enum): first = primero = auto() @@ -2775,11 +2540,11 @@ class Dupes(Enum): self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes)) def test_bizarre(self): - with self.assertRaisesRegex(TypeError, "invalid Flag 'Bizarre' -- missing values: 1, 2"): - class Bizarre(Flag): - b = 3 - c = 4 - d = 6 + class Bizarre(Flag): + b = 3 + c = 4 + d = 6 + self.assertEqual(repr(Bizarre(7)), '') def test_multiple_mixin(self): class AllMixin: @@ -2804,7 +2569,7 @@ class Color(AllMixin, Flag): self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 4) self.assertEqual(Color.ALL.value, 7) - self.assertEqual(str(Color.BLUE), 'BLUE') + self.assertEqual(str(Color.BLUE), 'Color.BLUE') class Color(AllMixin, StrMixin, Flag): RED = auto() GREEN = auto() @@ -2903,9 +2668,9 @@ class TestIntFlag(unittest.TestCase): """Tests of the IntFlags.""" class Perm(IntFlag): - R = 1 << 2 - W = 1 << 1 X = 1 << 0 + W = 1 << 1 + R = 1 << 2 class Open(IntFlag): RO = 0 @@ -2917,17 +2682,9 @@ class Open(IntFlag): class Color(IntFlag): BLACK = 0 RED = 1 - ROJO = 1 GREEN = 2 BLUE = 4 PURPLE = RED|BLUE - WHITE = RED|GREEN|BLUE - BLANCO = RED|GREEN|BLUE - - class Skip(IntFlag): - FIRST = 1 - SECOND = 2 - EIGHTH = 8 def test_type(self): Perm = self.Perm @@ -2947,79 +2704,74 @@ def test_type(self): def test_str(self): Perm = self.Perm - self.assertEqual(str(Perm.R), 'R') - self.assertEqual(str(Perm.W), 'W') - self.assertEqual(str(Perm.X), 'X') - self.assertEqual(str(Perm.R | Perm.W), 'R|W') - self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'R|W|X') - self.assertEqual(str(Perm.R | 8), '12') - self.assertEqual(str(Perm(0)), 'Perm(0)') - self.assertEqual(str(Perm(8)), '8') - self.assertEqual(str(~Perm.R), 'W|X') - self.assertEqual(str(~Perm.W), 'R|X') - self.assertEqual(str(~Perm.X), 'R|W') - self.assertEqual(str(~(Perm.R | Perm.W)), 'X') - self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)') - self.assertEqual(str(~(Perm.R | 8)), '-13') - self.assertEqual(str(Perm(~0)), 'R|W|X') - self.assertEqual(str(Perm(~8)), '-9') + self.assertEqual(str(Perm.R), 'Perm.R') + self.assertEqual(str(Perm.W), 'Perm.W') + self.assertEqual(str(Perm.X), 'Perm.X') + self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W') + self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X') + self.assertEqual(str(Perm.R | 8), 'Perm.8|R') + self.assertEqual(str(Perm(0)), 'Perm.0') + self.assertEqual(str(Perm(8)), 'Perm.8') + self.assertEqual(str(~Perm.R), 'Perm.W|X') + self.assertEqual(str(~Perm.W), 'Perm.R|X') + self.assertEqual(str(~Perm.X), 'Perm.R|W') + self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X') + self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8') + self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X') + self.assertEqual(str(Perm(~0)), 'Perm.R|W|X') + self.assertEqual(str(Perm(~8)), 'Perm.R|W|X') Open = self.Open - self.assertEqual(str(Open.RO), 'RO') - self.assertEqual(str(Open.WO), 'WO') - self.assertEqual(str(Open.AC), 'AC') - self.assertEqual(str(Open.RO | Open.CE), 'CE') - self.assertEqual(str(Open.WO | Open.CE), 'WO|CE') - self.assertEqual(str(Open(4)), '4') - self.assertEqual(str(~Open.RO), 'WO|RW|CE') - self.assertEqual(str(~Open.WO), 'RW|CE') - self.assertEqual(str(~Open.AC), 'CE') - self.assertEqual(str(~(Open.RO | Open.CE)), 'AC') - self.assertEqual(str(~(Open.WO | Open.CE)), 'RW') - self.assertEqual(str(Open(~4)), '-5') + self.assertEqual(str(Open.RO), 'Open.RO') + self.assertEqual(str(Open.WO), 'Open.WO') + self.assertEqual(str(Open.AC), 'Open.AC') + self.assertEqual(str(Open.RO | Open.CE), 'Open.CE') + self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO') + self.assertEqual(str(Open(4)), 'Open.4') + self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO') + self.assertEqual(str(~Open.WO), 'Open.CE|RW') + self.assertEqual(str(~Open.AC), 'Open.CE') + self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO') + self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW') + self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO') def test_repr(self): Perm = self.Perm - self.assertEqual(repr(Perm.R), 'Perm.R') - self.assertEqual(repr(Perm.W), 'Perm.W') - self.assertEqual(repr(Perm.X), 'Perm.X') - self.assertEqual(repr(Perm.R | Perm.W), 'Perm.R|Perm.W') - self.assertEqual(repr(Perm.R | Perm.W | Perm.X), 'Perm.R|Perm.W|Perm.X') - self.assertEqual(repr(Perm.R | 8), '12') - self.assertEqual(repr(Perm(0)), '0x0') - self.assertEqual(repr(Perm(8)), '8') - self.assertEqual(repr(~Perm.R), 'Perm.W|Perm.X') - self.assertEqual(repr(~Perm.W), 'Perm.R|Perm.X') - self.assertEqual(repr(~Perm.X), 'Perm.R|Perm.W') - self.assertEqual(repr(~(Perm.R | Perm.W)), 'Perm.X') - self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '0x0') - self.assertEqual(repr(~(Perm.R | 8)), '-13') - self.assertEqual(repr(Perm(~0)), 'Perm.R|Perm.W|Perm.X') - self.assertEqual(repr(Perm(~8)), '-9') + self.assertEqual(repr(Perm.R), '') + self.assertEqual(repr(Perm.W), '') + self.assertEqual(repr(Perm.X), '') + self.assertEqual(repr(Perm.R | Perm.W), '') + self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '') + self.assertEqual(repr(Perm.R | 8), '') + self.assertEqual(repr(Perm(0)), '') + self.assertEqual(repr(Perm(8)), '') + self.assertEqual(repr(~Perm.R), '') + self.assertEqual(repr(~Perm.W), '') + self.assertEqual(repr(~Perm.X), '') + self.assertEqual(repr(~(Perm.R | Perm.W)), '') + self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '') + self.assertEqual(repr(~(Perm.R | 8)), '') + self.assertEqual(repr(Perm(~0)), '') + self.assertEqual(repr(Perm(~8)), '') Open = self.Open - self.assertEqual(repr(Open.RO), 'Open.RO') - self.assertEqual(repr(Open.WO), 'Open.WO') - self.assertEqual(repr(Open.AC), 'Open.AC') - self.assertEqual(repr(Open.RO | Open.CE), 'Open.CE') - self.assertEqual(repr(Open.WO | Open.CE), 'Open.WO|Open.CE') - self.assertEqual(repr(Open(4)), '4') - self.assertEqual(repr(~Open.RO), 'Open.WO|Open.RW|Open.CE') - self.assertEqual(repr(~Open.WO), 'Open.RW|Open.CE') - self.assertEqual(repr(~Open.AC), 'Open.CE') - self.assertEqual(repr(~(Open.RO | Open.CE)), 'Open.AC') - self.assertEqual(repr(~(Open.WO | Open.CE)), 'Open.RW') - self.assertEqual(repr(Open(~4)), '-5') + self.assertEqual(repr(Open.RO), '') + self.assertEqual(repr(Open.WO), '') + self.assertEqual(repr(Open.AC), '') + self.assertEqual(repr(Open.RO | Open.CE), '') + self.assertEqual(repr(Open.WO | Open.CE), '') + self.assertEqual(repr(Open(4)), '') + self.assertEqual(repr(~Open.RO), '') + self.assertEqual(repr(~Open.WO), '') + self.assertEqual(repr(~Open.AC), '') + self.assertEqual(repr(~(Open.RO | Open.CE)), '') + self.assertEqual(repr(~(Open.WO | Open.CE)), '') + self.assertEqual(repr(Open(~4)), '') - @unittest.skipUnless( - python_version < (3, 12), - 'mixin-format now uses member instead of member.value', - ) def test_format(self): - with self.assertWarns(DeprecationWarning): - Perm = self.Perm - self.assertEqual(format(Perm.R, ''), '4') - self.assertEqual(format(Perm.R | Perm.X, ''), '5') + Perm = self.Perm + self.assertEqual(format(Perm.R, ''), '4') + self.assertEqual(format(Perm.R | Perm.X, ''), '5') def test_or(self): Perm = self.Perm @@ -3097,7 +2849,8 @@ def test_invert(self): RWX = Perm.R | Perm.W | Perm.X values = list(Perm) + [RW, RX, WX, RWX, Perm(0)] for i in values: - self.assertEqual(~i, (~i).value) + self.assertEqual(~i, ~i.value) + self.assertEqual((~i).value, ~i.value) self.assertIs(type(~i), Perm) self.assertEqual(~~i, i) for i in Perm: @@ -3106,50 +2859,6 @@ def test_invert(self): self.assertIs(Open.WO & ~Open.WO, Open.RO) self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE) - def test_boundary(self): - self.assertIs(enum.IntFlag._boundary_, EJECT) - class Iron(IntFlag, boundary=STRICT): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Iron._boundary_, STRICT) - # - class Water(IntFlag, boundary=CONFORM): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Water._boundary_, CONFORM) - # - class Space(IntFlag, boundary=EJECT): - ONE = 1 - TWO = 2 - EIGHT = 8 - self.assertIs(Space._boundary_, EJECT) - # - # - class Bizarre(IntFlag, boundary=KEEP): - b = 3 - c = 4 - d = 6 - # - self.assertRaisesRegex(ValueError, 'invalid value: 5', Iron, 5) - # - self.assertIs(Water(7), Water.ONE|Water.TWO) - self.assertIs(Water(~9), Water.TWO) - # - self.assertEqual(Space(7), 7) - self.assertTrue(type(Space(7)) is int) - # - self.assertEqual(list(Bizarre), [Bizarre.c]) - self.assertIs(Bizarre(3), Bizarre.b) - self.assertIs(Bizarre(6), Bizarre.d) - - def test_iter(self): - Color = self.Color - Open = self.Open - self.assertEqual(list(Color), [Color.RED, Color.GREEN, Color.BLUE]) - self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE]) - def test_programatic_function_string(self): Perm = IntFlag('Perm', 'R W X') lst = list(Perm) @@ -3313,30 +3022,6 @@ def test_member_contains(self): with self.assertRaises(TypeError): self.assertFalse('test' in RW) - def test_member_iter(self): - Color = self.Color - self.assertEqual(list(Color.BLACK), []) - self.assertEqual(list(Color.PURPLE), [Color.RED, Color.BLUE]) - self.assertEqual(list(Color.BLUE), [Color.BLUE]) - self.assertEqual(list(Color.GREEN), [Color.GREEN]) - self.assertEqual(list(Color.WHITE), [Color.RED, Color.GREEN, Color.BLUE]) - - def test_member_length(self): - self.assertEqual(self.Color.__len__(self.Color.BLACK), 0) - self.assertEqual(self.Color.__len__(self.Color.GREEN), 1) - self.assertEqual(self.Color.__len__(self.Color.PURPLE), 2) - self.assertEqual(self.Color.__len__(self.Color.BLANCO), 3) - - def test_aliases(self): - Color = self.Color - self.assertEqual(Color(1).name, 'RED') - self.assertEqual(Color['ROJO'].name, 'RED') - self.assertEqual(Color(7).name, 'WHITE') - self.assertEqual(Color['BLANCO'].name, 'WHITE') - self.assertIs(Color.BLANCO, Color.WHITE) - Open = self.Open - self.assertIs(Open['AC'], Open.AC) - def test_bool(self): Perm = self.Perm for f in Perm: @@ -3345,13 +3030,6 @@ def test_bool(self): for f in Open: self.assertEqual(bool(f.value), bool(f)) - def test_bizarre(self): - with self.assertRaisesRegex(TypeError, "invalid Flag 'Bizarre' -- missing values: 1, 2"): - class Bizarre(IntFlag): - b = 3 - c = 4 - d = 6 - def test_multiple_mixin(self): class AllMixin: @classproperty @@ -3375,7 +3053,7 @@ class Color(AllMixin, IntFlag): self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 4) self.assertEqual(Color.ALL.value, 7) - self.assertEqual(str(Color.BLUE), 'BLUE') + self.assertEqual(str(Color.BLUE), 'Color.BLUE') class Color(AllMixin, StrMixin, IntFlag): RED = auto() GREEN = auto() @@ -3496,40 +3174,13 @@ class Sillier(IntEnum): triple = 3 value = 4 -class TestHelpers(unittest.TestCase): - - sunder_names = '_bad_', '_good_', '_what_ho_' - dunder_names = '__mal__', '__bien__', '__que_que__' - private_names = '_MyEnum__private', '_MyEnum__still_private' - private_and_sunder_names = '_MyEnum__private_', '_MyEnum__also_private_' - random_names = 'okay', '_semi_private', '_weird__', '_MyEnum__' - - def test_sunder(self): - for name in self.sunder_names + self.private_and_sunder_names: - self.assertTrue(enum._is_sunder(name), '%r is a not sunder name?' % name) - for name in self.dunder_names + self.private_names + self.random_names: - self.assertFalse(enum._is_sunder(name), '%r is a sunder name?' % name) - def test_dunder(self): - for name in self.dunder_names: - self.assertTrue(enum._is_dunder(name), '%r is a not dunder name?' % name) - for name in self.sunder_names + self.private_names + self.private_and_sunder_names + self.random_names: - self.assertFalse(enum._is_dunder(name), '%r is a dunder name?' % name) - - def test_is_private(self): - for name in self.private_names + self.private_and_sunder_names: - self.assertTrue(enum._is_private('MyEnum', name), '%r is a not private name?') - for name in self.sunder_names + self.dunder_names + self.random_names: - self.assertFalse(enum._is_private('MyEnum', name), '%r is a private name?') - -class TestEnumTypeSubclassing(unittest.TestCase): - pass expected_help_output_with_docs = """\ Help on class Color in module %s: class Color(enum.Enum) - | Color(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) + | Color(value, names=None, *, module=None, qualname=None, type=None, start=1) |\x20\x20 | An enumeration. |\x20\x20 @@ -3540,11 +3191,11 @@ class Color(enum.Enum) |\x20\x20 | Data and other attributes defined here: |\x20\x20 - | blue = Color.blue + | blue = |\x20\x20 - | green = Color.green + | green = |\x20\x20 - | red = Color.red + | red = |\x20\x20 | ---------------------------------------------------------------------- | Data descriptors inherited from enum.Enum: @@ -3556,7 +3207,7 @@ class Color(enum.Enum) | The value of the Enum member. |\x20\x20 | ---------------------------------------------------------------------- - | Readonly properties inherited from enum.EnumType: + | Readonly properties inherited from enum.EnumMeta: |\x20\x20 | __members__ | Returns a mapping of member name->value. @@ -3577,11 +3228,11 @@ class Color(enum.Enum) |\x20\x20 | Data and other attributes defined here: |\x20\x20 - | blue = Color.blue + | blue = |\x20\x20 - | green = Color.green + | green = |\x20\x20 - | red = Color.red + | red = |\x20\x20 | ---------------------------------------------------------------------- | Data descriptors inherited from enum.Enum: @@ -3591,7 +3242,7 @@ class Color(enum.Enum) | value |\x20\x20 | ---------------------------------------------------------------------- - | Data descriptors inherited from enum.EnumType: + | Data descriptors inherited from enum.EnumMeta: |\x20\x20 | __members__""" @@ -3618,7 +3269,7 @@ def test_pydoc(self): def test_inspect_getmembers(self): values = dict(( - ('__class__', EnumType), + ('__class__', EnumMeta), ('__doc__', 'An enumeration.'), ('__members__', self.Color.__members__), ('__module__', __name__), @@ -3629,7 +3280,7 @@ def test_inspect_getmembers(self): ('value', Enum.__dict__['value']), )) result = dict(inspect.getmembers(self.Color)) - self.assertEqual(set(values.keys()), set(result.keys())) + self.assertEqual(values.keys(), result.keys()) failed = False for k in values.keys(): if result[k] != values[k]: @@ -3645,11 +3296,11 @@ def test_inspect_classify_class_attrs(self): from inspect import Attribute values = [ Attribute(name='__class__', kind='data', - defining_class=object, object=EnumType), + defining_class=object, object=EnumMeta), Attribute(name='__doc__', kind='data', defining_class=self.Color, object='An enumeration.'), Attribute(name='__members__', kind='property', - defining_class=EnumType, object=EnumType.__members__), + defining_class=EnumMeta, object=EnumMeta.__members__), Attribute(name='__module__', kind='data', defining_class=self.Color, object=__name__), Attribute(name='blue', kind='data', @@ -3666,10 +3317,6 @@ def test_inspect_classify_class_attrs(self): values.sort(key=lambda item: item.name) result = list(inspect.classify_class_attrs(self.Color)) result.sort(key=lambda item: item.name) - self.assertEqual( - len(values), len(result), - "%s != %s" % ([a.name for a in values], [a.name for a in result]) - ) failed = False for v, r in zip(values, result): if r != v: @@ -3678,45 +3325,10 @@ def test_inspect_classify_class_attrs(self): if failed: self.fail("result does not equal expected, see print above") - def test_test_simple_enum(self): - @_simple_enum(Enum) - class SimpleColor: - RED = 1 - GREEN = 2 - BLUE = 3 - class CheckedColor(Enum): - RED = 1 - GREEN = 2 - BLUE = 3 - self.assertTrue(_test_simple_enum(CheckedColor, SimpleColor) is None) - SimpleColor.GREEN._value_ = 9 - self.assertRaisesRegex( - TypeError, "enum mismatch", - _test_simple_enum, CheckedColor, SimpleColor, - ) - class CheckedMissing(IntFlag, boundary=KEEP): - SIXTY_FOUR = 64 - ONE_TWENTY_EIGHT = 128 - TWENTY_FORTY_EIGHT = 2048 - ALL = 2048 + 128 + 64 + 12 - CM = CheckedMissing - self.assertEqual(list(CheckedMissing), [CM.SIXTY_FOUR, CM.ONE_TWENTY_EIGHT, CM.TWENTY_FORTY_EIGHT]) - # - @_simple_enum(IntFlag, boundary=KEEP) - class Missing: - SIXTY_FOUR = 64 - ONE_TWENTY_EIGHT = 128 - TWENTY_FORTY_EIGHT = 2048 - ALL = 2048 + 128 + 64 + 12 - M = Missing - self.assertEqual(list(CheckedMissing), [M.SIXTY_FOUR, M.ONE_TWENTY_EIGHT, M.TWENTY_FORTY_EIGHT]) - # - _test_simple_enum(CheckedMissing, Missing) - class MiscTestCase(unittest.TestCase): def test__all__(self): - support.check__all__(self, enum, not_exported={'bin'}) + check__all__(self, enum) # These are unordered here on purpose to ensure that declaration order @@ -3728,22 +3340,7 @@ def test__all__(self): CONVERT_TEST_NAME_E = 5 CONVERT_TEST_NAME_F = 5 -CONVERT_STRING_TEST_NAME_D = 5 -CONVERT_STRING_TEST_NAME_C = 5 -CONVERT_STRING_TEST_NAME_B = 5 -CONVERT_STRING_TEST_NAME_A = 5 # This one should sort first. -CONVERT_STRING_TEST_NAME_E = 5 -CONVERT_STRING_TEST_NAME_F = 5 - class TestIntEnumConvert(unittest.TestCase): - def setUp(self): - # Reset the module-level test variables to their original integer - # values, otherwise the already created enum values get converted - # instead. - for suffix in ['A', 'B', 'C', 'D', 'E', 'F']: - globals()[f'CONVERT_TEST_NAME_{suffix}'] = 5 - globals()[f'CONVERT_STRING_TEST_NAME_{suffix}'] = 5 - def test_convert_value_lookup_priority(self): test_type = enum.IntEnum._convert_( 'UnittestConvert', @@ -3789,55 +3386,33 @@ def test_convert_raise(self): ('test.test_enum', '__main__')[__name__=='__main__'], filter=lambda x: x.startswith('CONVERT_TEST_')) - @unittest.skipUnless( - python_version < (3, 12), - 'mixin-format now uses member instead of member.value', - ) - def test_convert_repr_and_str(self): - module = ('test.test_enum', '__main__')[__name__=='__main__'] - test_type = enum.IntEnum._convert_( - 'UnittestConvert', - module, - filter=lambda x: x.startswith('CONVERT_STRING_TEST_')) - self.assertEqual(repr(test_type.CONVERT_STRING_TEST_NAME_A), '%s.CONVERT_STRING_TEST_NAME_A' % module) - self.assertEqual(str(test_type.CONVERT_STRING_TEST_NAME_A), 'CONVERT_STRING_TEST_NAME_A') - with self.assertWarns(DeprecationWarning): - self.assertEqual(format(test_type.CONVERT_STRING_TEST_NAME_A), '5') +class TestHelpers(unittest.TestCase): -# global names for StrEnum._convert_ test -CONVERT_STR_TEST_2 = 'goodbye' -CONVERT_STR_TEST_1 = 'hello' + sunder_names = '_bad_', '_good_', '_what_ho_' + dunder_names = '__mal__', '__bien__', '__que_que__' + private_names = '_MyEnum__private', '_MyEnum__still_private' + private_and_sunder_names = '_MyEnum__private_', '_MyEnum__also_private_' + random_names = 'okay', '_semi_private', '_weird__', '_MyEnum__' -class TestStrEnumConvert(unittest.TestCase): - def setUp(self): - global CONVERT_STR_TEST_1 - global CONVERT_STR_TEST_2 - CONVERT_STR_TEST_2 = 'goodbye' - CONVERT_STR_TEST_1 = 'hello' + def test_sunder(self): + for name in self.sunder_names + self.private_and_sunder_names: + self.assertTrue(enum._is_sunder(name), '%r is a not sunder name?' % name) + for name in self.dunder_names + self.private_names + self.random_names: + self.assertFalse(enum._is_sunder(name), '%r is a sunder name?' % name) - def test_convert(self): - test_type = enum.StrEnum._convert_( - 'UnittestConvert', - ('test.test_enum', '__main__')[__name__=='__main__'], - filter=lambda x: x.startswith('CONVERT_STR_')) - # Ensure that test_type has all of the desired names and values. - self.assertEqual(test_type.CONVERT_STR_TEST_1, 'hello') - self.assertEqual(test_type.CONVERT_STR_TEST_2, 'goodbye') - # Ensure that test_type only picked up names matching the filter. - self.assertEqual([name for name in dir(test_type) - if name[0:2] not in ('CO', '__')], - [], msg='Names other than CONVERT_STR_* found.') + def test_dunder(self): + for name in self.dunder_names: + self.assertTrue(enum._is_dunder(name), '%r is a not dunder name?' % name) + for name in self.sunder_names + self.private_names + self.private_and_sunder_names + self.random_names: + self.assertFalse(enum._is_dunder(name), '%r is a dunder name?' % name) - def test_convert_repr_and_str(self): - module = ('test.test_enum', '__main__')[__name__=='__main__'] - test_type = enum.StrEnum._convert_( - 'UnittestConvert', - module, - filter=lambda x: x.startswith('CONVERT_STR_')) - self.assertEqual(repr(test_type.CONVERT_STR_TEST_1), '%s.CONVERT_STR_TEST_1' % module) - self.assertEqual(str(test_type.CONVERT_STR_TEST_2), 'goodbye') - self.assertEqual(format(test_type.CONVERT_STR_TEST_1), 'hello') + def test_is_private(self): + for name in self.private_names + self.private_and_sunder_names: + self.assertTrue(enum._is_private('MyEnum', name), '%r is a not private name?') + for name in self.sunder_names + self.dunder_names + self.random_names: + self.assertFalse(enum._is_private('MyEnum', name), '%r is a private name?') if __name__ == '__main__': unittest.main() + diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py index 2d3b4ae4e591ef..abcbf046e2cc22 100644 --- a/Lib/test/test_eof.py +++ b/Lib/test/test_eof.py @@ -29,6 +29,13 @@ def test_EOFS(self): else: raise support.TestFailed + def test_EOFS_with_file(self): + expect = ("(, line 1)") + with os_helper.temp_dir() as temp_dir: + file_name = script_helper.make_script(temp_dir, 'foo', """'''this is \na \ntest""") + rc, out, err = script_helper.assert_python_failure(file_name) + self.assertIn(b'unterminated triple-quoted string literal (detected at line 3)', err) + def test_eof_with_line_continuation(self): expect = "unexpected EOF while parsing (, line 1)" try: diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index bc0404ea4b04d5..86b5dccaaed985 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -168,15 +168,28 @@ def ckmsg(src, msg, exception=SyntaxError): self.fail("failed to get expected SyntaxError") s = '''print "old style"''' - ckmsg(s, "Missing parentheses in call to 'print'. " - "Did you mean print(\"old style\")?") + ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?") s = '''print "old style",''' - ckmsg(s, "Missing parentheses in call to 'print'. " - "Did you mean print(\"old style\", end=\" \")?") + ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?") + + s = 'print f(a+b,c)' + ckmsg(s, "Missing parentheses in call to 'print'. Did you mean print(...)?") s = '''exec "old style"''' - ckmsg(s, "Missing parentheses in call to 'exec'") + ckmsg(s, "Missing parentheses in call to 'exec'. Did you mean exec(...)?") + + s = 'exec f(a+b,c)' + ckmsg(s, "Missing parentheses in call to 'exec'. Did you mean exec(...)?") + + # Check that we don't incorrectly identify '(...)' as an expression to the right + # of 'print' + + s = 'print (a+b,c) $ 42' + ckmsg(s, "invalid syntax") + + s = 'exec (a+b,c) $ 42' + ckmsg(s, "invalid syntax") # should not apply to subclasses, see issue #31161 s = '''if True:\nprint "No indent"''' @@ -196,6 +209,10 @@ def check(self, src, lineno, offset, encoding='utf-8'): src = src.decode(encoding, 'replace') line = src.split('\n')[lineno-1] self.assertIn(line, cm.exception.text) + + def test_error_offset_continuation_characters(self): + check = self.check + check('"\\\n"(1 for c in I,\\\n\\', 2, 2) def testSyntaxErrorOffset(self): check = self.check @@ -211,21 +228,26 @@ def testSyntaxErrorOffset(self): check('lambda x: x = 2', 1, 1) check('f{a + b + c}', 1, 2) check('[file for str(file) in []\n])', 1, 11) + check('a = « hello » « world »', 1, 5) check('[\nfile\nfor str(file)\nin\n[]\n]', 3, 5) check('[file for\n str(file) in []]', 2, 2) + check("ages = {'Alice'=22, 'Bob'=23}", 1, 16) + check('match ...:\n case {**rest, "key": value}:\n ...', 2, 19) + check("[a b c d e f]", 1, 2) + check("for x yfff:", 1, 7) # Errors thrown by compile.c check('class foo:return 1', 1, 11) check('def f():\n continue', 2, 3) check('def f():\n break', 2, 3) - check('try:\n pass\nexcept:\n pass\nexcept ValueError:\n pass', 2, 3) + check('try:\n pass\nexcept:\n pass\nexcept ValueError:\n pass', 3, 1) # Errors thrown by tokenizer.c check('(0x+1)', 1, 3) check('x = 0xI', 1, 6) - check('0010 + 2', 1, 4) + check('0010 + 2', 1, 1) check('x = 32e-+4', 1, 8) - check('x = 0o9', 1, 6) + check('x = 0o9', 1, 7) check('\u03b1 = 0xI', 1, 6) check(b'\xce\xb1 = 0xI', 1, 6) check(b'# -*- coding: iso8859-7 -*-\n\xe1 = 0xI', 2, 6, @@ -242,11 +264,26 @@ def baz(): """, 9, 24) check("pass\npass\npass\n(1+)\npass\npass\npass", 4, 4) check("(1+)", 1, 4) + check("[interesting\nfoo()\n", 1, 1) + check(b"\xef\xbb\xbf#coding: utf8\nprint('\xe6\x88\x91')\n", 0, -1) + check("""f''' + { + (123_a) + }'''""", 3, 17) + check("""f''' + { + f\"\"\" + { + (123_a) + } + \"\"\" + }'''""", 5, 17) # Errors thrown by symtable.c - check('x = [(yield i) for i in range(3)]', 1, 5) - check('def f():\n from _ import *', 1, 1) - check('def f(x, x):\n pass', 1, 1) + check('x = [(yield i) for i in range(3)]', 1, 7) + check('def f():\n from _ import *', 2, 17) + check('def f(x, x):\n pass', 1, 10) + check('{i for i in range(5) if (j := 0) for j in range(5)}', 1, 38) check('def f(x):\n nonlocal x', 2, 3) check('def f(x):\n x = 1\n global x', 3, 3) check('nonlocal x', 1, 1) @@ -638,6 +675,7 @@ def inner_raising_func(): except MyException as e: pass obj = None + gc_collect() # For PyPy or other GCs. obj = wr() self.assertIsNone(obj) @@ -649,6 +687,7 @@ def inner_raising_func(): except MyException: pass obj = None + gc_collect() # For PyPy or other GCs. obj = wr() self.assertIsNone(obj) @@ -660,6 +699,7 @@ def inner_raising_func(): except: pass obj = None + gc_collect() # For PyPy or other GCs. obj = wr() self.assertIsNone(obj) @@ -672,6 +712,7 @@ def inner_raising_func(): except: break obj = None + gc_collect() # For PyPy or other GCs. obj = wr() self.assertIsNone(obj) @@ -690,6 +731,7 @@ def inner_raising_func(): # must clear the latter manually for our test to succeed. e.__context__ = None obj = None + gc_collect() # For PyPy or other GCs. obj = wr() # guarantee no ref cycles on CPython (don't gc_collect) if check_impl_detail(cpython=False): @@ -880,6 +922,7 @@ def raising_gen(): next(g) testfunc(g) g = obj = None + gc_collect() # For PyPy or other GCs. obj = wr() self.assertIsNone(obj) @@ -933,8 +976,152 @@ def __del__(self): raise Exception(MyObject()) except: pass + gc_collect() # For PyPy or other GCs. self.assertEqual(e, (None, None, None)) + def test_raise_does_not_create_context_chain_cycle(self): + class A(Exception): + pass + class B(Exception): + pass + class C(Exception): + pass + + # Create a context chain: + # C -> B -> A + # Then raise A in context of C. + try: + try: + raise A + except A as a_: + a = a_ + try: + raise B + except B as b_: + b = b_ + try: + raise C + except C as c_: + c = c_ + self.assertIsInstance(a, A) + self.assertIsInstance(b, B) + self.assertIsInstance(c, C) + self.assertIsNone(a.__context__) + self.assertIs(b.__context__, a) + self.assertIs(c.__context__, b) + raise a + except A as e: + exc = e + + # Expect A -> C -> B, without cycle + self.assertIs(exc, a) + self.assertIs(a.__context__, c) + self.assertIs(c.__context__, b) + self.assertIsNone(b.__context__) + + def test_no_hang_on_context_chain_cycle1(self): + # See issue 25782. Cycle in context chain. + + def cycle(): + try: + raise ValueError(1) + except ValueError as ex: + ex.__context__ = ex + raise TypeError(2) + + try: + cycle() + except Exception as e: + exc = e + + self.assertIsInstance(exc, TypeError) + self.assertIsInstance(exc.__context__, ValueError) + self.assertIs(exc.__context__.__context__, exc.__context__) + + @unittest.skip("See issue 44895") + def test_no_hang_on_context_chain_cycle2(self): + # See issue 25782. Cycle at head of context chain. + + class A(Exception): + pass + class B(Exception): + pass + class C(Exception): + pass + + # Context cycle: + # +-----------+ + # V | + # C --> B --> A + with self.assertRaises(C) as cm: + try: + raise A() + except A as _a: + a = _a + try: + raise B() + except B as _b: + b = _b + try: + raise C() + except C as _c: + c = _c + a.__context__ = c + raise c + + self.assertIs(cm.exception, c) + # Verify the expected context chain cycle + self.assertIs(c.__context__, b) + self.assertIs(b.__context__, a) + self.assertIs(a.__context__, c) + + def test_no_hang_on_context_chain_cycle3(self): + # See issue 25782. Longer context chain with cycle. + + class A(Exception): + pass + class B(Exception): + pass + class C(Exception): + pass + class D(Exception): + pass + class E(Exception): + pass + + # Context cycle: + # +-----------+ + # V | + # E --> D --> C --> B --> A + with self.assertRaises(E) as cm: + try: + raise A() + except A as _a: + a = _a + try: + raise B() + except B as _b: + b = _b + try: + raise C() + except C as _c: + c = _c + a.__context__ = c + try: + raise D() + except D as _d: + d = _d + e = E() + raise e + + self.assertIs(cm.exception, e) + # Verify the expected context chain cycle + self.assertIs(e.__context__, d) + self.assertIs(d.__context__, c) + self.assertIs(c.__context__, b) + self.assertIs(b.__context__, a) + self.assertIs(a.__context__, c) + def test_unicode_change_attributes(self): # See issue 7309. This was a crasher. @@ -1009,6 +1196,21 @@ def g(): self.assertIsInstance(v, RecursionError, type(v)) self.assertIn("maximum recursion depth exceeded", str(v)) + + @cpython_only + def test_trashcan_recursion(self): + # See bpo-33930 + + def foo(): + o = object() + for x in range(1_000_000): + # Create a big chain of method objects that will trigger + # a deep chain of calls when they need to be destructed. + o = o.__dir__ + + foo() + support.gc_collect() + @cpython_only def test_recursion_normalizing_exception(self): # Issue #22898. @@ -1237,6 +1439,7 @@ def inner(): self.assertNotEqual(wr(), None) else: self.fail("MemoryError not raised") + gc_collect() # For PyPy or other GCs. self.assertEqual(wr(), None) @no_tracing @@ -1257,6 +1460,7 @@ def inner(): self.assertNotEqual(wr(), None) else: self.fail("RecursionError not raised") + gc_collect() # For PyPy or other GCs. self.assertEqual(wr(), None) def test_errno_ENOTDIR(self): @@ -1277,6 +1481,7 @@ def __del__(self): with support.catch_unraisable_exception() as cm: del obj + gc_collect() # For PyPy or other GCs. self.assertEqual(cm.unraisable.object, BrokenDel.__del__) self.assertIsNotNone(cm.unraisable.exc_traceback) @@ -1654,7 +1859,7 @@ def f(): with support.captured_stderr() as err: sys.__excepthook__(*sys.exc_info()) - self.assertNotIn("a1", err.getvalue()) + self.assertNotRegex(err.getvalue(), r"NameError.*a1") def test_name_error_with_custom_exceptions(self): def f(): @@ -1695,6 +1900,37 @@ def foo(): self.assertNotIn("something", err.getvalue()) + def test_issue45826(self): + # regression test for bpo-45826 + def f(): + with self.assertRaisesRegex(NameError, 'aaa'): + aab + + try: + f() + except self.failureException: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("aab", err.getvalue()) + + def test_issue45826_focused(self): + def f(): + try: + nonsense + except BaseException as E: + E.with_traceback(None) + raise ZeroDivisionError() + + try: + f() + except ZeroDivisionError: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertIn("nonsense", err.getvalue()) + self.assertIn("ZeroDivisionError", err.getvalue()) + class AttributeErrorTests(unittest.TestCase): def test_attributes(self): @@ -1911,6 +2147,18 @@ def __getattr__(self, attr): self.assertIn("blech", err.getvalue()) + def test_getattr_suggestions_for_same_name(self): + class A: + def __dir__(self): + return ['blech'] + try: + A().blech + except AttributeError as exc: + with support.captured_stderr() as err: + sys.__excepthook__(*sys.exc_info()) + + self.assertNotIn("Did you mean", err.getvalue()) + def test_attribute_error_with_failing_dict(self): class T: bluch = 1 @@ -2083,7 +2331,7 @@ def test_range_of_offsets(self): abcdefg SyntaxError: bad bad """)), - # End offset pass the source lenght + # End offset pass the source length (("bad.py", 1, 2, "abcdefg", 1, 100), dedent( """ @@ -2100,8 +2348,50 @@ def test_range_of_offsets(self): except SyntaxError as exc: with support.captured_stderr() as err: sys.__excepthook__(*sys.exc_info()) + self.assertIn(expected, err.getvalue()) the_exception = exc + def test_encodings(self): + source = ( + '# -*- coding: cp437 -*-\n' + '"┬ó┬ó┬ó┬ó┬ó┬ó" + f(4, x for x in range(1))\n' + ) + try: + with open(TESTFN, 'w', encoding='cp437') as testfile: + testfile.write(source) + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertEqual(err[-3], ' "┬ó┬ó┬ó┬ó┬ó┬ó" + f(4, x for x in range(1))') + self.assertEqual(err[-2], ' ^^^^^^^^^^^^^^^^^^^') + finally: + unlink(TESTFN) + + # Check backwards tokenizer errors + source = '# -*- coding: ascii -*-\n\n(\n' + try: + with open(TESTFN, 'w', encoding='ascii') as testfile: + testfile.write(source) + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertEqual(err[-3], ' (') + self.assertEqual(err[-2], ' ^') + finally: + unlink(TESTFN) + + def test_non_utf8(self): + # Check non utf-8 characters + try: + with open(TESTFN, 'bw') as testfile: + testfile.write(b"\x89") + rc, out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) + err = err.decode('utf-8').splitlines() + + self.assertIn("SyntaxError: Non-UTF-8 code starting with '\\x89' in file", err[-1]) + finally: + unlink(TESTFN) + def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) @@ -2139,18 +2429,23 @@ def test_incorrect_constructor(self): class PEP626Tests(unittest.TestCase): - def lineno_after_raise(self, f, line): + def lineno_after_raise(self, f, *expected): try: f() except Exception as ex: t = ex.__traceback__ - while t.tb_next: - t = t.tb_next + else: + self.fail("No exception raised") + lines = [] + t = t.tb_next # Skip this function + while t: frame = t.tb_frame - if line is None: - self.assertEqual(frame.f_lineno, line) - else: - self.assertEqual(frame.f_lineno-frame.f_code.co_firstlineno, line) + lines.append( + None if frame.f_lineno is None else + frame.f_lineno-frame.f_code.co_firstlineno + ) + t = t.tb_next + self.assertEqual(tuple(lines), expected) def test_lineno_after_raise_simple(self): def simple(): @@ -2229,5 +2524,17 @@ def f(): f.__code__ = f.__code__.replace(co_linetable=b'\x04\x80\xff\x80') self.lineno_after_raise(f, None) + def test_lineno_after_raise_in_with_exit(self): + class ExitFails: + def __enter__(self): + return self + def __exit__(self, *args): + raise ValueError + + def after_with(): + with ExitFails(): + 1/0 + self.lineno_after_raise(after_with, 1, 1) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 648624482e5553..ee3f41a108a14c 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -89,10 +89,12 @@ def get_output(self, code, filename=None, fd=None): output = output.decode('ascii', 'backslashreplace') return output.splitlines(), exitcode - def check_error(self, code, line_number, fatal_error, *, + def check_error(self, code, lineno, fatal_error, *, filename=None, all_threads=True, other_regex=None, fd=None, know_current_thread=True, - py_fatal_error=False): + py_fatal_error=False, + garbage_collecting=False, + function=''): """ Check that the fault handler for fatal errors is enabled and check the traceback from the child process output. @@ -106,20 +108,21 @@ def check_error(self, code, line_number, fatal_error, *, header = 'Thread 0x[0-9a-f]+' else: header = 'Stack' - regex = r""" - (?m)^{fatal_error} - - {header} \(most recent call first\): - File "", line {lineno} in - """ + regex = [f'^{fatal_error}'] if py_fatal_error: - fatal_error += "\nPython runtime state: initialized" - regex = dedent(regex).format( - lineno=line_number, - fatal_error=fatal_error, - header=header).strip() + regex.append("Python runtime state: initialized") + regex.append('') + regex.append(fr'{header} \(most recent call first\):') + if garbage_collecting: + regex.append(' Garbage-collecting') + regex.append(fr' File "", line {lineno} in {function}') + regex = '\n'.join(regex) + if other_regex: - regex += '|' + other_regex + regex = f'(?:{regex}|{other_regex})' + + # Enable MULTILINE flag + regex = f'(?m){regex}' output, exitcode = self.get_output(code, filename=filename, fd=fd) output = '\n'.join(output) self.assertRegex(output, regex) @@ -168,6 +171,42 @@ def test_sigsegv(self): 3, 'Segmentation fault') + @skip_segfault_on_android + def test_gc(self): + # bpo-44466: Detect if the GC is running + self.check_fatal_error(""" + import faulthandler + import gc + import sys + + faulthandler.enable() + + class RefCycle: + def __del__(self): + faulthandler._sigsegv() + + # create a reference cycle which triggers a fatal + # error in a destructor + a = RefCycle() + b = RefCycle() + a.b = b + b.a = a + + # Delete the objects, not the cycle + a = None + b = None + + # Break the reference cycle: call __del__() + gc.collect() + + # Should not reach this line + print("exit", file=sys.stderr) + """, + 9, + 'Segmentation fault', + function='__del__', + garbage_collecting=True) + def test_fatal_error_c_thread(self): self.check_fatal_error(""" import faulthandler @@ -663,7 +702,7 @@ def check_register(self, filename=False, all_threads=False, import sys all_threads = {all_threads} - signum = {signum} + signum = {signum:d} unregister = {unregister} chain = {chain} filename = {filename!r} diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index 83ee7a5b0d0120..fc8c39365f12b7 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -6,7 +6,7 @@ import sys import unittest from multiprocessing import Process -from test.support import (verbose, run_unittest, cpython_only) +from test.support import verbose, cpython_only from test.support.import_helper import import_module from test.support.os_helper import TESTFN, unlink @@ -210,8 +210,5 @@ def test_fcntl_f_pipesize(self): os.close(test_pipe_w) -def test_main(): - run_unittest(TestFcntl) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index fbfba64759a1e4..1146a37323c9bf 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -7,6 +7,7 @@ import io import _pyio as pyio +from test.support import gc_collect from test.support.os_helper import TESTFN from test.support import os_helper from test.support import warnings_helper @@ -30,6 +31,7 @@ def testWeakRefs(self): self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None + gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, getattr, p, 'tell') def testAttributes(self): @@ -154,6 +156,22 @@ def testModeStrings(self): f.close() self.fail('%r is an invalid file mode' % mode) + def testStdin(self): + if sys.platform == 'osf1V5': + # This causes the interpreter to exit on OSF1 v5.1. + self.skipTest( + ' sys.stdin.seek(-1) may crash the interpreter on OSF1.' + ' Test manually.') + + if not sys.stdin.isatty(): + # Issue 14853: stdin becomes seekable when redirected to a file + self.skipTest('stdin must be a TTY in this test') + + with self.assertRaises((IOError, ValueError)): + sys.stdin.seek(-1) + with self.assertRaises((IOError, ValueError)): + sys.stdin.truncate() + def testBadModeArgument(self): # verify that we get a sensible error message for bad mode argument bad_mode = "qwerty" diff --git a/Lib/test/test_filecmp.py b/Lib/test/test_filecmp.py index 64ba5a0e18169c..9b5ac12bccc58f 100644 --- a/Lib/test/test_filecmp.py +++ b/Lib/test/test_filecmp.py @@ -246,8 +246,5 @@ def _assert_report(self, dircmp_report, expected_report_lines): self.assertEqual(report_lines, expected_report_lines) -def test_main(): - support.run_unittest(FileCompareTestCase, DirCompareTestCase) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index ff611a90eede3b..4269b0e53f56df 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -9,7 +9,7 @@ from weakref import proxy from functools import wraps -from test.support import (run_unittest, cpython_only, swap_attr) +from test.support import cpython_only, swap_attr, gc_collect from test.support.os_helper import (TESTFN, TESTFN_UNICODE, make_bad_fd) from test.support.warnings_helper import check_warnings from collections import UserList @@ -36,6 +36,7 @@ def testWeakRefs(self): self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None + gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, getattr, p, 'tell') def testSeekTell(self): @@ -605,15 +606,12 @@ def test_open_code(self): self.assertNotEqual(w.warnings, []) -def test_main(): +def tearDownModule(): # Historically, these tests have been sloppy about removing TESTFN. # So get rid of it no matter what. - try: - run_unittest(CAutoFileTests, PyAutoFileTests, - COtherFileTests, PyOtherFileTests) - finally: - if os.path.exists(TESTFN): - os.unlink(TESTFN) + if os.path.exists(TESTFN): + os.unlink(TESTFN) + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index ff4f3876be5cd3..29f775644dd4a8 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -564,6 +564,25 @@ def test_float_pow(self): #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315) #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315) + def test_hash(self): + for x in range(-30, 30): + self.assertEqual(hash(float(x)), hash(x)) + self.assertEqual(hash(float(sys.float_info.max)), + hash(int(sys.float_info.max))) + self.assertEqual(hash(float('inf')), sys.hash_info.inf) + self.assertEqual(hash(float('-inf')), -sys.hash_info.inf) + + def test_hash_nan(self): + value = float('nan') + self.assertEqual(hash(value), object.__hash__(value)) + class H: + def __hash__(self): + return 42 + class F(float, H): + pass + value = F('nan') + self.assertEqual(hash(value), object.__hash__(value)) + @requires_setformat class FormatFunctionsTestCase(unittest.TestCase): @@ -1165,10 +1184,10 @@ def test_whitespace(self): def test_from_hex(self): - MIN = self.MIN; - MAX = self.MAX; - TINY = self.TINY; - EPS = self.EPS; + MIN = self.MIN + MAX = self.MAX + TINY = self.TINY + EPS = self.EPS # two spellings of infinity, with optional signs; case-insensitive self.identical(fromHex('inf'), INF) @@ -1449,6 +1468,20 @@ def test_from_hex(self): self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS) self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS) + # Regression test for a corner-case bug reported in b.p.o. 44954 + self.identical(fromHex('0x.8p-1074'), 0.0) + self.identical(fromHex('0x.80p-1074'), 0.0) + self.identical(fromHex('0x.81p-1074'), TINY) + self.identical(fromHex('0x8p-1078'), 0.0) + self.identical(fromHex('0x8.0p-1078'), 0.0) + self.identical(fromHex('0x8.1p-1078'), TINY) + self.identical(fromHex('0x80p-1082'), 0.0) + self.identical(fromHex('0x81p-1082'), TINY) + self.identical(fromHex('.8p-1074'), 0.0) + self.identical(fromHex('8p-1078'), 0.0) + self.identical(fromHex('-.8p-1074'), -0.0) + self.identical(fromHex('+8p-1078'), 0.0) + def test_roundtrip(self): def roundtrip(x): return fromHex(toHex(x)) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 6679bd3d8899cd..ae0d4f7308e2c9 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -249,7 +249,7 @@ def test_common_format(self): # base marker shouldn't change the size testcommon("%0#35.33o", big, "0o012345670123456701234567012345670") - # Some small ints, in both Python int and flavors). + # Some small ints, in both Python int and flavors. testcommon("%d", 42, "42") testcommon("%d", -42, "-42") testcommon("%d", 42.0, "42") diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index caae1b7c4f8535..bd1ca943c7c094 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -212,11 +212,6 @@ def test_ast_line_numbers_nested(self): self.assertEqual(call.col_offset, 11) def test_ast_line_numbers_duplicate_expression(self): - """Duplicate expression - - NOTE: this is currently broken, always sets location of the first - expression. - """ expr = """ a = 10 f'{a * x()} {a * x()} {a * x()}' @@ -266,9 +261,9 @@ def test_ast_line_numbers_duplicate_expression(self): self.assertEqual(binop.lineno, 3) self.assertEqual(binop.left.lineno, 3) self.assertEqual(binop.right.lineno, 3) - self.assertEqual(binop.col_offset, 3) # FIXME: this is wrong - self.assertEqual(binop.left.col_offset, 3) # FIXME: this is wrong - self.assertEqual(binop.right.col_offset, 7) # FIXME: this is wrong + self.assertEqual(binop.col_offset, 13) + self.assertEqual(binop.left.col_offset, 13) + self.assertEqual(binop.right.col_offset, 17) # check the third binop location binop = t.body[1].value.values[4].value self.assertEqual(type(binop), ast.BinOp) @@ -278,9 +273,32 @@ def test_ast_line_numbers_duplicate_expression(self): self.assertEqual(binop.lineno, 3) self.assertEqual(binop.left.lineno, 3) self.assertEqual(binop.right.lineno, 3) - self.assertEqual(binop.col_offset, 3) # FIXME: this is wrong - self.assertEqual(binop.left.col_offset, 3) # FIXME: this is wrong - self.assertEqual(binop.right.col_offset, 7) # FIXME: this is wrong + self.assertEqual(binop.col_offset, 23) + self.assertEqual(binop.left.col_offset, 23) + self.assertEqual(binop.right.col_offset, 27) + + def test_ast_numbers_fstring_with_formatting(self): + + t = ast.parse('f"Here is that pesky {xxx:.3f} again"') + self.assertEqual(len(t.body), 1) + self.assertEqual(t.body[0].lineno, 1) + + self.assertEqual(type(t.body[0]), ast.Expr) + self.assertEqual(type(t.body[0].value), ast.JoinedStr) + self.assertEqual(len(t.body[0].value.values), 3) + + self.assertEqual(type(t.body[0].value.values[0]), ast.Constant) + self.assertEqual(type(t.body[0].value.values[1]), ast.FormattedValue) + self.assertEqual(type(t.body[0].value.values[2]), ast.Constant) + + _, expr, _ = t.body[0].value.values + + name = expr.value + self.assertEqual(type(name), ast.Name) + self.assertEqual(name.lineno, 1) + self.assertEqual(name.end_lineno, 1) + self.assertEqual(name.col_offset, 22) + self.assertEqual(name.end_col_offset, 25) def test_ast_line_numbers_multiline_fstring(self): # See bpo-30465 for details. @@ -926,7 +944,7 @@ def test_invalid_string_prefixes(self): "Bf''", "BF''",] double_quote_cases = [case.replace("'", '"') for case in single_quote_cases] - self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing', + self.assertAllRaise(SyntaxError, 'invalid syntax', single_quote_cases + double_quote_cases) def test_leading_trailing_spaces(self): diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index a48b429ca38027..56e3d8ab8528af 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -4,14 +4,13 @@ # environment import ftplib -import asyncore -import asynchat import socket import io import errno import os import threading import time +import unittest try: import ssl except ImportError: @@ -24,6 +23,13 @@ from test.support import warnings_helper from test.support.socket_helper import HOST, HOSTv6 +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import asynchat + + TIMEOUT = support.LOOPBACK_TIMEOUT DEFAULT_ENCODING = 'utf-8' # the dummy data returned by server over the data channel when @@ -1139,18 +1145,10 @@ def test__all__(self): support.check__all__(self, ftplib, not_exported=not_exported) -def test_main(): - tests = [TestFTPClass, TestTimeouts, - TestIPv6Environment, - TestTLS_FTPClassMixin, TestTLS_FTPClass, - MiscTestCase] - +def setUpModule(): thread_info = threading_helper.threading_setup() - try: - support.run_unittest(*tests) - finally: - threading_helper.threading_cleanup(*thread_info) + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 3320ab7ec6649d..9343d4e9fa3168 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -167,6 +167,7 @@ def test_weakref(self): p = proxy(f) self.assertEqual(f.func, p.func) f = None + support.gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, getattr, p, 'func') def test_with_bound_and_unbound_methods(self): @@ -951,8 +952,9 @@ class TestCmpToKeyC(TestCmpToKey, unittest.TestCase): @support.cpython_only def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) - tp = type(c_functools.cmp_to_key(None)) - self.assertRaises(TypeError, tp) + support.check_disallow_instantiation( + self, type(c_functools.cmp_to_key(None)) + ) class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase): @@ -1162,6 +1164,34 @@ def test_pickle(self): method_copy = pickle.loads(pickle.dumps(method, proto)) self.assertIs(method_copy, method) + + def test_total_ordering_for_metaclasses_issue_44605(self): + + @functools.total_ordering + class SortableMeta(type): + def __new__(cls, name, bases, ns): + return super().__new__(cls, name, bases, ns) + + def __lt__(self, other): + if not isinstance(other, SortableMeta): + pass + return self.__name__ < other.__name__ + + def __eq__(self, other): + if not isinstance(other, SortableMeta): + pass + return self.__name__ == other.__name__ + + class B(metaclass=SortableMeta): + pass + + class A(metaclass=SortableMeta): + pass + + self.assertTrue(A < B) + self.assertFalse(A > B) + + @functools.total_ordering class Orderable_LT: def __init__(self, value): @@ -2381,7 +2411,7 @@ def _(cls, arg): self.assertEqual(A.t(0.0).arg, "base") def test_abstractmethod_register(self): - class Abstract(abc.ABCMeta): + class Abstract(metaclass=abc.ABCMeta): @functools.singledispatchmethod @abc.abstractmethod @@ -2389,6 +2419,10 @@ def add(self, x, y): pass self.assertTrue(Abstract.add.__isabstractmethod__) + self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__) + + with self.assertRaises(TypeError): + Abstract() def test_type_ann_register(self): class A: @@ -2407,6 +2441,183 @@ def _(self, arg: str): self.assertEqual(a.t(''), "str") self.assertEqual(a.t(0.0), "base") + def test_staticmethod_type_ann_register(self): + class A: + @functools.singledispatchmethod + @staticmethod + def t(arg): + return arg + @t.register + @staticmethod + def _(arg: int): + return isinstance(arg, int) + @t.register + @staticmethod + def _(arg: str): + return isinstance(arg, str) + a = A() + + self.assertTrue(A.t(0)) + self.assertTrue(A.t('')) + self.assertEqual(A.t(0.0), 0.0) + + def test_classmethod_type_ann_register(self): + class A: + def __init__(self, arg): + self.arg = arg + + @functools.singledispatchmethod + @classmethod + def t(cls, arg): + return cls("base") + @t.register + @classmethod + def _(cls, arg: int): + return cls("int") + @t.register + @classmethod + def _(cls, arg: str): + return cls("str") + + self.assertEqual(A.t(0).arg, "int") + self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t(0.0).arg, "base") + + def test_method_wrapping_attributes(self): + class A: + @functools.singledispatchmethod + def func(self, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @classmethod + def cls_func(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + @functools.singledispatchmethod + @staticmethod + def static_func(arg: int) -> str: + """My function docstring""" + return str(arg) + + for meth in ( + A.func, + A().func, + A.cls_func, + A().cls_func, + A.static_func, + A().static_func + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual(A.func.__name__, 'func') + self.assertEqual(A().func.__name__, 'func') + self.assertEqual(A.cls_func.__name__, 'cls_func') + self.assertEqual(A().cls_func.__name__, 'cls_func') + self.assertEqual(A.static_func.__name__, 'static_func') + self.assertEqual(A().static_func.__name__, 'static_func') + + def test_double_wrapped_methods(self): + def classmethod_friendly_decorator(func): + wrapped = func.__func__ + @classmethod + @functools.wraps(wrapped) + def wrapper(*args, **kwargs): + return wrapped(*args, **kwargs) + return wrapper + + class WithoutSingleDispatch: + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + try: + yield str(arg) + finally: + return 'Done' + + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + return str(arg) + + class WithSingleDispatch: + @functools.singledispatchmethod + @classmethod + @contextlib.contextmanager + def cls_context_manager(cls, arg: int) -> str: + """My function docstring""" + try: + yield str(arg) + finally: + return 'Done' + + @functools.singledispatchmethod + @classmethod_friendly_decorator + @classmethod + def decorated_classmethod(cls, arg: int) -> str: + """My function docstring""" + return str(arg) + + # These are sanity checks + # to test the test itself is working as expected + with WithoutSingleDispatch.cls_context_manager(5) as foo: + without_single_dispatch_foo = foo + + with WithSingleDispatch.cls_context_manager(5) as foo: + single_dispatch_foo = foo + + self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) + self.assertEqual(single_dispatch_foo, '5') + + self.assertEqual( + WithoutSingleDispatch.decorated_classmethod(5), + WithSingleDispatch.decorated_classmethod(5) + ) + + self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5') + + # Behavioural checks now follow + for method_name in ('cls_context_manager', 'decorated_classmethod'): + with self.subTest(method=method_name): + self.assertEqual( + getattr(WithSingleDispatch, method_name).__name__, + getattr(WithoutSingleDispatch, method_name).__name__ + ) + + self.assertEqual( + getattr(WithSingleDispatch(), method_name).__name__, + getattr(WithoutSingleDispatch(), method_name).__name__ + ) + + for meth in ( + WithSingleDispatch.cls_context_manager, + WithSingleDispatch().cls_context_manager, + WithSingleDispatch.decorated_classmethod, + WithSingleDispatch().decorated_classmethod + ): + with self.subTest(meth=meth): + self.assertEqual(meth.__doc__, 'My function docstring') + self.assertEqual(meth.__annotations__['arg'], int) + + self.assertEqual( + WithSingleDispatch.cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch().cls_context_manager.__name__, + 'cls_context_manager' + ) + self.assertEqual( + WithSingleDispatch.decorated_classmethod.__name__, + 'decorated_classmethod' + ) + self.assertEqual( + WithSingleDispatch().decorated_classmethod.__name__, + 'decorated_classmethod' + ) + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( @@ -2454,6 +2665,74 @@ def f(*args): with self.assertRaisesRegex(TypeError, msg): f() + def test_register_genericalias(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int], lambda arg: "types.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int], lambda arg: "typing.GenericAlias") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[float] | bytes, lambda arg: "typing.Union[typing.GenericAlias]") + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any, lambda arg: "typing.Any") + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + + def test_register_genericalias_decorator(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int]) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(list[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.List[int] | str) + with self.assertRaisesRegex(TypeError, "Invalid first argument to "): + f.register(typing.Any) + + def test_register_genericalias_annotation(self): + @functools.singledispatch + def f(arg): + return "default" + + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int]): + return "types.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float]): + return "typing.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: list[int] | str): + return "types.UnionType(types.GenericAlias)" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.List[float] | bytes): + return "typing.Union[typing.GenericAlias]" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register + def _(arg: typing.Any): + return "typing.Any" + + self.assertEqual(f([1]), "default") + self.assertEqual(f([1.0]), "default") + self.assertEqual(f(""), "default") + self.assertEqual(f(b""), "default") + class CachedCostItem: _cost = 1 diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 4ef11232a33681..5a3944e69e640e 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -329,7 +329,7 @@ def test_annotations(self): def test_fstring_debug_annotations(self): # f-strings with '=' don't round trip very well, so set the expected - # result explicitely. + # result explicitly. self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'") self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'") diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index ee4fe49a57f2af..6c28b2b677ceeb 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,6 +1,6 @@ import unittest import unittest.mock -from test.support import (verbose, refcount_test, run_unittest, +from test.support import (verbose, refcount_test, cpython_only) from test.support.import_helper import import_module from test.support.os_helper import temp_dir, TESTFN, unlink @@ -1361,26 +1361,55 @@ def __del__(self): # empty __dict__. self.assertEqual(x, None) -def test_main(): + +class PythonFinalizationTests(unittest.TestCase): + def test_ast_fini(self): + # bpo-44184: Regression test for subtype_dealloc() when deallocating + # an AST instance also destroy its AST type: subtype_dealloc() must + # not access the type memory after deallocating the instance, since + # the type memory can be freed as well. The test is also related to + # _PyAST_Fini() which clears references to AST types. + code = textwrap.dedent(""" + import ast + import codecs + + # Small AST tree to keep their AST types alive + tree = ast.parse("def f(x, y): return 2*x-y") + x = [tree] + x.append(x) + + # Put the cycle somewhere to survive until the last GC collection. + # Codec search functions are only cleared at the end of + # interpreter_clear(). + def search_func(encoding): + return None + search_func.a = x + codecs.register(search_func) + """) + assert_python_ok("-c", code) + + +def setUpModule(): + global enabled, debug enabled = gc.isenabled() gc.disable() assert not gc.isenabled() debug = gc.get_debug() gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak + gc.collect() # Delete 2nd generation garbage + + +def tearDownModule(): + gc.set_debug(debug) + # test gc.enable() even if GC is disabled by default + if verbose: + print("restoring automatic collection") + # make sure to always test gc.enable() + gc.enable() + assert gc.isenabled() + if not enabled: + gc.disable() - try: - gc.collect() # Delete 2nd generation garbage - run_unittest(GCTests, GCTogglingTests, GCCallbackTests) - finally: - gc.set_debug(debug) - # test gc.enable() even if GC is disabled by default - if verbose: - print("restoring automatic collection") - # make sure to always test gc.enable() - gc.enable() - assert gc.isenabled() - if not enabled: - gc.disable() if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py index 22c75bae987219..5f554897f86a0b 100644 --- a/Lib/test/test_gdb.py +++ b/Lib/test/test_gdb.py @@ -145,7 +145,8 @@ class DebuggerTests(unittest.TestCase): def get_stack_trace(self, source=None, script=None, breakpoint=BREAKPOINT_FN, cmds_after_breakpoint=None, - import_site=False): + import_site=False, + ignore_stderr=False): ''' Run 'python -c SOURCE' under gdb with a breakpoint. @@ -224,8 +225,9 @@ def get_stack_trace(self, source=None, script=None, # Use "args" to invoke gdb, capturing stdout, stderr: out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED) - for line in err.splitlines(): - print(line, file=sys.stderr) + if not ignore_stderr: + for line in err.splitlines(): + print(line, file=sys.stderr) # bpo-34007: Sometimes some versions of the shared libraries that # are part of the traceback are compiled in optimised mode and the @@ -908,6 +910,9 @@ def bar(): cmd, breakpoint=func_name, cmds_after_breakpoint=['bt', 'py-bt'], + # bpo-45207: Ignore 'Function "meth_varargs" not + # defined.' message in stderr. + ignore_stderr=True, ) self.assertIn(f'>> from test.support import gc_collect + Sending a value into a started generator: >>> def f(): @@ -2163,7 +2199,7 @@ def printsolution(self, x): >>> g = f() >>> next(g) ->>> del g +>>> del g; gc_collect() # For PyPy or other GCs. exiting @@ -2178,7 +2214,7 @@ def printsolution(self, x): >>> g = f() >>> next(g) ->>> del g +>>> del g; gc_collect() # For PyPy or other GCs. finally diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 9f927392fc8740..0daaff099a868d 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -2,6 +2,7 @@ import unittest import pickle +import copy from collections import ( defaultdict, deque, OrderedDict, Counter, UserDict, UserList ) @@ -270,11 +271,30 @@ class MyType(type): def test_pickle(self): alias = GenericAlias(list, T) - s = pickle.dumps(alias) - loaded = pickle.loads(s) - self.assertEqual(alias.__origin__, loaded.__origin__) - self.assertEqual(alias.__args__, loaded.__args__) - self.assertEqual(alias.__parameters__, loaded.__parameters__) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(alias, proto) + loaded = pickle.loads(s) + self.assertEqual(loaded.__origin__, alias.__origin__) + self.assertEqual(loaded.__args__, alias.__args__) + self.assertEqual(loaded.__parameters__, alias.__parameters__) + + def test_copy(self): + class X(list): + def __copy__(self): + return self + def __deepcopy__(self, memo): + return self + + for origin in list, deque, X: + alias = GenericAlias(origin, T) + copied = copy.copy(alias) + self.assertEqual(copied.__origin__, alias.__origin__) + self.assertEqual(copied.__args__, alias.__args__) + self.assertEqual(copied.__parameters__, alias.__parameters__) + copied = copy.deepcopy(alias) + self.assertEqual(copied.__origin__, alias.__origin__) + self.assertEqual(copied.__args__, alias.__args__) + self.assertEqual(copied.__parameters__, alias.__parameters__) def test_union(self): a = typing.Union[list[int], list[str]] @@ -317,96 +337,6 @@ def __new__(cls, *args, **kwargs): with self.assertRaises(TypeError): Bad(list, int, bad=int) - def test_abc_callable(self): - # A separate test is needed for Callable since it uses a subclass of - # GenericAlias. - alias = Callable[[int, str], float] - with self.subTest("Testing subscription"): - self.assertIs(alias.__origin__, Callable) - self.assertEqual(alias.__args__, (int, str, float)) - self.assertEqual(alias.__parameters__, ()) - - with self.subTest("Testing instance checks"): - self.assertIsInstance(alias, GenericAlias) - - with self.subTest("Testing weakref"): - self.assertEqual(ref(alias)(), alias) - - with self.subTest("Testing pickling"): - s = pickle.dumps(alias) - loaded = pickle.loads(s) - self.assertEqual(alias.__origin__, loaded.__origin__) - self.assertEqual(alias.__args__, loaded.__args__) - self.assertEqual(alias.__parameters__, loaded.__parameters__) - - with self.subTest("Testing TypeVar substitution"): - C1 = Callable[[int, T], T] - C2 = Callable[[K, T], V] - C3 = Callable[..., T] - self.assertEqual(C1[str], Callable[[int, str], str]) - self.assertEqual(C2[int, float, str], Callable[[int, float], str]) - self.assertEqual(C3[int], Callable[..., int]) - - # multi chaining - C4 = C2[int, V, str] - self.assertEqual(repr(C4).split(".")[-1], "Callable[[int, ~V], str]") - self.assertEqual(repr(C4[dict]).split(".")[-1], "Callable[[int, dict], str]") - self.assertEqual(C4[dict], Callable[[int, dict], str]) - - # substitute a nested GenericAlias (both typing and the builtin - # version) - C5 = Callable[[typing.List[T], tuple[K, T], V], int] - self.assertEqual(C5[int, str, float], - Callable[[typing.List[int], tuple[str, int], float], int]) - - with self.subTest("Testing type erasure"): - class C1(Callable): - def __call__(self): - return None - a = C1[[int], T] - self.assertIs(a().__class__, C1) - self.assertEqual(a().__orig_class__, C1[[int], T]) - - # bpo-42195 - with self.subTest("Testing collections.abc.Callable's consistency " - "with typing.Callable"): - c1 = typing.Callable[[int, str], dict] - c2 = Callable[[int, str], dict] - self.assertEqual(c1.__args__, c2.__args__) - self.assertEqual(hash(c1.__args__), hash(c2.__args__)) - - with self.subTest("Testing ParamSpec uses"): - P = typing.ParamSpec('P') - C1 = Callable[P, T] - # substitution - self.assertEqual(C1[int, str], Callable[[int], str]) - self.assertEqual(C1[[int, str], str], Callable[[int, str], str]) - self.assertEqual(repr(C1).split(".")[-1], "Callable[~P, ~T]") - self.assertEqual(repr(C1[int, str]).split(".")[-1], "Callable[[int], str]") - - C2 = Callable[P, int] - # special case in PEP 612 where - # X[int, str, float] == X[[int, str, float]] - self.assertEqual(C2[int, str, float], C2[[int, str, float]]) - self.assertEqual(repr(C2).split(".")[-1], "Callable[~P, int]") - self.assertEqual(repr(C2[int, str]).split(".")[-1], "Callable[[int, str], int]") - - with self.subTest("Testing Concatenate uses"): - P = typing.ParamSpec('P') - C1 = Callable[typing.Concatenate[int, P], int] - self.assertEqual(repr(C1), "collections.abc.Callable" - "[typing.Concatenate[int, ~P], int]") - - with self.subTest("Testing TypeErrors"): - with self.assertRaisesRegex(TypeError, "variables left in"): - alias[int] - P = typing.ParamSpec('P') - C1 = Callable[P, T] - with self.assertRaisesRegex(TypeError, "many arguments for"): - C1[int, str, str] - with self.assertRaisesRegex(TypeError, "few arguments for"): - C1[int] - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index c67e6f51a23464..e0db9e40e650b6 100644 --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -874,6 +874,13 @@ def test_s_hash(self): self.assertRaises(TypeError, getargs_s_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_s_hash, None) + def test_s_hash_int(self): + # "s#" without PY_SSIZE_T_CLEAN defined. + from _testcapi import getargs_s_hash_int + self.assertRaises(SystemError, getargs_s_hash_int, "abc") + self.assertRaises(SystemError, getargs_s_hash_int, x=42) + # getargs_s_hash_int() don't raise SystemError because skipitem() is not called. + def test_z(self): from _testcapi import getargs_z self.assertEqual(getargs_z('abc\xe9'), b'abc\xc3\xa9') diff --git a/Lib/test/test_global.py b/Lib/test/test_global.py index c71d055297e0c9..d0bde3fd040e60 100644 --- a/Lib/test/test_global.py +++ b/Lib/test/test_global.py @@ -1,6 +1,6 @@ """Verify that warnings are issued for global statements following use.""" -from test.support import run_unittest, check_syntax_error +from test.support import check_syntax_error from test.support.warnings_helper import check_warnings import unittest import warnings @@ -53,10 +53,12 @@ def test4(self): compile(prog_text_4, "", "exec") -def test_main(): - with warnings.catch_warnings(): - warnings.filterwarnings("error", module="") - run_unittest(GlobalTests) +def setUpModule(): + cm = warnings.catch_warnings() + cm.__enter__() + unittest.addModuleCleanup(cm.__exit__, None, None, None) + warnings.filterwarnings("error", module="") + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index ebc9dde97e7306..b6c457465609af 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -177,8 +177,10 @@ def test_floats(self): def test_float_exponent_tokenization(self): # See issue 21642. - self.assertEqual(1 if 1else 0, 1) - self.assertEqual(1 if 0else 0, 0) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + self.assertEqual(eval("1 if 1else 0"), 1) + self.assertEqual(eval("1 if 0else 0"), 0) self.assertRaises(SyntaxError, eval, "0 if 1Else 0") def test_underscore_literals(self): @@ -211,6 +213,92 @@ def test_bad_numerical_literals(self): check("1e2_", "invalid decimal literal") check("1e+", "invalid decimal literal") + def test_end_of_numerical_literals(self): + def check(test): + with self.assertWarns(DeprecationWarning): + compile(test, "", "eval") + + def check_error(test): + with warnings.catch_warnings(record=True) as w: + with self.assertRaises(SyntaxError): + compile(test, "", "eval") + self.assertEqual(w, []) + + check_error("0xfand x") + check("0o7and x") + check("0b1and x") + check("9and x") + check("0and x") + check("1.and x") + check("1e3and x") + check("1jand x") + + check("0xfor x") + check("0o7or x") + check("0b1or x") + check("9or x") + check_error("0or x") + check("1.or x") + check("1e3or x") + check("1jor x") + + check("0xfin x") + check("0o7in x") + check("0b1in x") + check("9in x") + check("0in x") + check("1.in x") + check("1e3in x") + check("1jin x") + + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SyntaxWarning) + check("0xfis x") + check("0o7is x") + check("0b1is x") + check("9is x") + check("0is x") + check("1.is x") + check("1e3is x") + check("1jis x") + + check("0xfif x else y") + check("0o7if x else y") + check("0b1if x else y") + check("9if x else y") + check("0if x else y") + check("1.if x else y") + check("1e3if x else y") + check("1jif x else y") + + check_error("x if 0xfelse y") + check("x if 0o7else y") + check("x if 0b1else y") + check("x if 9else y") + check("x if 0else y") + check("x if 1.else y") + check("x if 1e3else y") + check("x if 1jelse y") + + check("[0x1ffor x in ()]") + check("[0x1for x in ()]") + check("[0xfor x in ()]") + check("[0o7for x in ()]") + check("[0b1for x in ()]") + check("[9for x in ()]") + check("[1.for x in ()]") + check("[1e3for x in ()]") + check("[1jfor x in ()]") + + check_error("0xfspam") + check_error("0o7spam") + check_error("0b1spam") + check_error("9spam") + check_error("0spam") + check_error("1.spam") + check_error("1e3spam") + check_error("1jspam") + def test_string_literals(self): x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y) x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39) @@ -385,7 +473,7 @@ class CC(metaclass=CMeta): def test_var_annot_module_semantics(self): self.assertEqual(test.__annotations__, {}) self.assertEqual(ann_module.__annotations__, - {1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int]}) + {1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int], 'u': int | float}) self.assertEqual(ann_module.M.__annotations__, {'123': 123, 'o': type}) self.assertEqual(ann_module2.__annotations__, {}) diff --git a/Lib/test/test_graphlib.py b/Lib/test/test_graphlib.py index 00432537f22d00..86246a62ed6422 100644 --- a/Lib/test/test_graphlib.py +++ b/Lib/test/test_graphlib.py @@ -13,13 +13,19 @@ def static_order_with_groups(ts): nodes = ts.get_ready() for node in nodes: ts.done(node) - yield nodes + yield tuple(sorted(nodes)) ts = graphlib.TopologicalSorter(graph) self.assertEqual(list(static_order_with_groups(ts)), list(expected)) ts = graphlib.TopologicalSorter(graph) - self.assertEqual(list(ts.static_order()), list(chain(*expected))) + # need to be a bit careful comparing the result of ts.static_order and + # expected, because the order within a group is dependent on set + # iteration order + it = iter(ts.static_order()) + for group in expected: + tsgroup = {next(it) for element in group} + self.assertEqual(set(group), tsgroup) def _assert_cycle(self, graph, cycle): ts = graphlib.TopologicalSorter() @@ -36,7 +42,7 @@ def _assert_cycle(self, graph, cycle): def test_simple_cases(self): self._test_graph( {2: {11}, 9: {11, 8}, 10: {11, 3}, 11: {7, 5}, 8: {7, 3}}, - [(3, 5, 7), (11, 8), (2, 10, 9)], + [(3, 5, 7), (8, 11), (2, 9, 10)], ) self._test_graph({1: {}}, [(1,)]) @@ -80,7 +86,7 @@ def test_no_dependencies(self): def test_the_node_multiple_times(self): # Test same node multiple times in dependencies - self._test_graph({1: {2}, 3: {4}, 0: [2, 4, 4, 4, 4, 4]}, [(2, 4), (1, 3, 0)]) + self._test_graph({1: {2}, 3: {4}, 0: [2, 4, 4, 4, 4, 4]}, [(2, 4), (0, 1, 3)]) # Test adding the same dependency multiple times ts = graphlib.TopologicalSorter() @@ -242,3 +248,6 @@ def check_order_with_hash_seed(seed): self.assertNotEqual(run1, "") self.assertNotEqual(run2, "") self.assertEqual(run1, run2) + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index 446b61ab439ffe..f86e767ac0e59c 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -10,7 +10,6 @@ import sys import unittest from subprocess import PIPE, Popen -from test import support from test.support import import_helper from test.support import os_helper from test.support import _4G, bigmemtest @@ -592,6 +591,15 @@ def test_prepend_error(self): with gzip.open(self.filename, "rb") as f: f._buffer.raw._fp.prepend() + def test_issue44439(self): + q = array.array('Q', [1, 2, 3, 4, 5]) + LENGTH = len(q) * q.itemsize + + with gzip.GzipFile(fileobj=io.BytesIO(), mode='w') as f: + self.assertEqual(f.write(q), LENGTH) + self.assertEqual(f.tell(), LENGTH) + + class TestOpen(BaseTest): def test_binary_modes(self): uncompressed = data1 * 50 @@ -833,9 +841,5 @@ def test_decompress_cannot_have_flags_compression(self): self.assertEqual(out, b'') -def test_main(verbose=None): - support.run_unittest(TestGzip, TestOpen, TestCommandLine) - - if __name__ == "__main__": - test_main(verbose=True) + unittest.main() diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index ad2ed69e24b2c4..110eb48fd4f8ca 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -48,12 +48,15 @@ builtin_hashlib = None try: - from _hashlib import HASH, HASHXOF, openssl_md_meth_names + from _hashlib import HASH, HASHXOF, openssl_md_meth_names, get_fips_mode except ImportError: HASH = None HASHXOF = None openssl_md_meth_names = frozenset() + def get_fips_mode(): + return 0 + try: import _blake2 except ImportError: @@ -192,10 +195,7 @@ def hash_constructors(self): @property def is_fips_mode(self): - if hasattr(self._hashlib, "get_fips_mode"): - return self._hashlib.get_fips_mode() - else: - return None + return get_fips_mode() def test_hash_array(self): a = array.array("b", range(10)) @@ -909,28 +909,29 @@ def test_disallow_instantiation(self): continue # all other types have DISALLOW_INSTANTIATION for constructor in constructors: - h = constructor() + # In FIPS mode some algorithms are not available raising ValueError + try: + h = constructor() + except ValueError: + continue with self.subTest(constructor=constructor): - hash_type = type(h) - self.assertRaises(TypeError, hash_type) + support.check_disallow_instantiation(self, type(h)) @unittest.skipUnless(HASH is not None, 'need _hashlib') - def test_hash_disallow_instanciation(self): + def test_hash_disallow_instantiation(self): # internal types like _hashlib.HASH are not constructable - with self.assertRaisesRegex( - TypeError, "cannot create '_hashlib.HASH' instance" - ): - HASH() - with self.assertRaisesRegex( - TypeError, "cannot create '_hashlib.HASHXOF' instance" - ): - HASHXOF() + support.check_disallow_instantiation(self, HASH) + support.check_disallow_instantiation(self, HASHXOF) def test_readonly_types(self): for algorithm, constructors in self.constructors_to_test.items(): # all other types have DISALLOW_INSTANTIATION for constructor in constructors: - hash_type = type(constructor()) + # In FIPS mode some algorithms are not available raising ValueError + try: + hash_type = type(constructor()) + except ValueError: + continue with self.subTest(hash_type=hash_type): with self.assertRaisesRegex(TypeError, "immutable type"): hash_type.value = False @@ -1016,7 +1017,7 @@ def _test_pbkdf2_hmac(self, pbkdf2, supported): self.assertEqual(out, expected, (digest_name, password, salt, rounds)) - with self.assertRaisesRegex(ValueError, 'unsupported hash type'): + with self.assertRaisesRegex(ValueError, '.*unsupported.*'): pbkdf2('unknown', b'pass', b'salt', 1) if 'sha1' in supported: @@ -1056,6 +1057,7 @@ def test_pbkdf2_hmac_c(self): @unittest.skipUnless(hasattr(hashlib, 'scrypt'), ' test requires OpenSSL > 1.1') + @unittest.skipIf(get_fips_mode(), reason="scrypt is blocked in FIPS mode") def test_scrypt(self): for password, salt, n, r, p, expected in self.scrypt_test_vectors: result = hashlib.scrypt(password, salt=salt, n=n, r=r, p=p) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index ebbc62745707cc..cb1e4505b02a30 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -146,11 +146,11 @@ def test_heappushpop(self): self.assertEqual(type(h[0]), int) self.assertEqual(type(x), float) - h = [10]; + h = [10] x = self.module.heappushpop(h, 9) self.assertEqual((h, x), ([10], 9)) - h = [10]; + h = [10] x = self.module.heappushpop(h, 11) self.assertEqual((h, x), ([11], 10)) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 964acd0361e342..7cf99735ca39f0 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -6,7 +6,7 @@ import unittest.mock import warnings -from test.support import hashlib_helper +from test.support import hashlib_helper, check_disallow_instantiation from _operator import _compare_digest as operator_compare_digest @@ -439,11 +439,7 @@ def test_withmodule(self): @unittest.skipUnless(C_HMAC is not None, 'need _hashlib') def test_internal_types(self): # internal types like _hashlib.C_HMAC are not constructable - with self.assertRaisesRegex( - TypeError, "cannot create '_hashlib.HMAC' instance" - ): - C_HMAC() - + check_disallow_instantiation(self, C_HMAC) with self.assertRaisesRegex(TypeError, "immutable type"): C_HMAC.value = None diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index fdf15efde12ef2..9450104d0b9a75 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1920,14 +1920,5 @@ def test_session_cookies(self): self.assertNotEqual(counter["session_before"], 0) -def test_main(verbose=None): - test.support.run_unittest( - DateTimeTests, - HeaderTests, - CookieTests, - FileCookieJarTests, - LWPCookieTests, - ) - if __name__ == "__main__": - test_main(verbose=True) + unittest.main() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index db41e29a4b8394..77152cf64565e0 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1,4 +1,3 @@ -import enum import errno from http import client, HTTPStatus import io @@ -525,150 +524,6 @@ def test_dir_with_added_behavior_on_status(self): # see issue40084 self.assertTrue({'description', 'name', 'phrase', 'value'} <= set(dir(HTTPStatus(404)))) - def test_simple_httpstatus(self): - class CheckedHTTPStatus(enum.IntEnum): - """HTTP status codes and reason phrases - - Status codes from the following RFCs are all observed: - - * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616 - * RFC 6585: Additional HTTP Status Codes - * RFC 3229: Delta encoding in HTTP - * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518 - * RFC 5842: Binding Extensions to WebDAV - * RFC 7238: Permanent Redirect - * RFC 2295: Transparent Content Negotiation in HTTP - * RFC 2774: An HTTP Extension Framework - * RFC 7725: An HTTP Status Code to Report Legal Obstacles - * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2) - * RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) - * RFC 8297: An HTTP Status Code for Indicating Hints - * RFC 8470: Using Early Data in HTTP - """ - def __new__(cls, value, phrase, description=''): - obj = int.__new__(cls, value) - obj._value_ = value - - obj.phrase = phrase - obj.description = description - return obj - # informational - CONTINUE = 100, 'Continue', 'Request received, please continue' - SWITCHING_PROTOCOLS = (101, 'Switching Protocols', - 'Switching to new protocol; obey Upgrade header') - PROCESSING = 102, 'Processing' - EARLY_HINTS = 103, 'Early Hints' - # success - OK = 200, 'OK', 'Request fulfilled, document follows' - CREATED = 201, 'Created', 'Document created, URL follows' - ACCEPTED = (202, 'Accepted', - 'Request accepted, processing continues off-line') - NON_AUTHORITATIVE_INFORMATION = (203, - 'Non-Authoritative Information', 'Request fulfilled from cache') - NO_CONTENT = 204, 'No Content', 'Request fulfilled, nothing follows' - RESET_CONTENT = 205, 'Reset Content', 'Clear input form for further input' - PARTIAL_CONTENT = 206, 'Partial Content', 'Partial content follows' - MULTI_STATUS = 207, 'Multi-Status' - ALREADY_REPORTED = 208, 'Already Reported' - IM_USED = 226, 'IM Used' - # redirection - MULTIPLE_CHOICES = (300, 'Multiple Choices', - 'Object has several resources -- see URI list') - MOVED_PERMANENTLY = (301, 'Moved Permanently', - 'Object moved permanently -- see URI list') - FOUND = 302, 'Found', 'Object moved temporarily -- see URI list' - SEE_OTHER = 303, 'See Other', 'Object moved -- see Method and URL list' - NOT_MODIFIED = (304, 'Not Modified', - 'Document has not changed since given time') - USE_PROXY = (305, 'Use Proxy', - 'You must use proxy specified in Location to access this resource') - TEMPORARY_REDIRECT = (307, 'Temporary Redirect', - 'Object moved temporarily -- see URI list') - PERMANENT_REDIRECT = (308, 'Permanent Redirect', - 'Object moved permanently -- see URI list') - # client error - BAD_REQUEST = (400, 'Bad Request', - 'Bad request syntax or unsupported method') - UNAUTHORIZED = (401, 'Unauthorized', - 'No permission -- see authorization schemes') - PAYMENT_REQUIRED = (402, 'Payment Required', - 'No payment -- see charging schemes') - FORBIDDEN = (403, 'Forbidden', - 'Request forbidden -- authorization will not help') - NOT_FOUND = (404, 'Not Found', - 'Nothing matches the given URI') - METHOD_NOT_ALLOWED = (405, 'Method Not Allowed', - 'Specified method is invalid for this resource') - NOT_ACCEPTABLE = (406, 'Not Acceptable', - 'URI not available in preferred format') - PROXY_AUTHENTICATION_REQUIRED = (407, - 'Proxy Authentication Required', - 'You must authenticate with this proxy before proceeding') - REQUEST_TIMEOUT = (408, 'Request Timeout', - 'Request timed out; try again later') - CONFLICT = 409, 'Conflict', 'Request conflict' - GONE = (410, 'Gone', - 'URI no longer exists and has been permanently removed') - LENGTH_REQUIRED = (411, 'Length Required', - 'Client must specify Content-Length') - PRECONDITION_FAILED = (412, 'Precondition Failed', - 'Precondition in headers is false') - REQUEST_ENTITY_TOO_LARGE = (413, 'Request Entity Too Large', - 'Entity is too large') - REQUEST_URI_TOO_LONG = (414, 'Request-URI Too Long', - 'URI is too long') - UNSUPPORTED_MEDIA_TYPE = (415, 'Unsupported Media Type', - 'Entity body in unsupported format') - REQUESTED_RANGE_NOT_SATISFIABLE = (416, - 'Requested Range Not Satisfiable', - 'Cannot satisfy request range') - EXPECTATION_FAILED = (417, 'Expectation Failed', - 'Expect condition could not be satisfied') - IM_A_TEAPOT = (418, 'I\'m a Teapot', - 'Server refuses to brew coffee because it is a teapot.') - MISDIRECTED_REQUEST = (421, 'Misdirected Request', - 'Server is not able to produce a response') - UNPROCESSABLE_ENTITY = 422, 'Unprocessable Entity' - LOCKED = 423, 'Locked' - FAILED_DEPENDENCY = 424, 'Failed Dependency' - TOO_EARLY = 425, 'Too Early' - UPGRADE_REQUIRED = 426, 'Upgrade Required' - PRECONDITION_REQUIRED = (428, 'Precondition Required', - 'The origin server requires the request to be conditional') - TOO_MANY_REQUESTS = (429, 'Too Many Requests', - 'The user has sent too many requests in ' - 'a given amount of time ("rate limiting")') - REQUEST_HEADER_FIELDS_TOO_LARGE = (431, - 'Request Header Fields Too Large', - 'The server is unwilling to process the request because its header ' - 'fields are too large') - UNAVAILABLE_FOR_LEGAL_REASONS = (451, - 'Unavailable For Legal Reasons', - 'The server is denying access to the ' - 'resource as a consequence of a legal demand') - # server errors - INTERNAL_SERVER_ERROR = (500, 'Internal Server Error', - 'Server got itself in trouble') - NOT_IMPLEMENTED = (501, 'Not Implemented', - 'Server does not support this operation') - BAD_GATEWAY = (502, 'Bad Gateway', - 'Invalid responses from another server/proxy') - SERVICE_UNAVAILABLE = (503, 'Service Unavailable', - 'The server cannot process the request due to a high load') - GATEWAY_TIMEOUT = (504, 'Gateway Timeout', - 'The gateway server did not receive a timely response') - HTTP_VERSION_NOT_SUPPORTED = (505, 'HTTP Version Not Supported', - 'Cannot fulfill request') - VARIANT_ALSO_NEGOTIATES = 506, 'Variant Also Negotiates' - INSUFFICIENT_STORAGE = 507, 'Insufficient Storage' - LOOP_DETECTED = 508, 'Loop Detected' - NOT_EXTENDED = 510, 'Not Extended' - NETWORK_AUTHENTICATION_REQUIRED = (511, - 'Network Authentication Required', - 'The client needs to authenticate to gain network access') - enum._test_simple_enum(CheckedHTTPStatus, HTTPStatus) - - def test_status_lines(self): # Test HTTP status lines @@ -1180,6 +1035,19 @@ def test_overflowing_header_line(self): resp = client.HTTPResponse(FakeSocket(body)) self.assertRaises(client.LineTooLong, resp.begin) + def test_overflowing_header_limit_after_100(self): + body = ( + 'HTTP/1.1 100 OK\r\n' + 'r\n' * 32768 + ) + resp = client.HTTPResponse(FakeSocket(body)) + with self.assertRaises(client.HTTPException) as cm: + resp.begin() + # We must assert more because other reasonable errors that we + # do not want can also be HTTPException derived. + self.assertIn('got more than ', str(cm.exception)) + self.assertIn('headers', str(cm.exception)) + def test_overflowing_chunked_line(self): body = ( 'HTTP/1.1 200 OK\r\n' @@ -1581,7 +1449,7 @@ def readline(self, limit): class OfflineTest(TestCase): def test_all(self): # Documented objects defined in the module should be in __all__ - expected = {"responses"} # White-list documented dict() object + expected = {"responses"} # Allowlist documented dict() object # HTTPMessage, parse_headers(), and the HTTP status code constants are # intentionally omitted for simplicity denylist = {"HTTPMessage", "parse_headers"} diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 6b17817b22bf05..1cc020f63539de 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -259,7 +259,7 @@ def test_send_error(self): for code in (HTTPStatus.NO_CONTENT, HTTPStatus.NOT_MODIFIED, HTTPStatus.PROCESSING, HTTPStatus.RESET_CONTENT, HTTPStatus.SWITCHING_PROTOCOLS): - self.con.request('SEND_ERROR', '/{:d}'.format(code)) + self.con.request('SEND_ERROR', '/{}'.format(code)) res = self.con.getresponse() self.assertEqual(code, res.status) self.assertEqual(None, res.getheader('Content-Length')) @@ -276,7 +276,7 @@ def test_head_via_send_error(self): for code in (HTTPStatus.OK, HTTPStatus.NO_CONTENT, HTTPStatus.NOT_MODIFIED, HTTPStatus.RESET_CONTENT, HTTPStatus.SWITCHING_PROTOCOLS): - self.con.request('HEAD', '/{:d}'.format(code)) + self.con.request('HEAD', '/{}'.format(code)) res = self.con.getresponse() self.assertEqual(code, res.status) if code == HTTPStatus.OK: @@ -428,6 +428,7 @@ def test_get(self): self.check_status_and_reason(response, HTTPStatus.OK) response = self.request(self.base_url) self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY) + self.assertEqual(response.getheader("Content-Length"), "0") response = self.request(self.base_url + '/?hi=2') self.check_status_and_reason(response, HTTPStatus.OK) response = self.request(self.base_url + '?hi=1') @@ -592,9 +593,18 @@ def test_html_escape_filename(self): #!%s import os -print("Content-type: text/plain") +print("X-ambv: was here") +print("Content-type: text/html") print() -print(repr(os.environ)) +print("
      ")
      +for k, v in os.environ.items():
      +    try:
      +        k.encode('ascii')
      +        v.encode('ascii')
      +    except UnicodeEncodeError:
      +        continue  # see: BPO-44647
      +    print(f"{k}={v}")
      +print("
      ") """ @@ -849,8 +859,8 @@ def test_accept(self): with self.subTest(headers): res = self.request('/cgi-bin/file6.py', 'GET', headers=headers) self.assertEqual(http.HTTPStatus.OK, res.status) - expected = f"'HTTP_ACCEPT': {expected!r}" - self.assertIn(expected.encode('ascii'), res.read()) + expected = f"HTTP_ACCEPT={expected}".encode('ascii') + self.assertIn(expected, res.read()) class SocketlessRequestHandler(SimpleHTTPRequestHandler): @@ -1292,21 +1302,9 @@ def test_server_test_ipv4(self, _): self.assertEqual(mock_server.address_family, socket.AF_INET) -def test_main(verbose=None): - cwd = os.getcwd() - try: - support.run_unittest( - RequestHandlerLoggingTestCase, - BaseHTTPRequestHandlerTestCase, - BaseHTTPServerTestCase, - SimpleHTTPServerTestCase, - CGIHTTPServerTestCase, - SimpleHTTPRequestHandlerTestCase, - MiscTestCase, - ScriptTestCase - ) - finally: - os.chdir(cwd) +def setUpModule(): + unittest.addModuleCleanup(os.chdir, os.getcwd()) + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index c2b935f58164e5..30b553746af11a 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -387,7 +387,7 @@ def cmd_AUTHENTICATE(self, tag, args): self.assertEqual(code, 'OK') self.assertEqual(server.response, b'ZmFrZQ==\r\n') # b64 encoded 'fake' - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def test_login_cram_md5_bytes(self): class AuthHandler(SimpleIMAPHandler): capabilities = 'LOGINDISABLED AUTH=CRAM-MD5' @@ -405,7 +405,7 @@ def cmd_AUTHENTICATE(self, tag, args): ret, _ = client.login_cram_md5("tim", b"tanstaaftanstaaf") self.assertEqual(ret, "OK") - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def test_login_cram_md5_plain_text(self): class AuthHandler(SimpleIMAPHandler): capabilities = 'LOGINDISABLED AUTH=CRAM-MD5' @@ -851,7 +851,7 @@ def cmd_AUTHENTICATE(self, tag, args): b'ZmFrZQ==\r\n') # b64 encoded 'fake' @threading_helper.reap_threads - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def test_login_cram_md5(self): class AuthHandler(SimpleIMAPHandler): diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 8fe3e1d4bf38d8..97447619b90d2d 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -1086,7 +1086,7 @@ def test_get_sourcefile(self): # Given a valid bytecode path, return the path to the corresponding # source file if it exists. with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: - _path_isfile.return_value = True; + _path_isfile.return_value = True path = TESTFN + '.pyc' expect = TESTFN + '.py' self.assertEqual(_get_sourcefile(path), expect) @@ -1095,7 +1095,7 @@ def test_get_sourcefile_no_source(self): # Given a valid bytecode path without a corresponding source path, # return the original bytecode path. with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: - _path_isfile.return_value = False; + _path_isfile.return_value = False path = TESTFN + '.pyc' self.assertEqual(_get_sourcefile(path), path) diff --git a/Lib/test/test_importlib/source/test_source_encoding.py b/Lib/test/test_importlib/source/test_source_encoding.py index 980855fe1ade18..c0b9b031262eb7 100644 --- a/Lib/test/test_importlib/source/test_source_encoding.py +++ b/Lib/test/test_importlib/source/test_source_encoding.py @@ -23,7 +23,7 @@ class EncodingTest: PEP 263 specifies how that can change on a per-file basis. Either the first or second line can contain the encoding line [encoding first line] - encoding second line]. If the file has the BOM marker it is considered UTF-8 + [encoding second line]. If the file has the BOM marker it is considered UTF-8 implicitly [BOM]. If any encoding is specified it must be UTF-8, else it is an error [BOM and utf-8][BOM conflict]. diff --git a/Lib/test/test_importlib/test_locks.py b/Lib/test/test_importlib/test_locks.py index 0e94ce91801d67..9290bac80a78ac 100644 --- a/Lib/test/test_importlib/test_locks.py +++ b/Lib/test/test_importlib/test_locks.py @@ -4,6 +4,7 @@ import sys import threading +import unittest import weakref from test import support @@ -139,15 +140,10 @@ def test_all_locks(self): ) = test_util.test_both(LifetimeTests, init=init) -@threading_helper.reap_threads -def test_main(): - support.run_unittest(Frozen_ModuleLockAsRLockTests, - Source_ModuleLockAsRLockTests, - Frozen_DeadlockAvoidanceTests, - Source_DeadlockAvoidanceTests, - Frozen_LifetimeTests, - Source_LifetimeTests) +def setUpModule(): + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == '__main__': - test_main() + unittets.main() diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py index 825edc10f121a2..4a45312e31cd58 100644 --- a/Lib/test/test_importlib/test_metadata_api.py +++ b/Lib/test/test_importlib/test_metadata_api.py @@ -3,6 +3,7 @@ import unittest import warnings import importlib +import contextlib from . import fixtures from importlib.metadata import ( @@ -17,6 +18,13 @@ ) +@contextlib.contextmanager +def suppress_known_deprecation(): + with warnings.catch_warnings(record=True) as ctx: + warnings.simplefilter('default') + yield ctx + + class APITests( fixtures.EggInfoPkg, fixtures.DistInfoPkg, @@ -118,8 +126,7 @@ def test_entry_points_dict_construction(self): # Prior versions of entry_points() returned simple lists and # allowed casting those lists into maps by name using ``dict()``. # Capture this now deprecated use-case. - with warnings.catch_warnings(record=True) as caught: - warnings.filterwarnings("default", category=DeprecationWarning) + with suppress_known_deprecation() as caught: eps = dict(entry_points(group='entries')) assert 'main' in eps @@ -130,11 +137,27 @@ def test_entry_points_dict_construction(self): assert expected.category is DeprecationWarning assert "Construction of dict of EntryPoints is deprecated" in str(expected) + def test_entry_points_by_index(self): + """ + Prior versions of Distribution.entry_points would return a + tuple that allowed access by index. + Capture this now deprecated use-case + See python/importlib_metadata#300 and bpo-44246. + """ + eps = distribution('distinfo-pkg').entry_points + with suppress_known_deprecation() as caught: + eps[0] + + # check warning + expected = next(iter(caught)) + assert expected.category is DeprecationWarning + assert "Accessing entry points by index is deprecated" in str(expected) + def test_entry_points_groups_getitem(self): # Prior versions of entry_points() returned a dict. Ensure # that callers using '.__getitem__()' are supported but warned to # migrate. - with warnings.catch_warnings(record=True): + with suppress_known_deprecation(): entry_points()['entries'] == entry_points(group='entries') with self.assertRaises(KeyError): @@ -144,7 +167,7 @@ def test_entry_points_groups_get(self): # Prior versions of entry_points() returned a dict. Ensure # that callers using '.get()' are supported but warned to # migrate. - with warnings.catch_warnings(record=True): + with suppress_known_deprecation(): entry_points().get('missing', 'default') == 'default' entry_points().get('entries', 'default') == entry_points()['entries'] entry_points().get('missing', ()) == () @@ -212,6 +235,7 @@ def test_more_complex_deps_requires_text(self): [extra1] dep4 + dep6@ git+https://example.com/python/dep.git@v1.0.0 [extra2:python_version < "3"] dep5 @@ -224,6 +248,7 @@ def test_more_complex_deps_requires_text(self): 'dep3; python_version < "3"', 'dep4; extra == "extra1"', 'dep5; (python_version < "3") and extra == "extra2"', + 'dep6@ git+https://example.com/python/dep.git@v1.0.0 ; extra == "extra1"', ] # It's important that the environment marker expression be # wrapped in parentheses to avoid the following 'and' binding more diff --git a/Lib/test/test_importlib/test_reader.py b/Lib/test/test_importlib/test_reader.py index b0bf49b8ba7f28..9d20c976b82505 100644 --- a/Lib/test/test_importlib/test_reader.py +++ b/Lib/test/test_importlib/test_reader.py @@ -79,7 +79,13 @@ def test_join_path(self): def test_repr(self): self.assertEqual( repr(MultiplexedPath(self.folder)), - "MultiplexedPath('{}')".format(self.folder), + f"MultiplexedPath('{self.folder}')", + ) + + def test_name(self): + self.assertEqual( + MultiplexedPath(self.folder).name, + os.path.basename(self.folder), ) @@ -115,7 +121,7 @@ def test_files(self): reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01')) self.assertIsInstance(reader.files(), MultiplexedPath) - self.assertEqual(repr(reader.files()), "MultiplexedPath('{}')".format(root)) + self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')") if __name__ == '__main__': diff --git a/Lib/test/test_importlib/test_resource.py b/Lib/test/test_importlib/test_resource.py index f8d861e9d4c205..003f7e95ad9122 100644 --- a/Lib/test/test_importlib/test_resource.py +++ b/Lib/test/test_importlib/test_resource.py @@ -152,7 +152,7 @@ def setUp(self): data_path = pathlib.Path(self.ZIP_MODULE.__file__) data_dir = data_path.parent self.source_zip_path = data_dir / 'ziptestdata.zip' - self.zip_path = pathlib.Path('{}.zip'.format(uuid.uuid4())).absolute() + self.zip_path = pathlib.Path(f'{uuid.uuid4()}.zip').absolute() self.zip_path.write_bytes(self.source_zip_path.read_bytes()) sys.path.append(str(self.zip_path)) self.data = import_module('ziptestdata') diff --git a/Lib/test/test_importlib/test_threaded_import.py b/Lib/test/test_importlib/test_threaded_import.py index 03bde96de6c297..76b028eac97bf9 100644 --- a/Lib/test/test_importlib/test_threaded_import.py +++ b/Lib/test/test_importlib/test_threaded_import.py @@ -14,7 +14,7 @@ import threading import unittest from unittest import mock -from test.support import (verbose, run_unittest) +from test.support import verbose from test.support.import_helper import forget from test.support.os_helper import (TESTFN, unlink, rmtree) from test.support import script_helper, threading_helper @@ -258,19 +258,16 @@ def test_multiprocessing_pool_circular_import(self): script_helper.assert_python_ok(fn) -@threading_helper.reap_threads -def test_main(): - old_switchinterval = None +def setUpModule(): + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) try: old_switchinterval = sys.getswitchinterval() + unittest.addModuleCleanup(sys.setswitchinterval, old_switchinterval) sys.setswitchinterval(1e-5) except AttributeError: pass - try: - run_unittest(ThreadedImportTests) - finally: - if old_switchinterval is not None: - sys.setswitchinterval(old_switchinterval) + if __name__ == "__main__": - test_main() + unittets.main() diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 104452267c0673..f9ff26fc7e3a00 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -859,7 +859,7 @@ def test_magic_number(self): # stakeholders such as OS package maintainers must be notified # in advance. Such exceptional releases will then require an # adjustment to this test case. - EXPECTED_MAGIC_NUMBER = 3413 + EXPECTED_MAGIC_NUMBER = 3439 actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little') msg = ( diff --git a/Lib/test/test_importlib/test_zip.py b/Lib/test/test_importlib/test_zip.py index 83e041385e0e8c..bf16a3b95e18c5 100644 --- a/Lib/test/test_importlib/test_zip.py +++ b/Lib/test/test_importlib/test_zip.py @@ -76,3 +76,7 @@ def test_files(self): for file in files('example'): path = str(file.dist.locate_file(file)) assert '.egg/' in path, path + + def test_normalized_name(self): + dist = distribution('example') + assert dist._normalized_name == 'example' diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 0ab65307cdd095..93ff2f85df193d 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -24,7 +24,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import run_unittest, cpython_only +from test.support import cpython_only from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support.import_helper import DirsOnSysPath from test.support.os_helper import TESTFN @@ -493,6 +493,15 @@ def test_getmodule(self): # Check filename override self.assertEqual(inspect.getmodule(None, modfile), mod) + def test_getmodule_file_not_found(self): + # See bpo-45406 + def _getabsfile(obj, _filename): + raise FileNotFoundError('bad file') + with unittest.mock.patch('inspect.getabsfile', _getabsfile): + f = inspect.currentframe() + self.assertIsNone(inspect.getmodule(f)) + inspect.getouterframes(f) # smoke test + def test_getframeinfo_get_first_line(self): frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) self.assertEqual(frame_info.code_context[0], "# line 1\n") @@ -585,6 +594,17 @@ def monkey(filename, module_globals=None): def test_getsource_on_code_object(self): self.assertSourceEqual(mod.eggs.__code__, 12, 18) +class TestGetsourceInteractive(unittest.TestCase): + def test_getclasses_interactive(self): + # bpo-44648: simulate a REPL session; + # there is no `__file__` in the __main__ module + code = "import sys, inspect; \ + assert not hasattr(sys.modules['__main__'], '__file__'); \ + A = type('A', (), {}); \ + inspect.getsource(A)" + _, _, stderr = assert_python_failure("-c", code, __isolated=True) + self.assertIn(b'OSError: source code not available', stderr) + class TestGettingSourceOfToplevelFrames(GetSourceBase): fodderModule = mod @@ -3063,6 +3083,47 @@ def __init__(self, b): ('bar', 2, ..., "keyword_only")), ...)) + def test_signature_on_subclass(self): + class A: + def __new__(cls, a=1, *args, **kwargs): + return object.__new__(cls) + class B(A): + def __init__(self, b): + pass + class C(A): + def __new__(cls, a=1, b=2, *args, **kwargs): + return object.__new__(cls) + class D(A): + pass + + self.assertEqual(self.signature(B), + ((('b', ..., ..., "positional_or_keyword"),), + ...)) + self.assertEqual(self.signature(C), + ((('a', 1, ..., 'positional_or_keyword'), + ('b', 2, ..., 'positional_or_keyword'), + ('args', ..., ..., 'var_positional'), + ('kwargs', ..., ..., 'var_keyword')), + ...)) + self.assertEqual(self.signature(D), + ((('a', 1, ..., 'positional_or_keyword'), + ('args', ..., ..., 'var_positional'), + ('kwargs', ..., ..., 'var_keyword')), + ...)) + + def test_signature_on_generic_subclass(self): + from typing import Generic, TypeVar + + T = TypeVar('T') + + class A(Generic[T]): + def __init__(self, *, a: int) -> None: + pass + + self.assertEqual(self.signature(A), + ((('a', ..., int, 'keyword_only'),), + None)) + @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_signature_on_class_without_init(self): @@ -3264,6 +3325,17 @@ def foo(): pass self.assertEqual(str(inspect.signature(foo)), '()') + def foo(a: list[str]) -> tuple[str, float]: + pass + self.assertEqual(str(inspect.signature(foo)), + '(a: list[str]) -> tuple[str, float]') + + from typing import Tuple + def foo(a: list[str]) -> Tuple[str, float]: + pass + self.assertEqual(str(inspect.signature(foo)), + '(a: list[str]) -> Tuple[str, float]') + def test_signature_str_positional_only(self): P = inspect.Parameter S = inspect.Signature @@ -4298,18 +4370,5 @@ def test_getsource_reload(self): self.assertInspectEqual(path, module) -def test_main(): - run_unittest( - TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments, - TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates, - TestGetcallargsFunctions, TestGetcallargsMethods, - TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState, - TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, - TestBoundArguments, TestSignaturePrivateHelpers, - TestSignatureDefinitions, TestIsDataDescriptor, - TestGetClosureVars, TestUnwrap, TestMain, TestReload, - TestGetCoroutineState, TestGettingSourceOfToplevelFrames - ) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 32c29ea5dc4a76..35013b6a090cbb 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -73,6 +73,10 @@ class EmptyStruct(ctypes.Structure): '--with-memory-sanitizer' in _config_args ) +ADDRESS_SANITIZER = ( + '-fsanitize=address' in _cflags +) + # Does io.IOBase finalizer log the exception if the close() method fails? # The exception is ignored silently by default in release build. IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode) @@ -1546,7 +1550,7 @@ def test_truncate_on_read_only(self): class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader - @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedReaderTest.test_constructor(self) @@ -1911,7 +1915,7 @@ def test_slow_close_from_thread(self): class CBufferedWriterTest(BufferedWriterTest, SizeofTest): tp = io.BufferedWriter - @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedWriterTest.test_constructor(self) @@ -2410,7 +2414,7 @@ def test_interleaved_readline_write(self): class CBufferedRandomTest(BufferedRandomTest, SizeofTest): tp = io.BufferedRandom - @unittest.skipIf(MEMORY_SANITIZER, "MSan defaults to crashing " + @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing " "instead of returning NULL for malloc failure.") def test_constructor(self): BufferedRandomTest.test_constructor(self) @@ -4372,6 +4376,31 @@ def check_interrupted_write(self, item, bytes, **fdopen_kwargs): """Check that a partial write, when it gets interrupted, properly invokes the signal handler, and bubbles up the exception raised in the latter.""" + + # XXX This test has three flaws that appear when objects are + # XXX not reference counted. + + # - if wio.write() happens to trigger a garbage collection, + # the signal exception may be raised when some __del__ + # method is running; it will not reach the assertRaises() + # call. + + # - more subtle, if the wio object is not destroyed at once + # and survives this function, the next opened file is likely + # to have the same fileno (since the file descriptor was + # actively closed). When wio.__del__ is finally called, it + # will close the other's test file... To trigger this with + # CPython, try adding "global wio" in this function. + + # - This happens only for streams created by the _pyio module, + # because a wio.close() that fails still consider that the + # file needs to be closed again. You can try adding an + # "assert wio.closed" at the end of the function. + + # Fortunately, a little gc.collect() seems to be enough to + # work around all these issues. + support.gc_collect() # For PyPy or other GCs. + read_results = [] def _read(): s = os.read(r, 1) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index cdd9880c3c17fa..ff77bdb1bbc582 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -97,7 +97,7 @@ class CommonTestMixin_v4(CommonTestMixin): def test_leading_zeros(self): # bpo-36384: no leading zeros to avoid ambiguity with octal notation - msg = "Leading zeros are not permitted in '\d+'" + msg = "Leading zeros are not permitted in '\\d+'" addresses = [ "000.000.000.000", "192.168.000.001", @@ -2339,6 +2339,12 @@ def testIpv4Mapped(self): self.assertEqual(ipaddress.ip_address('::ffff:c0a8:101').ipv4_mapped, ipaddress.ip_address('192.168.1.1')) + def testIpv4MappedPrivateCheck(self): + self.assertEqual( + True, ipaddress.ip_address('::ffff:192.168.1.1').is_private) + self.assertEqual( + False, ipaddress.ip_address('::ffff:172.32.0.0').is_private) + def testAddrExclude(self): addr1 = ipaddress.ip_network('10.1.1.0/24') addr2 = ipaddress.ip_network('10.1.1.0/26') diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py index 109c3f84a5c426..9d37cff9903385 100644 --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -5,6 +5,7 @@ import unittest import sys import typing +from test import support @@ -266,12 +267,14 @@ def test_subclass_tuple(self): def test_subclass_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, issubclass, str, str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, issubclass, str, str) def test_isinstance_recursion_limit(self): # make sure that issubclass raises RecursionError before the C stack is # blown - self.assertRaises(RecursionError, blowstack, isinstance, '', str) + with support.infinite_recursion(): + self.assertRaises(RecursionError, blowstack, isinstance, '', str) def test_subclass_with_union(self): self.assertTrue(issubclass(int, int | float | int)) @@ -308,10 +311,42 @@ class X: @property def __bases__(self): return self.__bases__ + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) + self.assertRaises(RecursionError, issubclass, int, X()) + self.assertRaises(RecursionError, isinstance, 1, X()) + + def test_infinite_recursion_via_bases_tuple(self): + """Regression test for bpo-30570.""" + class Failure(object): + def __getattr__(self, attr): + return (self, None) + with support.infinite_recursion(): + with self.assertRaises(RecursionError): + issubclass(Failure(), int) + + def test_infinite_cycle_in_bases(self): + """Regression test for bpo-30570.""" + class X: + @property + def __bases__(self): + return (self, self, self) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) - self.assertRaises(RecursionError, issubclass, X(), int) - self.assertRaises(RecursionError, issubclass, int, X()) - self.assertRaises(RecursionError, isinstance, 1, X()) + def test_infinitely_many_bases(self): + """Regression test for bpo-30570.""" + class X: + def __getattr__(self, attr): + self.assertEqual(attr, "__bases__") + class A: + pass + class B: + pass + A.__getattr__ = B.__getattr__ = X.__getattr__ + return (A(), B()) + with support.infinite_recursion(): + self.assertRaises(RecursionError, issubclass, X(), int) def blowstack(fxn, arg, compare_to): diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py index 20cb9c06809146..554f602f6252c0 100644 --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -2,7 +2,7 @@ import sys import unittest -from test.support import run_unittest, cpython_only +from test.support import cpython_only from test.support.os_helper import TESTFN, unlink from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ import pickle @@ -1037,9 +1037,5 @@ def test_error_iter(self): self.assertRaises(ZeroDivisionError, iter, BadIterableClass()) -def test_main(): - run_unittest(TestCase) - - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index a99b5e2bb71db9..a12f6f0b9773e4 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -1442,6 +1442,7 @@ def test_tee(self): p = weakref.proxy(a) self.assertEqual(getattr(p, '__class__'), type(b)) del a + support.gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, getattr, p, '__class__') ans = list('abc') @@ -2393,6 +2394,23 @@ def test_permutations_sizeof(self): ... else: ... return starmap(func, repeat(args, times)) +>>> def triplewise(iterable): +... "Return overlapping triplets from an iterable" +... # pairwise('ABCDEFG') -> ABC BCD CDE DEF EFG +... for (a, _), (b, c) in pairwise(pairwise(iterable)): +... yield a, b, c + +>>> import collections +>>> def sliding_window(iterable, n): +... # sliding_window('ABCDEFG', 4) -> ABCD BCDE CDEF DEFG +... it = iter(iterable) +... window = collections.deque(islice(it, n), maxlen=n) +... if len(window) == n: +... yield tuple(window) +... for x in it: +... window.append(x) +... yield tuple(window) + >>> def grouper(n, iterable, fillvalue=None): ... "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" ... args = [iter(iterable)] * n @@ -2411,6 +2429,40 @@ def test_permutations_sizeof(self): ... pending -= 1 ... nexts = cycle(islice(nexts, pending)) +>>> def partition(pred, iterable): +... "Use a predicate to partition entries into false entries and true entries" +... # partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 +... t1, t2 = tee(iterable) +... return filterfalse(pred, t1), filter(pred, t2) + +>>> def before_and_after(predicate, it): +... ''' Variant of takewhile() that allows complete +... access to the remainder of the iterator. +... +... >>> all_upper, remainder = before_and_after(str.isupper, 'ABCdEfGhI') +... >>> str.join('', all_upper) +... 'ABC' +... >>> str.join('', remainder) +... 'dEfGhI' +... +... Note that the first iterator must be fully +... consumed before the second iterator can +... generate valid results. +... ''' +... it = iter(it) +... transition = [] +... def true_iterator(): +... for elem in it: +... if predicate(elem): +... yield elem +... else: +... transition.append(elem) +... return +... def remainder_iterator(): +... yield from transition +... yield from it +... return true_iterator(), remainder_iterator() + >>> def powerset(iterable): ... "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" ... s = list(iterable) @@ -2535,9 +2587,31 @@ def test_permutations_sizeof(self): >>> list(grouper(3, 'abcdefg', 'x')) [('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'x', 'x')] +>>> list(triplewise('ABCDEFG')) +[('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')] + +>>> list(sliding_window('ABCDEFG', 4)) +[('A', 'B', 'C', 'D'), ('B', 'C', 'D', 'E'), ('C', 'D', 'E', 'F'), ('D', 'E', 'F', 'G')] + >>> list(roundrobin('abc', 'd', 'ef')) ['a', 'd', 'e', 'b', 'f', 'c'] +>>> def is_odd(x): +... return x % 2 == 1 + +>>> evens, odds = partition(is_odd, range(10)) +>>> list(evens) +[0, 2, 4, 6, 8] +>>> list(odds) +[1, 3, 5, 7, 9] + +>>> it = iter('ABCdEfGhI') +>>> all_upper, remainder = before_and_after(str.isupper, it) +>>> ''.join(all_upper) +'ABC' +>>> ''.join(remainder) +'dEfGhI' + >>> list(powerset([1,2,3])) [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] diff --git a/Lib/test/test_json/test_speedups.py b/Lib/test/test_json/test_speedups.py index fbfee1a582095b..682014cfd5b344 100644 --- a/Lib/test/test_json/test_speedups.py +++ b/Lib/test/test_json/test_speedups.py @@ -59,6 +59,15 @@ def bad_encoder2(*args): with self.assertRaises(ZeroDivisionError): enc('spam', 4) + def test_bad_markers_argument_to_encoder(self): + # https://bugs.python.org/issue45269 + with self.assertRaisesRegex( + TypeError, + r'make_encoder\(\) argument 1 must be dict or None, not int', + ): + self.json.encoder.c_make_encoder(1, None, None, None, ': ', ', ', + False, False, False) + def test_bad_bool_args(self): def test(name): self.json.encoder.JSONEncoder(**{name: BadBool()}).encode({'a': 1}) diff --git a/Lib/test/test_json/test_tool.py b/Lib/test/test_json/test_tool.py index 0386690cad95be..1d7fca6efb1cc7 100644 --- a/Lib/test/test_json/test_tool.py +++ b/Lib/test/test_json/test_tool.py @@ -131,6 +131,15 @@ def test_infile_outfile(self): self.assertEqual(out, b'') self.assertEqual(err, b'') + def test_writing_in_place(self): + infile = self._create_infile() + rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile) + with open(infile, "r", encoding="utf-8") as fp: + self.assertEqual(fp.read(), self.expect) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def test_jsonlines(self): args = sys.executable, '-m', 'json.tool', '--json-lines' process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True) diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py index 59e00da242ad63..c6e2dadbb25e1f 100644 --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -239,5 +239,47 @@ def raise_memoryerror(*args, **kwargs): self.assertEqual(linecache.getlines(FILENAME), lines) +class LineCacheInvalidationTests(unittest.TestCase): + def setUp(self): + super().setUp() + linecache.clearcache() + self.deleted_file = os_helper.TESTFN + '.1' + self.modified_file = os_helper.TESTFN + '.2' + self.unchanged_file = os_helper.TESTFN + '.3' + + for fname in (self.deleted_file, + self.modified_file, + self.unchanged_file): + self.addCleanup(os_helper.unlink, fname) + with open(fname, 'w', encoding='utf-8') as source: + source.write(f'print("I am {fname}")') + + self.assertNotIn(fname, linecache.cache) + linecache.getlines(fname) + self.assertIn(fname, linecache.cache) + + os.remove(self.deleted_file) + with open(self.modified_file, 'w', encoding='utf-8') as source: + source.write('print("was modified")') + + def test_checkcache_for_deleted_file(self): + linecache.checkcache(self.deleted_file) + self.assertNotIn(self.deleted_file, linecache.cache) + self.assertIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + def test_checkcache_for_modified_file(self): + linecache.checkcache(self.modified_file) + self.assertIn(self.deleted_file, linecache.cache) + self.assertNotIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + def test_checkcache_with_no_parameter(self): + linecache.checkcache() + self.assertNotIn(self.deleted_file, linecache.cache) + self.assertNotIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_lltrace.py b/Lib/test/test_lltrace.py index 8f1a92e5c725c3..06e33f4c4c2f38 100644 --- a/Lib/test/test_lltrace.py +++ b/Lib/test/test_lltrace.py @@ -12,7 +12,7 @@ def test_lltrace_does_not_crash_on_subscript_operator(self): # If this test fails, it will reproduce a crash reported as # bpo-34113. The crash happened at the command line console of # debug Python builds with __ltrace__ enabled (only possible in console), - # when the interal Python stack was negatively adjusted + # when the internal Python stack was negatively adjusted with open(os_helper.TESTFN, 'w', encoding='utf-8') as fd: self.addCleanup(os_helper.unlink, os_helper.TESTFN) fd.write(textwrap.dedent("""\ diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 2c788f2dfa65e6..f844e62ca2e72b 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -496,7 +496,7 @@ def test_japanese(self): class TestMiscellaneous(unittest.TestCase): def test_defaults_UTF8(self): # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is - # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing + # valid. Furthermore LC_CTYPE=UTF is used by the UTF-8 locale coercing # during interpreter startup (on macOS). import _locale import os diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index ee00a32026f65e..03d0319306a480 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,4 +1,4 @@ -# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved. +# Copyright 2001-2021 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, @@ -16,7 +16,7 @@ """Test harness for the logging module. Run all tests. -Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved. +Copyright (C) 2001-2021 Vinay Sajip. All Rights Reserved. """ import logging @@ -36,6 +36,7 @@ import queue import random import re +import shutil import socket import struct import sys @@ -54,13 +55,16 @@ import warnings import weakref -import asyncore from http.server import HTTPServer, BaseHTTPRequestHandler -import smtpd from urllib.parse import urlparse, parse_qs from socketserver import (ThreadingUDPServer, DatagramRequestHandler, ThreadingTCPServer, StreamRequestHandler) +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import smtpd + try: import win32evtlog, win32evtlogutil, pywintypes except ImportError: @@ -888,7 +892,7 @@ class ControlMixin(object): single parameter - the request - in order to process the request. This handler is called on the server thread, effectively meaning that requests are - processed serially. While not quite Web scale ;-), + processed serially. While not quite web scale ;-), this should be fine for testing applications. :param poll_interval: The polling interval in seconds. """ @@ -4418,8 +4422,10 @@ def _extract_logrecord_process_name(key, logMultiprocessing, conn=None): name = mp.current_process().name r1 = logging.makeLogRecord({'msg': f'msg1_{key}'}) - del sys.modules['multiprocessing'] - r2 = logging.makeLogRecord({'msg': f'msg2_{key}'}) + + # https://bugs.python.org/issue45128 + with support.swap_item(sys.modules, 'multiprocessing', None): + r2 = logging.makeLogRecord({'msg': f'msg2_{key}'}) results = {'processName' : name, 'r1.processName': r1.processName, @@ -4468,7 +4474,6 @@ def test_multiprocessing(self): if multiprocessing_imported: import multiprocessing - def test_optional(self): r = logging.makeLogRecord({}) NOT_NONE = self.assertIsNotNone @@ -5163,6 +5168,9 @@ def assertLogFile(self, filename): msg="Log file %r does not exist" % filename) self.rmfiles.append(filename) + def next_rec(self): + return logging.LogRecord('n', logging.DEBUG, 'p', 1, + self.next_message(), None, None, None) class FileHandlerTest(BaseFileTest): def test_delay(self): @@ -5175,17 +5183,31 @@ def test_delay(self): self.assertTrue(os.path.exists(self.fn)) fh.close() -class RotatingFileHandlerTest(BaseFileTest): - def next_rec(self): - return logging.LogRecord('n', logging.DEBUG, 'p', 1, - self.next_message(), None, None, None) + def test_emit_after_closing_in_write_mode(self): + # Issue #42378 + os.unlink(self.fn) + fh = logging.FileHandler(self.fn, encoding='utf-8', mode='w') + fh.setFormatter(logging.Formatter('%(message)s')) + fh.emit(self.next_rec()) # '1' + fh.close() + fh.emit(self.next_rec()) # '2' + with open(self.fn) as fp: + self.assertEqual(fp.read().strip(), '1') +class RotatingFileHandlerTest(BaseFileTest): def test_should_not_rollover(self): # If maxbytes is zero rollover never occurs rh = logging.handlers.RotatingFileHandler( self.fn, encoding="utf-8", maxBytes=0) self.assertFalse(rh.shouldRollover(None)) rh.close() + # bpo-45401 - test with special file + # We set maxBytes to 1 so that rollover would normally happen, except + # for the check for regular files + rh = logging.handlers.RotatingFileHandler( + os.devnull, encoding="utf-8", maxBytes=1) + self.assertFalse(rh.shouldRollover(self.next_rec())) + rh.close() def test_should_rollover(self): rh = logging.handlers.RotatingFileHandler(self.fn, encoding="utf-8", maxBytes=1) @@ -5280,6 +5302,15 @@ def rotator(source, dest): rh.close() class TimedRotatingFileHandlerTest(BaseFileTest): + def test_should_not_rollover(self): + # See bpo-45401. Should only ever rollover regular files + fh = logging.handlers.TimedRotatingFileHandler( + os.devnull, 'S', encoding="utf-8", backupCount=1) + time.sleep(1.1) # a little over a second ... + r = logging.makeLogRecord({'msg': 'testing - device file'}) + self.assertFalse(fh.shouldRollover(r)) + fh.close() + # other test methods added below def test_rollover(self): fh = logging.handlers.TimedRotatingFileHandler( @@ -5388,6 +5419,54 @@ def test_compute_rollover_weekly_attime(self): finally: rh.close() + def test_compute_files_to_delete(self): + # See bpo-46063 for background + wd = tempfile.mkdtemp(prefix='test_logging_') + self.addCleanup(shutil.rmtree, wd) + times = [] + dt = datetime.datetime.now() + for i in range(10): + times.append(dt.strftime('%Y-%m-%d_%H-%M-%S')) + dt += datetime.timedelta(seconds=5) + prefixes = ('a.b', 'a.b.c', 'd.e', 'd.e.f') + files = [] + rotators = [] + for prefix in prefixes: + p = os.path.join(wd, '%s.log' % prefix) + rotator = logging.handlers.TimedRotatingFileHandler(p, when='s', + interval=5, + backupCount=7, + delay=True) + rotators.append(rotator) + if prefix.startswith('a.b'): + for t in times: + files.append('%s.log.%s' % (prefix, t)) + else: + rotator.namer = lambda name: name.replace('.log', '') + '.log' + for t in times: + files.append('%s.%s.log' % (prefix, t)) + # Create empty files + for fn in files: + p = os.path.join(wd, fn) + with open(p, 'wb') as f: + pass + # Now the checks that only the correct files are offered up for deletion + for i, prefix in enumerate(prefixes): + rotator = rotators[i] + candidates = rotator.getFilesToDelete() + self.assertEqual(len(candidates), 3) + if prefix.startswith('a.b'): + p = '%s.log.' % prefix + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.startswith(p)) + else: + for c in candidates: + d, fn = os.path.split(c) + self.assertTrue(fn.endswith('.log')) + self.assertTrue(fn.startswith(prefix + '.') and + fn[len(prefix) + 2].isdigit()) + def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) @@ -5485,25 +5564,11 @@ def test__all__(self): # Set the locale to the platform-dependent default. I have no idea # why the test does this, but in any case we save the current locale # first and restore it at the end. -@support.run_with_locale('LC_ALL', '') -def test_main(): - tests = [ - BuiltinLevelsTest, BasicFilterTest, CustomLevelsAndFiltersTest, - HandlerTest, MemoryHandlerTest, ConfigFileTest, SocketHandlerTest, - DatagramHandlerTest, MemoryTest, EncodingTest, WarningsTest, - ConfigDictTest, ManagerTest, FormatterTest, BufferingFormatterTest, - StreamHandlerTest, LogRecordFactoryTest, ChildLoggerTest, - QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest, - LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest, - RotatingFileHandlerTest, LastResortTest, LogRecordTest, - ExceptionTest, SysLogHandlerTest, IPv6SysLogHandlerTest, HTTPHandlerTest, - NTEventLogHandlerTest, TimedRotatingFileHandlerTest, - UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest, - MiscTestCase - ] - if hasattr(logging.handlers, 'QueueListener'): - tests.append(QueueListenerTest) - support.run_unittest(*tests) +def setUpModule(): + cm = support.run_with_locale('LC_ALL', '') + cm.__enter__() + unittest.addModuleCleanup(cm.__exit__, None, None, None) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index db20300056e489..145c8cfced4080 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -1,4 +1,5 @@ import _compression +import array from io import BytesIO, UnsupportedOperation, DEFAULT_BUFFER_SIZE import os import pathlib @@ -8,9 +9,7 @@ from test import support import unittest -from test.support import ( - _4G, bigmemtest, run_unittest -) +from test.support import _4G, bigmemtest from test.support.import_helper import import_module from test.support.os_helper import ( TESTFN, unlink @@ -1231,6 +1230,14 @@ def test_issue21872(self): self.assertTrue(d2.eof) self.assertEqual(out1 + out2, entire) + def test_issue44439(self): + q = array.array('Q', [1, 2, 3, 4, 5]) + LENGTH = len(q) * q.itemsize + + with LZMAFile(BytesIO(), 'w') as f: + self.assertEqual(f.write(q), LENGTH) + self.assertEqual(f.tell(), LENGTH) + class OpenTestCase(unittest.TestCase): @@ -1932,14 +1939,5 @@ def test_filter_properties_roundtrip(self): ) -def test_main(): - run_unittest( - CompressorDecompressorTestCase, - CompressDecompressFunctionTestCase, - FileTestCase, - OpenTestCase, - MiscellaneousTestCase, - ) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 8a5d69246228e3..604fc4525f53e9 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -2300,15 +2300,9 @@ def test__all__(self): not_exported={"linesep", "fcntl"}) -def test_main(): - tests = (TestMailboxSuperclass, TestMaildir, TestMbox, TestMMDF, TestMH, - TestBabyl, TestMessage, TestMaildirMessage, TestMboxMessage, - TestMHMessage, TestBabylMessage, TestMMDFMessage, - TestMessageConversion, TestProxyFile, TestPartialFile, - MaildirTestCase, TestFakeMailBox, MiscTestCase) - support.run_unittest(*tests) +def tearDownModule(): support.reap_children() if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 3d128749bec40f..e5f4e2bbadefb7 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1783,16 +1783,22 @@ def test_prod(self): self.assertRaises(TypeError, prod) self.assertRaises(TypeError, prod, 42) self.assertRaises(TypeError, prod, ['a', 'b', 'c']) - self.assertRaises(TypeError, prod, ['a', 'b', 'c'], '') - self.assertRaises(TypeError, prod, [b'a', b'c'], b'') + self.assertRaises(TypeError, prod, ['a', 'b', 'c'], start='') + self.assertRaises(TypeError, prod, [b'a', b'c'], start=b'') values = [bytearray(b'a'), bytearray(b'b')] - self.assertRaises(TypeError, prod, values, bytearray(b'')) + self.assertRaises(TypeError, prod, values, start=bytearray(b'')) self.assertRaises(TypeError, prod, [[1], [2], [3]]) self.assertRaises(TypeError, prod, [{2:3}]) - self.assertRaises(TypeError, prod, [{2:3}]*2, {2:3}) - self.assertRaises(TypeError, prod, [[1], [2], [3]], []) + self.assertRaises(TypeError, prod, [{2:3}]*2, start={2:3}) + self.assertRaises(TypeError, prod, [[1], [2], [3]], start=[]) + + # Some odd cases + self.assertEqual(prod([2, 3], start='ab'), 'abababababab') + self.assertEqual(prod([2, 3], start=[1, 2]), [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]) + self.assertEqual(prod([], start={2: 3}), {2:3}) + with self.assertRaises(TypeError): - prod([10, 20], [30, 40]) # start is a keyword-only argument + prod([10, 20], 1) # start is a keyword-only argument self.assertEqual(prod([0, 1, 2, 3]), 0) self.assertEqual(prod([1, 0, 2, 3]), 0) diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index f5c040a97addf2..4098a22644092f 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -9,6 +9,11 @@ from test.support import os_helper from platform import win32_edition +try: + import _winapi +except ImportError: + _winapi = None + def setUpModule(): global knownfiles @@ -108,20 +113,29 @@ def test_filename_with_url_delimiters(self): eq(self.db.guess_type(r" \"\`;b&b&c |.tar.gz"), gzip_expected) def test_guess_all_types(self): - eq = self.assertEqual - unless = self.assertTrue # First try strict. Use a set here for testing the results because if # test_urllib2 is run before test_mimetypes, global state is modified # such that the 'all' set will have more items in it. - all = set(self.db.guess_all_extensions('text/plain', strict=True)) - unless(all >= set(['.bat', '.c', '.h', '.ksh', '.pl', '.txt'])) + all = self.db.guess_all_extensions('text/plain', strict=True) + self.assertTrue(set(all) >= {'.bat', '.c', '.h', '.ksh', '.pl', '.txt'}) + self.assertEqual(len(set(all)), len(all)) # no duplicates # And now non-strict all = self.db.guess_all_extensions('image/jpg', strict=False) - all.sort() - eq(all, ['.jpg']) + self.assertEqual(all, ['.jpg']) # And now for no hits all = self.db.guess_all_extensions('image/jpg', strict=True) - eq(all, []) + self.assertEqual(all, []) + # And now for type existing in both strict and non-strict mappings. + self.db.add_type('test-type', '.strict-ext') + self.db.add_type('test-type', '.non-strict-ext', strict=False) + all = self.db.guess_all_extensions('test-type', strict=False) + self.assertEqual(all, ['.strict-ext', '.non-strict-ext']) + all = self.db.guess_all_extensions('test-type') + self.assertEqual(all, ['.strict-ext']) + # Test that changing the result list does not affect the global state + all.append('.no-such-ext') + all = self.db.guess_all_extensions('test-type') + self.assertNotIn('.no-such-ext', all) def test_encoding(self): getpreferredencoding = locale.getpreferredencoding @@ -235,6 +249,21 @@ def test_registry_parsing(self): eq(self.db.guess_type("image.jpg"), ("image/jpeg", None)) eq(self.db.guess_type("image.png"), ("image/png", None)) + @unittest.skipIf(not hasattr(_winapi, "_mimetypes_read_windows_registry"), + "read_windows_registry accelerator unavailable") + def test_registry_accelerator(self): + from_accel = {} + from_reg = {} + _winapi._mimetypes_read_windows_registry( + lambda v, k: from_accel.setdefault(k, set()).add(v) + ) + mimetypes.MimeTypes._read_windows_registry( + lambda v, k: from_reg.setdefault(k, set()).add(v) + ) + self.assertEqual(list(from_reg), list(from_accel)) + for k in from_reg: + self.assertEqual(from_reg[k], from_accel[k]) + class MiscTestCase(unittest.TestCase): def test__all__(self): @@ -288,6 +317,5 @@ def test_guess_type(self): type_info = self.mimetypes_cmd("foo.pic") eq(type_info, "I don't know anything about type foo.pic") - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py index 3efa1505e5c92c..cf8bb5e3a0520d 100644 --- a/Lib/test/test_multibytecodec.py +++ b/Lib/test/test_multibytecodec.py @@ -403,8 +403,6 @@ class TestHZStateful(TestStateful): reset = b'~}' expected_reset = expected + reset -def test_main(): - support.run_unittest(__name__) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py index 1ecae85f62f2c9..b9b8f155826708 100644 --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -153,6 +153,11 @@ def test_countOf(self): self.assertRaises(ZeroDivisionError, operator.countOf, BadIterable(), 1) self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 3), 1) self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 5), 0) + # is but not == + nan = float("nan") + self.assertEqual(operator.countOf([nan, nan, 21], nan), 2) + # == but not is + self.assertEqual(operator.countOf([{}, 1, {}, 2], {}), 2) def test_delitem(self): operator = self.module @@ -188,6 +193,9 @@ def test_indexOf(self): self.assertRaises(ZeroDivisionError, operator.indexOf, BadIterable(), 1) self.assertEqual(operator.indexOf([4, 3, 2, 1], 3), 1) self.assertRaises(ValueError, operator.indexOf, [4, 3, 2, 1], 0) + nan = float("nan") + self.assertEqual(operator.indexOf([nan, nan, 21], nan), 0) + self.assertEqual(operator.indexOf([{}, 1, {}, 2], {}), 0) def test_invert(self): operator = self.module diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index 1ed6bf9f919a2c..28b274462388ed 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -1656,8 +1656,5 @@ def test__all__(self): support.check__all__(self, optparse, not_exported=not_exported) -def test_main(): - support.run_unittest(__name__) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 8b3d1feb78fe36..0ad13d59ded372 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2,8 +2,6 @@ # does add tests for a few functions which have been determined to be more # portable than they had been thought to be. -import asynchat -import asyncore import codecs import contextlib import decimal @@ -39,6 +37,11 @@ from test.support import warnings_helper from platform import win32_is_iot +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + try: import resource except ImportError: @@ -4498,6 +4501,22 @@ def test_times(self): self.assertEqual(times.elapsed, 0) +@requires_os_func('fork') +class ForkTests(unittest.TestCase): + def test_fork(self): + # bpo-42540: ensure os.fork() with non-default memory allocator does + # not crash on exit. + code = """if 1: + import os + from test import support + pid = os.fork() + if pid != 0: + support.wait_process(pid, exitcode=0) + """ + assert_python_ok("-c", code) + assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") + + # Only test if the C version is provided, otherwise TestPEP519 already tested # the pure Python implementation. if hasattr(os, "_fspath"): diff --git a/Lib/test/test_ossaudiodev.py b/Lib/test/test_ossaudiodev.py index d3766e580b9843..ebce3e9c272f9c 100644 --- a/Lib/test/test_ossaudiodev.py +++ b/Lib/test/test_ossaudiodev.py @@ -188,7 +188,7 @@ def test_on_closed(self): mixer.close() self.assertRaises(ValueError, mixer.fileno) -def test_main(): +def setUpModule(): try: dsp = ossaudiodev.open('w') except (ossaudiodev.error, OSError) as msg: @@ -197,7 +197,6 @@ def test_main(): raise unittest.SkipTest(msg) raise dsp.close() - support.run_unittest(__name__) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 6ed08f7e70ce3d..555c7ee795bd12 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -324,7 +324,7 @@ def test_match_common(self): self.assertFalse(P('b/py').match('b.py')) self.assertFalse(P('/a.py').match('b.py')) self.assertFalse(P('b.py/c').match('b.py')) - # Wilcard relative pattern. + # Wildcard relative pattern. self.assertTrue(P('b.py').match('*.py')) self.assertTrue(P('a/b.py').match('*.py')) self.assertTrue(P('/a/b.py').match('*.py')) @@ -1282,19 +1282,35 @@ def test_is_reserved(self): self.assertIs(False, P('').is_reserved()) self.assertIs(False, P('/').is_reserved()) self.assertIs(False, P('/foo/bar').is_reserved()) + # UNC paths are never reserved. + self.assertIs(False, P('//my/share/nul/con/aux').is_reserved()) + # Case-insensitive DOS-device names are reserved. + self.assertIs(True, P('nul').is_reserved()) + self.assertIs(True, P('aux').is_reserved()) + self.assertIs(True, P('prn').is_reserved()) self.assertIs(True, P('con').is_reserved()) - self.assertIs(True, P('NUL').is_reserved()) + self.assertIs(True, P('conin$').is_reserved()) + self.assertIs(True, P('conout$').is_reserved()) + # COM/LPT + 1-9 or + superscript 1-3 are reserved. + self.assertIs(True, P('COM1').is_reserved()) + self.assertIs(True, P('LPT9').is_reserved()) + self.assertIs(True, P('com\xb9').is_reserved()) + self.assertIs(True, P('com\xb2').is_reserved()) + self.assertIs(True, P('lpt\xb3').is_reserved()) + # DOS-device name mataching ignores characters after a dot or + # a colon and also ignores trailing spaces. self.assertIs(True, P('NUL.txt').is_reserved()) - self.assertIs(True, P('com1').is_reserved()) - self.assertIs(True, P('com9.bar').is_reserved()) + self.assertIs(True, P('PRN ').is_reserved()) + self.assertIs(True, P('AUX .txt').is_reserved()) + self.assertIs(True, P('COM1:bar').is_reserved()) + self.assertIs(True, P('LPT9 :bar').is_reserved()) + # DOS-device names are only matched at the beginning + # of a path component. self.assertIs(False, P('bar.com9').is_reserved()) - self.assertIs(True, P('lpt1').is_reserved()) - self.assertIs(True, P('lpt9.bar').is_reserved()) self.assertIs(False, P('bar.lpt9').is_reserved()) - # Only the last component matters. + # Only the last path component matters. + self.assertIs(True, P('c:/baz/con/NUL').is_reserved()) self.assertIs(False, P('c:/NUL/con/baz').is_reserved()) - # UNC paths are never reserved. - self.assertIs(False, P('//my/share/nul/con/aux').is_reserved()) class PurePathTest(_BasePurePathTest, unittest.TestCase): cls = pathlib.PurePath @@ -1799,6 +1815,16 @@ def test_resolve_dot(self): # Non-strict self.assertEqual(r.resolve(strict=False), p / '3' / '4') + def test_resolve_nonexist_relative_issue38671(self): + p = self.cls('non', 'exist') + + old_cwd = os.getcwd() + os.chdir(BASE) + try: + self.assertEqual(p.resolve(), self.cls(BASE, p)) + finally: + os.chdir(old_cwd) + def test_with(self): p = self.cls(BASE) it = p.iterdir() @@ -1934,7 +1960,8 @@ def test_link_to(self): self.assertTrue(p.stat) # Linking to a str of a relative path. r = rel_join('fileAAA') - q.link_to(r) + with self.assertWarns(DeprecationWarning): + q.link_to(r) self.assertEqual(os.stat(r).st_size, size) self.assertTrue(q.stat) @@ -2531,13 +2558,21 @@ def test_expanduser(self): othername = username otherhome = userhome + fakename = 'fakeuser' + # This user can theoretically exist on a test runner. Create unique name: + try: + while pwd.getpwnam(fakename): + fakename += '1' + except KeyError: + pass # Non-existent name found + p1 = P('~/Documents') - p2 = P('~' + username + '/Documents') - p3 = P('~' + othername + '/Documents') - p4 = P('../~' + username + '/Documents') - p5 = P('/~' + username + '/Documents') + p2 = P(f'~{username}/Documents') + p3 = P(f'~{othername}/Documents') + p4 = P(f'../~{username}/Documents') + p5 = P(f'/~{username}/Documents') p6 = P('') - p7 = P('~fakeuser/Documents') + p7 = P(f'~{fakename}/Documents') with os_helper.EnvironmentVarGuard() as env: env.pop('HOME', None) diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index 084d0879f17645..aa18e29e22548f 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -1,23 +1,10 @@ import array import collections -import contextlib import dataclasses import enum import inspect +import sys import unittest -import warnings - - -def no_perf(f): - f.no_perf = None - return f - - -@dataclasses.dataclass -class MyClass: - x: int - y: str - __match_args__ = ("x", "y") @dataclasses.dataclass @@ -26,11 +13,122 @@ class Point: y: int -class TestPatma(unittest.TestCase): +class TestCompiler(unittest.TestCase): - def assert_syntax_error(self, code: str): - with self.assertRaises(SyntaxError): - compile(inspect.cleandoc(code), "", "exec") + def test_refleaks(self): + # Hunting for leaks using -R doesn't catch leaks in the compiler itself, + # just the code under test. This test ensures that if there are leaks in + # the pattern compiler, those runs will fail: + with open(__file__) as file: + compile(file.read(), __file__, "exec") + + +class TestInheritance(unittest.TestCase): + + @staticmethod + def check_sequence_then_mapping(x): + match x: + case [*_]: + return "seq" + case {}: + return "map" + + @staticmethod + def check_mapping_then_sequence(x): + match x: + case {}: + return "map" + case [*_]: + return "seq" + + def test_multiple_inheritance_mapping(self): + class C: + pass + class M1(collections.UserDict, collections.abc.Sequence): + pass + class M2(C, collections.UserDict, collections.abc.Sequence): + pass + class M3(collections.UserDict, C, list): + pass + class M4(dict, collections.abc.Sequence, C): + pass + self.assertEqual(self.check_sequence_then_mapping(M1()), "map") + self.assertEqual(self.check_sequence_then_mapping(M2()), "map") + self.assertEqual(self.check_sequence_then_mapping(M3()), "map") + self.assertEqual(self.check_sequence_then_mapping(M4()), "map") + self.assertEqual(self.check_mapping_then_sequence(M1()), "map") + self.assertEqual(self.check_mapping_then_sequence(M2()), "map") + self.assertEqual(self.check_mapping_then_sequence(M3()), "map") + self.assertEqual(self.check_mapping_then_sequence(M4()), "map") + + def test_multiple_inheritance_sequence(self): + class C: + pass + class S1(collections.UserList, collections.abc.Mapping): + pass + class S2(C, collections.UserList, collections.abc.Mapping): + pass + class S3(list, C, collections.abc.Mapping): + pass + class S4(collections.UserList, dict, C): + pass + self.assertEqual(self.check_sequence_then_mapping(S1()), "seq") + self.assertEqual(self.check_sequence_then_mapping(S2()), "seq") + self.assertEqual(self.check_sequence_then_mapping(S3()), "seq") + self.assertEqual(self.check_sequence_then_mapping(S4()), "seq") + self.assertEqual(self.check_mapping_then_sequence(S1()), "seq") + self.assertEqual(self.check_mapping_then_sequence(S2()), "seq") + self.assertEqual(self.check_mapping_then_sequence(S3()), "seq") + self.assertEqual(self.check_mapping_then_sequence(S4()), "seq") + + def test_late_registration_mapping(self): + class Parent: + pass + class ChildPre(Parent): + pass + class GrandchildPre(ChildPre): + pass + collections.abc.Mapping.register(Parent) + class ChildPost(Parent): + pass + class GrandchildPost(ChildPost): + pass + self.assertEqual(self.check_sequence_then_mapping(Parent()), "map") + self.assertEqual(self.check_sequence_then_mapping(ChildPre()), "map") + self.assertEqual(self.check_sequence_then_mapping(GrandchildPre()), "map") + self.assertEqual(self.check_sequence_then_mapping(ChildPost()), "map") + self.assertEqual(self.check_sequence_then_mapping(GrandchildPost()), "map") + self.assertEqual(self.check_mapping_then_sequence(Parent()), "map") + self.assertEqual(self.check_mapping_then_sequence(ChildPre()), "map") + self.assertEqual(self.check_mapping_then_sequence(GrandchildPre()), "map") + self.assertEqual(self.check_mapping_then_sequence(ChildPost()), "map") + self.assertEqual(self.check_mapping_then_sequence(GrandchildPost()), "map") + + def test_late_registration_sequence(self): + class Parent: + pass + class ChildPre(Parent): + pass + class GrandchildPre(ChildPre): + pass + collections.abc.Sequence.register(Parent) + class ChildPost(Parent): + pass + class GrandchildPost(ChildPost): + pass + self.assertEqual(self.check_sequence_then_mapping(Parent()), "seq") + self.assertEqual(self.check_sequence_then_mapping(ChildPre()), "seq") + self.assertEqual(self.check_sequence_then_mapping(GrandchildPre()), "seq") + self.assertEqual(self.check_sequence_then_mapping(ChildPost()), "seq") + self.assertEqual(self.check_sequence_then_mapping(GrandchildPost()), "seq") + self.assertEqual(self.check_mapping_then_sequence(Parent()), "seq") + self.assertEqual(self.check_mapping_then_sequence(ChildPre()), "seq") + self.assertEqual(self.check_mapping_then_sequence(GrandchildPre()), "seq") + self.assertEqual(self.check_mapping_then_sequence(ChildPost()), "seq") + self.assertEqual(self.check_mapping_then_sequence(GrandchildPost()), "seq") + + +class TestPatma(unittest.TestCase): def test_patma_000(self): match 0: @@ -1701,7 +1799,6 @@ def http_error(status): self.assertIs(http_error("400"), None) self.assertIs(http_error(401 | 403 | 404), None) # 407 - @no_perf def test_patma_176(self): def whereis(point): match point: @@ -1714,13 +1811,12 @@ def whereis(point): case (x, y): return f"X={x}, Y={y}" case _: - raise ValueError("Not a point") + return "Not a point" self.assertEqual(whereis((0, 0)), "Origin") self.assertEqual(whereis((0, -1.0)), "Y=-1.0") self.assertEqual(whereis(("X", 0)), "X=X") self.assertEqual(whereis((None, 1j)), "X=None, Y=1j") - with self.assertRaises(ValueError): - whereis(42) + self.assertEqual(whereis(42), "Not a point") def test_patma_177(self): def whereis(point): @@ -2179,11 +2275,11 @@ def f(w): def test_patma_212(self): def f(w): match w: - case MyClass(int(xx), y="hello"): + case Point(int(xx), y="hello"): out = locals() del out["w"] return out - self.assertEqual(f(MyClass(42, "hello")), {"xx": 42}) + self.assertEqual(f(Point(42, "hello")), {"xx": 42}) def test_patma_213(self): def f(w): @@ -2225,99 +2321,35 @@ def f(): return locals() self.assertEqual(set(f()), {"abc"}) - @no_perf def test_patma_218(self): - self.assert_syntax_error(""" - match ...: - case "a" | a: - pass - """) - - @no_perf - def test_patma_219(self): - self.assert_syntax_error(""" - match ...: - case a | "a": - pass - """) - - def test_patma_220(self): def f(): match ..., ...: case a, b: return locals() self.assertEqual(set(f()), {"a", "b"}) - @no_perf - def test_patma_221(self): - self.assert_syntax_error(""" - match ...: - case a, a: - pass - """) - - def test_patma_222(self): + def test_patma_219(self): def f(): match {"k": ..., "l": ...}: case {"k": a, "l": b}: return locals() self.assertEqual(set(f()), {"a", "b"}) - @no_perf - def test_patma_223(self): - self.assert_syntax_error(""" - match ...: - case {"k": a, "l": a}: - pass - """) - - def test_patma_224(self): + def test_patma_220(self): def f(): - match MyClass(..., ...): - case MyClass(x, y=y): + match Point(..., ...): + case Point(x, y=y): return locals() self.assertEqual(set(f()), {"x", "y"}) - @no_perf - def test_patma_225(self): - self.assert_syntax_error(""" - match ...: - case MyClass(x, x): - pass - """) - - @no_perf - def test_patma_226(self): - self.assert_syntax_error(""" - match ...: - case MyClass(x=x, y=x): - pass - """) - - @no_perf - def test_patma_227(self): - self.assert_syntax_error(""" - match ...: - case MyClass(x, y=x): - pass - """) - - def test_patma_228(self): + def test_patma_221(self): def f(): match ...: case b as a: return locals() self.assertEqual(set(f()), {"a", "b"}) - @no_perf - def test_patma_229(self): - self.assert_syntax_error(""" - match ...: - case a as a: - pass - """) - - def test_patma_230(self): + def test_patma_222(self): def f(x): match x: case _: @@ -2327,7 +2359,7 @@ def f(x): self.assertEqual(f(2), 0) self.assertEqual(f(3), 0) - def test_patma_231(self): + def test_patma_223(self): def f(x): match x: case 0: @@ -2337,7 +2369,7 @@ def f(x): self.assertIs(f(2), None) self.assertIs(f(3), None) - def test_patma_232(self): + def test_patma_224(self): def f(x): match x: case 0: @@ -2349,7 +2381,7 @@ def f(x): self.assertEqual(f(2), 1) self.assertEqual(f(3), 1) - def test_patma_233(self): + def test_patma_225(self): def f(x): match x: case 0: @@ -2361,7 +2393,7 @@ def f(x): self.assertIs(f(2), None) self.assertIs(f(3), None) - def test_patma_234(self): + def test_patma_226(self): def f(x): match x: case 0: @@ -2375,7 +2407,7 @@ def f(x): self.assertEqual(f(2), 2) self.assertEqual(f(3), 2) - def test_patma_235(self): + def test_patma_227(self): def f(x): match x: case 0: @@ -2389,275 +2421,77 @@ def f(x): self.assertEqual(f(2), 2) self.assertIs(f(3), None) - @no_perf - def test_patma_236(self): - self.assert_syntax_error(""" - match ...: - case {**rest, "key": value}: - pass - """) + def test_patma_228(self): + match(): + case(): + x = 0 + self.assertEqual(x, 0) - @no_perf - def test_patma_237(self): - self.assert_syntax_error(""" - match ...: - case {"first": first, **rest, "last": last}: - pass - """) + def test_patma_229(self): + x = 0 + match(x): + case(x): + y = 0 + self.assertEqual(x, 0) + self.assertEqual(y, 0) - @no_perf - def test_patma_238(self): - self.assert_syntax_error(""" - match ...: - case *a, b, *c, d, *e: - pass - """) + def test_patma_230(self): + x = 0 + match x: + case False: + y = 0 + case 0: + y = 1 + self.assertEqual(x, 0) + self.assertEqual(y, 1) - @no_perf - def test_patma_239(self): - self.assert_syntax_error(""" - match ...: - case a, *b, c, *d, e: - pass - """) + def test_patma_231(self): + x = 1 + match x: + case True: + y = 0 + case 1: + y = 1 + self.assertEqual(x, 1) + self.assertEqual(y, 1) - @no_perf - def test_patma_240(self): - self.assert_syntax_error(""" - match ...: - case 0+0: - pass - """) + def test_patma_232(self): + class Eq: + def __eq__(self, other): + return True + x = eq = Eq() + y = None + match x: + case None: + y = 0 + self.assertIs(x, eq) + self.assertEqual(y, None) - @no_perf - def test_patma_241(self): - self.assert_syntax_error(""" - match ...: - case f"": - pass - """) + def test_patma_233(self): + x = False + match x: + case False: + y = 0 + self.assertIs(x, False) + self.assertEqual(y, 0) - @no_perf - def test_patma_242(self): - self.assert_syntax_error(""" - match ...: - case f"{x}": - pass - """) + def test_patma_234(self): + x = True + match x: + case True: + y = 0 + self.assertIs(x, True) + self.assertEqual(y, 0) - @no_perf - def test_patma_243(self): - self.assert_syntax_error(""" - match 42: - case x: - pass - case y: - pass - """) + def test_patma_235(self): + x = None + match x: + case None: + y = 0 + self.assertIs(x, None) + self.assertEqual(y, 0) - @no_perf - def test_patma_244(self): - self.assert_syntax_error(""" - match ...: - case {**_}: - pass - """) - - @no_perf - def test_patma_245(self): - self.assert_syntax_error(""" - match ...: - case 42 as _: - pass - """) - - @no_perf - def test_patma_246(self): - class Class: - __match_args__ = None - x = Class() - y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y): - z = 0 - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_247(self): - class Class: - __match_args__ = "XYZ" - x = Class() - y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y): - z = 0 - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_248(self): - class Class: - __match_args__ = (None,) - x = Class() - y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y): - z = 0 - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_249(self): - class Class: - __match_args__ = () - x = Class() - y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y): - z = 0 - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_250(self): - self.assert_syntax_error(""" - match ...: - case Class(a=_, a=_): - pass - """) - - @no_perf - def test_patma_251(self): - x = {"a": 0, "b": 1} - w = y = z = None - with self.assertRaises(ValueError): - match x: - case {"a": y, "a": z}: - w = 0 - self.assertIs(w, None) - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_252(self): - class Keys: - KEY = "a" - x = {"a": 0, "b": 1} - w = y = z = None - with self.assertRaises(ValueError): - match x: - case {Keys.KEY: y, "a": z}: - w = 0 - self.assertIs(w, None) - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_253(self): - class Class: - __match_args__ = ("a", "a") - a = None - x = Class() - w = y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y, z): - w = 0 - self.assertIs(w, None) - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_254(self): - class Class: - __match_args__ = ("a",) - a = None - x = Class() - w = y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y, a=z): - w = 0 - self.assertIs(w, None) - self.assertIs(y, None) - self.assertIs(z, None) - - def test_patma_255(self): - match(): - case(): - x = 0 - self.assertEqual(x, 0) - - def test_patma_256(self): - x = 0 - match(x): - case(x): - y = 0 - self.assertEqual(x, 0) - self.assertEqual(y, 0) - - def test_patma_257(self): - x = 0 - match x: - case False: - y = 0 - case 0: - y = 1 - self.assertEqual(x, 0) - self.assertEqual(y, 1) - - def test_patma_258(self): - x = 1 - match x: - case True: - y = 0 - case 1: - y = 1 - self.assertEqual(x, 1) - self.assertEqual(y, 1) - - def test_patma_259(self): - class Eq: - def __eq__(self, other): - return True - x = eq = Eq() - y = None - match x: - case None: - y = 0 - self.assertIs(x, eq) - self.assertEqual(y, None) - - def test_patma_260(self): - x = False - match x: - case False: - y = 0 - self.assertIs(x, False) - self.assertEqual(y, 0) - - def test_patma_261(self): - x = True - match x: - case True: - y = 0 - self.assertIs(x, True) - self.assertEqual(y, 0) - - def test_patma_262(self): - x = None - match x: - case None: - y = 0 - self.assertIs(x, None) - self.assertEqual(y, 0) - - def test_patma_263(self): + def test_patma_236(self): x = 0 match x: case (0 as w) as z: @@ -2667,7 +2501,7 @@ def test_patma_263(self): self.assertEqual(y, 0) self.assertEqual(z, 0) - def test_patma_264(self): + def test_patma_237(self): x = 0 match x: case (0 as w) as z: @@ -2677,7 +2511,7 @@ def test_patma_264(self): self.assertEqual(y, 0) self.assertEqual(z, 0) - def test_patma_265(self): + def test_patma_238(self): x = ((0, 1), (2, 3)) match x: case ((a as b, c as d) as e) as w, ((f as g, h) as i) as z: @@ -2696,87 +2530,7 @@ def test_patma_265(self): self.assertEqual(y, 0) self.assertEqual(z, (2, 3)) - @no_perf - def test_patma_266(self): - self.assert_syntax_error(""" - match ...: - case _ | _: - pass - """) - - @no_perf - def test_patma_267(self): - self.assert_syntax_error(""" - match ...: - case (_ as x) | [x]: - pass - """) - - - @no_perf - def test_patma_268(self): - self.assert_syntax_error(""" - match ...: - case _ | _ if condition(): - pass - """) - - - @no_perf - def test_patma_269(self): - self.assert_syntax_error(""" - match ...: - case x | [_ as x] if x: - pass - """) - - @no_perf - def test_patma_270(self): - self.assert_syntax_error(""" - match ...: - case _: - pass - case None: - pass - """) - - @no_perf - def test_patma_271(self): - self.assert_syntax_error(""" - match ...: - case x: - pass - case [x] if x: - pass - """) - - @no_perf - def test_patma_272(self): - self.assert_syntax_error(""" - match ...: - case x: - pass - case _: - pass - """) - - @no_perf - def test_patma_273(self): - self.assert_syntax_error(""" - match ...: - case (None | _) | _: - pass - """) - - @no_perf - def test_patma_274(self): - self.assert_syntax_error(""" - match ...: - case _ | (True | False): - pass - """) - - def test_patma_275(self): + def test_patma_239(self): x = collections.UserDict({0: 1, 2: 3}) match x: case {2: 3}: @@ -2784,7 +2538,7 @@ def test_patma_275(self): self.assertEqual(x, {0: 1, 2: 3}) self.assertEqual(y, 0) - def test_patma_276(self): + def test_patma_240(self): x = collections.UserDict({0: 1, 2: 3}) match x: case {2: 3, **z}: @@ -2793,7 +2547,7 @@ def test_patma_276(self): self.assertEqual(y, 0) self.assertEqual(z, {0: 1}) - def test_patma_277(self): + def test_patma_241(self): x = [[{0: 0}]] match x: case list([({-0-0j: int(real=0+0j, imag=0-0j) | (1) as z},)]): @@ -2802,7 +2556,7 @@ def test_patma_277(self): self.assertEqual(y, 0) self.assertEqual(z, 0) - def test_patma_278(self): + def test_patma_242(self): x = range(3) match x: case [y, *_, z]: @@ -2812,7 +2566,7 @@ def test_patma_278(self): self.assertEqual(y, 0) self.assertEqual(z, 2) - def test_patma_279(self): + def test_patma_243(self): x = range(3) match x: case [_, *_, y]: @@ -2821,7 +2575,7 @@ def test_patma_279(self): self.assertEqual(y, 2) self.assertEqual(z, 0) - def test_patma_280(self): + def test_patma_244(self): x = range(3) match x: case [*_, y]: @@ -2830,82 +2584,7 @@ def test_patma_280(self): self.assertEqual(y, 2) self.assertEqual(z, 0) - @no_perf - def test_patma_281(self): - x = range(10) - y = None - with self.assertRaises(TypeError): - match x: - case range(10): - y = 0 - self.assertEqual(x, range(10)) - self.assertIs(y, None) - - @no_perf - def test_patma_282(self): - class Class: - __match_args__ = ["spam", "eggs"] - spam = 0 - eggs = 1 - x = Class() - w = y = z = None - with self.assertRaises(TypeError): - match x: - case Class(y, z): - w = 0 - self.assertIs(w, None) - self.assertIs(y, None) - self.assertIs(z, None) - - @no_perf - def test_patma_283(self): - self.assert_syntax_error(""" - match ...: - case {0+0: _}: - pass - """) - - @no_perf - def test_patma_284(self): - self.assert_syntax_error(""" - match ...: - case {f"": _}: - pass - """) - - @no_perf - def test_patma_285(self): - self.assert_syntax_error(""" - match ...: - case 0j+0: - pass - """) - - @no_perf - def test_patma_286(self): - self.assert_syntax_error(""" - match ...: - case 0j+0j: - pass - """) - - @no_perf - def test_patma_287(self): - self.assert_syntax_error(""" - match ...: - case {0j+0: _}: - pass - """) - - @no_perf - def test_patma_288(self): - self.assert_syntax_error(""" - match ...: - case {0j+0j: _}: - pass - """) - - def test_patma_289(self): + def test_patma_245(self): x = {"y": 1} match x: case {"y": (0 as y) | (1 as y)}: @@ -2914,23 +2593,7 @@ def test_patma_289(self): self.assertEqual(y, 1) self.assertEqual(z, 0) - @no_perf - def test_patma_290(self): - self.assert_syntax_error(""" - match ...: - case [a, [b] | [c] | [d]]: - pass - """) - - @no_perf - def test_patma_291(self): - # Hunting for leaks using -R doesn't catch leaks in the compiler itself, - # just the code under test. This test ensures that if there are leaks in - # the pattern compiler, those runs will fail: - with open(__file__) as file: - compile(file.read(), __file__, "exec") - - def test_patma_292(self): + def test_patma_246(self): def f(x): match x: case ((a, b, c, d, e, f, g, h, i, 9) | @@ -2954,7 +2617,7 @@ def f(x): self.assertEqual(f(range(-1, -11, -1)), alts[3]) self.assertEqual(f(range(10, 20)), alts[4]) - def test_patma_293(self): + def test_patma_247(self): def f(x): match x: case [y, (a, b, c, d, e, f, g, h, i, 9) | @@ -2979,79 +2642,535 @@ def f(x): self.assertEqual(f((False, range(10, 20), True)), alts[4]) -class TestInheritance(unittest.TestCase): +class TestSyntaxErrors(unittest.TestCase): - def test_multiple_inheritance(self): - class C: - pass - class S1(collections.UserList, collections.abc.Mapping): - pass - class S2(C, collections.UserList, collections.abc.Mapping): - pass - class S3(list, C, collections.abc.Mapping): - pass - class S4(collections.UserList, dict, C): - pass - class M1(collections.UserDict, collections.abc.Sequence): - pass - class M2(C, collections.UserDict, collections.abc.Sequence): - pass - class M3(collections.UserDict, C, list): - pass - class M4(dict, collections.abc.Sequence, C): - pass - def f(x): + def assert_syntax_error(self, code: str): + with self.assertRaises(SyntaxError): + compile(inspect.cleandoc(code), "", "exec") + + def test_alternative_patterns_bind_different_names_0(self): + self.assert_syntax_error(""" + match ...: + case "a" | a: + pass + """) + + def test_alternative_patterns_bind_different_names_1(self): + self.assert_syntax_error(""" + match ...: + case [a, [b] | [c] | [d]]: + pass + """) + + + def test_attribute_name_repeated_in_class_pattern(self): + self.assert_syntax_error(""" + match ...: + case Class(a=_, a=_): + pass + """) + + def test_imaginary_number_required_in_complex_literal_0(self): + self.assert_syntax_error(""" + match ...: + case 0+0: + pass + """) + + def test_imaginary_number_required_in_complex_literal_1(self): + self.assert_syntax_error(""" + match ...: + case {0+0: _}: + pass + """) + + def test_invalid_syntax_0(self): + self.assert_syntax_error(""" + match ...: + case {**rest, "key": value}: + pass + """) + + def test_invalid_syntax_1(self): + self.assert_syntax_error(""" + match ...: + case {"first": first, **rest, "last": last}: + pass + """) + + def test_invalid_syntax_2(self): + self.assert_syntax_error(""" + match ...: + case {**_}: + pass + """) + + def test_invalid_syntax_3(self): + self.assert_syntax_error(""" + match ...: + case 42 as _: + pass + """) + + def test_mapping_pattern_keys_may_only_match_literals_and_attribute_lookups(self): + self.assert_syntax_error(""" + match ...: + case {f"": _}: + pass + """) + + def test_multiple_assignments_to_name_in_pattern_0(self): + self.assert_syntax_error(""" + match ...: + case a, a: + pass + """) + + def test_multiple_assignments_to_name_in_pattern_1(self): + self.assert_syntax_error(""" + match ...: + case {"k": a, "l": a}: + pass + """) + + def test_multiple_assignments_to_name_in_pattern_2(self): + self.assert_syntax_error(""" + match ...: + case MyClass(x, x): + pass + """) + + def test_multiple_assignments_to_name_in_pattern_3(self): + self.assert_syntax_error(""" + match ...: + case MyClass(x=x, y=x): + pass + """) + + def test_multiple_assignments_to_name_in_pattern_4(self): + self.assert_syntax_error(""" + match ...: + case MyClass(x, y=x): + pass + """) + + def test_multiple_assignments_to_name_in_pattern_5(self): + self.assert_syntax_error(""" + match ...: + case a as a: + pass + """) + + def test_multiple_starred_names_in_sequence_pattern_0(self): + self.assert_syntax_error(""" + match ...: + case *a, b, *c, d, *e: + pass + """) + + def test_multiple_starred_names_in_sequence_pattern_1(self): + self.assert_syntax_error(""" + match ...: + case a, *b, c, *d, e: + pass + """) + + def test_name_capture_makes_remaining_patterns_unreachable_0(self): + self.assert_syntax_error(""" + match ...: + case a | "a": + pass + """) + + def test_name_capture_makes_remaining_patterns_unreachable_1(self): + self.assert_syntax_error(""" + match 42: + case x: + pass + case y: + pass + """) + + def test_name_capture_makes_remaining_patterns_unreachable_2(self): + self.assert_syntax_error(""" + match ...: + case x | [_ as x] if x: + pass + """) + + def test_name_capture_makes_remaining_patterns_unreachable_3(self): + self.assert_syntax_error(""" + match ...: + case x: + pass + case [x] if x: + pass + """) + + def test_name_capture_makes_remaining_patterns_unreachable_4(self): + self.assert_syntax_error(""" + match ...: + case x: + pass + case _: + pass + """) + + def test_patterns_may_only_match_literals_and_attribute_lookups_0(self): + self.assert_syntax_error(""" + match ...: + case f"": + pass + """) + + def test_patterns_may_only_match_literals_and_attribute_lookups_1(self): + self.assert_syntax_error(""" + match ...: + case f"{x}": + pass + """) + + def test_real_number_required_in_complex_literal_0(self): + self.assert_syntax_error(""" + match ...: + case 0j+0: + pass + """) + + def test_real_number_required_in_complex_literal_1(self): + self.assert_syntax_error(""" + match ...: + case 0j+0j: + pass + """) + + def test_real_number_required_in_complex_literal_2(self): + self.assert_syntax_error(""" + match ...: + case {0j+0: _}: + pass + """) + + def test_real_number_required_in_complex_literal_3(self): + self.assert_syntax_error(""" + match ...: + case {0j+0j: _}: + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_0(self): + self.assert_syntax_error(""" + match ...: + case _ | _: + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_1(self): + self.assert_syntax_error(""" + match ...: + case (_ as x) | [x]: + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_2(self): + self.assert_syntax_error(""" + match ...: + case _ | _ if condition(): + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_3(self): + self.assert_syntax_error(""" + match ...: + case _: + pass + case None: + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_4(self): + self.assert_syntax_error(""" + match ...: + case (None | _) | _: + pass + """) + + def test_wildcard_makes_remaining_patterns_unreachable_5(self): + self.assert_syntax_error(""" + match ...: + case _ | (True | False): + pass + """) + + def test_mapping_pattern_duplicate_key(self): + self.assert_syntax_error(""" + match ...: + case {"a": _, "a": _}: + pass + """) + + def test_mapping_pattern_duplicate_key_edge_case0(self): + self.assert_syntax_error(""" + match ...: + case {0: _, False: _}: + pass + """) + + def test_mapping_pattern_duplicate_key_edge_case1(self): + self.assert_syntax_error(""" + match ...: + case {0: _, 0.0: _}: + pass + """) + + def test_mapping_pattern_duplicate_key_edge_case2(self): + self.assert_syntax_error(""" + match ...: + case {0: _, -0: _}: + pass + """) + + def test_mapping_pattern_duplicate_key_edge_case3(self): + self.assert_syntax_error(""" + match ...: + case {0: _, 0j: _}: + pass + """) + +class TestTypeErrors(unittest.TestCase): + + def test_accepts_positional_subpatterns_0(self): + class Class: + __match_args__ = () + x = Class() + y = z = None + with self.assertRaises(TypeError): match x: - case []: - return "seq" - case {}: - return "map" - def g(x): + case Class(y): + z = 0 + self.assertIs(y, None) + self.assertIs(z, None) + + def test_accepts_positional_subpatterns_1(self): + x = range(10) + y = None + with self.assertRaises(TypeError): match x: - case {}: - return "map" - case []: - return "seq" - for Seq in (S1, S2, S3, S4): - self.assertEqual(f(Seq()), "seq") - self.assertEqual(g(Seq()), "seq") - for Map in (M1, M2, M3, M4): - self.assertEqual(f(Map()), "map") - self.assertEqual(g(Map()), "map") + case range(10): + y = 0 + self.assertEqual(x, range(10)) + self.assertIs(y, None) + def test_got_multiple_subpatterns_for_attribute_0(self): + class Class: + __match_args__ = ("a", "a") + a = None + x = Class() + w = y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y, z): + w = 0 + self.assertIs(w, None) + self.assertIs(y, None) + self.assertIs(z, None) -class PerfPatma(TestPatma): + def test_got_multiple_subpatterns_for_attribute_1(self): + class Class: + __match_args__ = ("a",) + a = None + x = Class() + w = y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y, a=z): + w = 0 + self.assertIs(w, None) + self.assertIs(y, None) + self.assertIs(z, None) - def assertEqual(*_, **__): - pass + def test_match_args_elements_must_be_strings(self): + class Class: + __match_args__ = (None,) + x = Class() + y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y): + z = 0 + self.assertIs(y, None) + self.assertIs(z, None) - def assertIs(*_, **__): - pass + def test_match_args_must_be_a_tuple_0(self): + class Class: + __match_args__ = None + x = Class() + y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y): + z = 0 + self.assertIs(y, None) + self.assertIs(z, None) + + def test_match_args_must_be_a_tuple_1(self): + class Class: + __match_args__ = "XYZ" + x = Class() + y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y): + z = 0 + self.assertIs(y, None) + self.assertIs(z, None) + + def test_match_args_must_be_a_tuple_2(self): + class Class: + __match_args__ = ["spam", "eggs"] + spam = 0 + eggs = 1 + x = Class() + w = y = z = None + with self.assertRaises(TypeError): + match x: + case Class(y, z): + w = 0 + self.assertIs(w, None) + self.assertIs(y, None) + self.assertIs(z, None) - def assertRaises(*_, **__): - assert False, "this test should be decorated with @no_perf!" - def assertWarns(*_, **__): - assert False, "this test should be decorated with @no_perf!" +class TestValueErrors(unittest.TestCase): - def run_perf(self): - attrs = vars(TestPatma).items() - tests = [ - attr for name, attr in attrs - if name.startswith("test_") and not hasattr(attr, "no_perf") - ] - for _ in range(1 << 8): - for test in tests: - test(self) + def test_mapping_pattern_checks_duplicate_key_1(self): + class Keys: + KEY = "a" + x = {"a": 0, "b": 1} + w = y = z = None + with self.assertRaises(ValueError): + match x: + case {Keys.KEY: y, "a": z}: + w = 0 + self.assertIs(w, None) + self.assertIs(y, None) + self.assertIs(z, None) + + +class TestTracing(unittest.TestCase): @staticmethod - def setUpClass(): - raise unittest.SkipTest("performance testing") + def _trace(func, *args, **kwargs): + actual_linenos = [] + + def trace(frame, event, arg): + if event == "line" and frame.f_code.co_name == func.__name__: + assert arg is None + relative_lineno = frame.f_lineno - func.__code__.co_firstlineno + actual_linenos.append(relative_lineno) + return trace + + old_trace = sys.gettrace() + sys.settrace(trace) + try: + func(*args, **kwargs) + finally: + sys.settrace(old_trace) + return actual_linenos + + def test_default_wildcard(self): + def f(command): # 0 + match command.split(): # 1 + case ["go", direction] if direction in "nesw": # 2 + return f"go {direction}" # 3 + case ["go", _]: # 4 + return "no go" # 5 + case _: # 6 + return "default" # 7 + + self.assertListEqual(self._trace(f, "go n"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "go x"), [1, 2, 4, 5]) + self.assertListEqual(self._trace(f, "spam"), [1, 2, 4, 6, 7]) + + def test_default_capture(self): + def f(command): # 0 + match command.split(): # 1 + case ["go", direction] if direction in "nesw": # 2 + return f"go {direction}" # 3 + case ["go", _]: # 4 + return "no go" # 5 + case x: # 6 + return x # 7 + + self.assertListEqual(self._trace(f, "go n"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "go x"), [1, 2, 4, 5]) + self.assertListEqual(self._trace(f, "spam"), [1, 2, 4, 6, 7]) + + def test_no_default(self): + def f(command): # 0 + match command.split(): # 1 + case ["go", direction] if direction in "nesw": # 2 + return f"go {direction}" # 3 + case ["go", _]: # 4 + return "no go" # 5 + + self.assertListEqual(self._trace(f, "go n"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "go x"), [1, 2, 4, 5]) + self.assertListEqual(self._trace(f, "spam"), [1, 2, 4]) + + def test_only_default_wildcard(self): + def f(command): # 0 + match command.split(): # 1 + case _: # 2 + return "default" # 3 + + self.assertListEqual(self._trace(f, "go n"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "go x"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "spam"), [1, 2, 3]) + + def test_only_default_capture(self): + def f(command): # 0 + match command.split(): # 1 + case x: # 2 + return x # 3 + + self.assertListEqual(self._trace(f, "go n"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "go x"), [1, 2, 3]) + self.assertListEqual(self._trace(f, "spam"), [1, 2, 3]) + + +if __name__ == "__main__": + """ + # From inside environment using this Python, with pyperf installed: + sudo $(which pyperf) system tune && \ + $(which python) -m test.test_patma --rigorous; \ + sudo $(which pyperf) system reset + """ + import pyperf + + + class PerfPatma(TestPatma): + + def assertEqual(*_, **__): + pass + + def assertIs(*_, **__): + pass + + def assertRaises(*_, **__): + assert False, "this test should be a method of a different class!" + + def run_perf(self, count): + tests = [] + for attr in vars(TestPatma): + if attr.startswith("test_"): + tests.append(getattr(self, attr)) + tests *= count + start = pyperf.perf_counter() + for test in tests: + test() + return pyperf.perf_counter() - start -""" -# From inside venv pointing to this Python, with pyperf installed: -sudo $(which python) -m pyperf system tune && \ - $(which python) -m pyperf timeit --rigorous --setup "from test.test_patma import PerfPatma; p = PerfPatma()" "p.run_perf()"; \ -sudo $(which python) -m pyperf system reset -""" + runner = pyperf.Runner() + runner.bench_time_func("patma", PerfPatma().run_perf) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 870eab4e33e633..d4c037dabff97e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -9,8 +9,9 @@ import unittest import subprocess import textwrap +import linecache -from contextlib import ExitStack +from contextlib import ExitStack, redirect_stdout from io import StringIO from test.support import os_helper # This little helper class is essential for testing pdb under doctest. @@ -390,6 +391,34 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): (Pdb) continue """ +def test_pdb_pp_repr_exc(): + """Test that do_p/do_pp do not swallow exceptions. + + >>> class BadRepr: + ... def __repr__(self): + ... raise Exception('repr_exc') + >>> obj = BadRepr() + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'p obj', + ... 'pp obj', + ... 'continue', + ... ]): + ... test_function() + --Return-- + > (2)test_function()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) p obj + *** Exception: repr_exc + (Pdb) pp obj + *** Exception: repr_exc + (Pdb) continue + """ + + def do_nothing(): pass @@ -1287,12 +1316,41 @@ def test_pdb_issue_20766(): -> print('pdb %d: %s' % (i, sess._previous_sigint_handler)) (Pdb) continue pdb 1: - > (5)test_function() - -> sess.set_trace(sys._getframe()) + > (6)test_function() + -> print('pdb %d: %s' % (i, sess._previous_sigint_handler)) (Pdb) continue pdb 2: """ +def test_pdb_issue_43318(): + """echo breakpoints cleared with filename:lineno + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... print(1) + ... print(2) + ... print(3) + ... print(4) + >>> reset_Breakpoint() + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'break 3', + ... 'clear :3', + ... 'continue' + ... ]): + ... test_function() + > (3)test_function() + -> print(1) + (Pdb) break 3 + Breakpoint 1 at :3 + (Pdb) clear :3 + Deleted breakpoint 1 at :3 + (Pdb) continue + 1 + 2 + 3 + 4 + """ + class PdbTestCase(unittest.TestCase): def tearDown(self): @@ -1630,13 +1688,27 @@ def test_module_without_a_main(self): os_helper.rmtree(module_name) init_file = module_name + '/__init__.py' os.mkdir(module_name) - with open(init_file, 'w') as f: + with open(init_file, 'w'): pass self.addCleanup(os_helper.rmtree, module_name) stdout, stderr = self._run_pdb(['-m', module_name], "") self.assertIn("ImportError: No module named t_main.__main__", stdout.splitlines()) + def test_package_without_a_main(self): + pkg_name = 't_pkg' + module_name = 't_main' + os_helper.rmtree(pkg_name) + modpath = pkg_name + '/' + module_name + os.makedirs(modpath) + with open(modpath + '/__init__.py', 'w'): + pass + self.addCleanup(os_helper.rmtree, pkg_name) + stdout, stderr = self._run_pdb(['-m', modpath.replace('/', '.')], "") + self.assertIn( + "'t_pkg.t_main' is a package and cannot be directly executed", + stdout) + def test_blocks_at_first_code_line(self): script = """ #This is a comment, on line 2 @@ -1742,6 +1814,21 @@ def test_errors_in_command(self): '(Pdb) ', ]) + def test_issue34266(self): + '''do_run handles exceptions from parsing its arg''' + def check(bad_arg, msg): + commands = "\n".join([ + f'run {bad_arg}', + 'q', + ]) + stdout, _ = self.run_pdb_script('pass', commands + '\n') + self.assertEqual(stdout.splitlines()[1:], [ + '-> pass', + f'(Pdb) *** Cannot run {bad_arg}: {msg}', + '(Pdb) ', + ]) + check('\\', 'No escaped character') + check('"', 'No closing quotation') def test_issue42384(self): '''When running `python foo.py` sys.path[0] is an absolute path. `python -m pdb foo.py` should behave the same''' @@ -1807,10 +1894,48 @@ def test_issue42383(self): self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected) +class ChecklineTests(unittest.TestCase): + def setUp(self): + linecache.clearcache() # Pdb.checkline() uses linecache.getline() + + def tearDown(self): + os_helper.unlink(os_helper.TESTFN) + + def test_checkline_before_debugging(self): + with open(os_helper.TESTFN, "w") as f: + f.write("print(123)") + db = pdb.Pdb() + self.assertEqual(db.checkline(os_helper.TESTFN, 1), 1) + + def test_checkline_after_reset(self): + with open(os_helper.TESTFN, "w") as f: + f.write("print(123)") + db = pdb.Pdb() + db.reset() + self.assertEqual(db.checkline(os_helper.TESTFN, 1), 1) + + def test_checkline_is_not_executable(self): + # Test for comments, docstrings and empty lines + s = textwrap.dedent(""" + # Comment + \"\"\" docstring \"\"\" + ''' docstring ''' + + """) + with open(os_helper.TESTFN, "w") as f: + f.write(s) + num_lines = len(s.splitlines()) + 2 # Test for EOF + with redirect_stdout(StringIO()): + db = pdb.Pdb() + for lineno in range(num_lines): + self.assertFalse(db.checkline(os_helper.TESTFN, lineno)) + + def load_tests(*args): from test import test_pdb suites = [ unittest.makeSuite(PdbTestCase), + unittest.makeSuite(ChecklineTests), doctest.DocTestSuite(test_pdb) ] return unittest.TestSuite(suites) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 4034154e4dcfb5..11a4d1740b8dce 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -514,5 +514,12 @@ def test_bpo_42057(self): except Exception or Exception: pass + def test_bpo_45773_pop_jump_if_true(self): + compile("while True or spam: pass", "", "exec") + + def test_bpo_45773_pop_jump_if_false(self): + compile("while True or not spam: pass", "", "exec") + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_peg_generator/test_c_parser.py b/Lib/test/test_peg_generator/test_c_parser.py index 3852cfbc477b6b..013b3afd594392 100644 --- a/Lib/test/test_peg_generator/test_c_parser.py +++ b/Lib/test/test_peg_generator/test_c_parser.py @@ -1,7 +1,9 @@ import sysconfig import textwrap import unittest -from distutils.tests.support import TempdirManager +import os +import shutil +import tempfile from pathlib import Path from test import test_tools @@ -68,20 +70,21 @@ def test_parse(self): """ -class TestCParser(TempdirManager, unittest.TestCase): +class TestCParser(unittest.TestCase): def setUp(self): self._backup_config_vars = dict(sysconfig._CONFIG_VARS) cmd = support.missing_compiler_executable() if cmd is not None: self.skipTest("The %r command is not found" % cmd) - super(TestCParser, self).setUp() - self.tmp_path = self.mkdtemp() + self.old_cwd = os.getcwd() + self.tmp_path = tempfile.mkdtemp() change_cwd = os_helper.change_cwd(self.tmp_path) change_cwd.__enter__() self.addCleanup(change_cwd.__exit__, None, None, None) def tearDown(self): - super(TestCParser, self).tearDown() + os.chdir(self.old_cwd) + shutil.rmtree(self.tmp_path) sysconfig._CONFIG_VARS.clear() sysconfig._CONFIG_VARS.update(self._backup_config_vars) diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py index 23c7bd261e85ca..8775ff4b79157d 100644 --- a/Lib/test/test_pickle.py +++ b/Lib/test/test_pickle.py @@ -6,8 +6,10 @@ import collections import struct import sys +import warnings import weakref +import doctest import unittest from test import support from test.support import import_helper @@ -30,7 +32,7 @@ has_c_implementation = False -class PyPickleTests(AbstractPickleModuleTests): +class PyPickleTests(AbstractPickleModuleTests, unittest.TestCase): dump = staticmethod(pickle._dump) dumps = staticmethod(pickle._dumps) load = staticmethod(pickle._load) @@ -39,7 +41,7 @@ class PyPickleTests(AbstractPickleModuleTests): Unpickler = pickle._Unpickler -class PyUnpicklerTests(AbstractUnpickleTests): +class PyUnpicklerTests(AbstractUnpickleTests, unittest.TestCase): unpickler = pickle._Unpickler bad_stack_errors = (IndexError,) @@ -53,7 +55,7 @@ def loads(self, buf, **kwds): return u.load() -class PyPicklerTests(AbstractPickleTests): +class PyPicklerTests(AbstractPickleTests, unittest.TestCase): pickler = pickle._Pickler unpickler = pickle._Unpickler @@ -72,7 +74,7 @@ def loads(self, buf, **kwds): class InMemoryPickleTests(AbstractPickleTests, AbstractUnpickleTests, - BigmemPickleTests): + BigmemPickleTests, unittest.TestCase): bad_stack_errors = (pickle.UnpicklingError, IndexError) truncated_errors = (pickle.UnpicklingError, EOFError, @@ -109,14 +111,14 @@ def persistent_load(subself, obj): class PyPersPicklerTests(AbstractPersistentPicklerTests, - PersistentPicklerUnpicklerMixin): + PersistentPicklerUnpicklerMixin, unittest.TestCase): pickler = pickle._Pickler unpickler = pickle._Unpickler class PyIdPersPicklerTests(AbstractIdentityPersistentPicklerTests, - PersistentPicklerUnpicklerMixin): + PersistentPicklerUnpicklerMixin, unittest.TestCase): pickler = pickle._Pickler unpickler = pickle._Unpickler @@ -182,13 +184,13 @@ def persistent_load(pid): check(PersUnpickler) -class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests): +class PyPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase): pickler_class = pickle._Pickler unpickler_class = pickle._Unpickler -class PyDispatchTableTests(AbstractDispatchTableTests): +class PyDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): pickler_class = pickle._Pickler @@ -196,7 +198,7 @@ def get_dispatch_table(self): return pickle.dispatch_table.copy() -class PyChainDispatchTableTests(AbstractDispatchTableTests): +class PyChainDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): pickler_class = pickle._Pickler @@ -204,7 +206,7 @@ def get_dispatch_table(self): return collections.ChainMap({}, pickle.dispatch_table) -class PyPicklerHookTests(AbstractHookTests): +class PyPicklerHookTests(AbstractHookTests, unittest.TestCase): class CustomPyPicklerClass(pickle._Pickler, AbstractCustomPicklerClass): pass @@ -212,7 +214,7 @@ class CustomPyPicklerClass(pickle._Pickler, if has_c_implementation: - class CPickleTests(AbstractPickleModuleTests): + class CPickleTests(AbstractPickleModuleTests, unittest.TestCase): from _pickle import dump, dumps, load, loads, Pickler, Unpickler class CUnpicklerTests(PyUnpicklerTests): @@ -240,7 +242,7 @@ class DumpPickle_CLoadPickle(PyPicklerTests): pickler = pickle._Pickler unpickler = _pickle.Unpickler - class CPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests): + class CPicklerUnpicklerObjectTests(AbstractPicklerUnpicklerObjectTests, unittest.TestCase): pickler_class = _pickle.Pickler unpickler_class = _pickle.Unpickler @@ -253,17 +255,17 @@ def test_issue18339(self): unpickler.memo = {-1: None} unpickler.memo = {1: None} - class CDispatchTableTests(AbstractDispatchTableTests): + class CDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): pickler_class = pickle.Pickler def get_dispatch_table(self): return pickle.dispatch_table.copy() - class CChainDispatchTableTests(AbstractDispatchTableTests): + class CChainDispatchTableTests(AbstractDispatchTableTests, unittest.TestCase): pickler_class = pickle.Pickler def get_dispatch_table(self): return collections.ChainMap({}, pickle.dispatch_table) - class CPicklerHookTests(AbstractHookTests): + class CPicklerHookTests(AbstractHookTests, unittest.TestCase): class CustomCPicklerClass(_pickle.Pickler, AbstractCustomPicklerClass): pass pickler_class = CustomCPicklerClass @@ -367,7 +369,10 @@ def getmodule(module): return sys.modules[module] except KeyError: try: - __import__(module) + with warnings.catch_warnings(): + action = 'always' if support.verbose else 'ignore' + warnings.simplefilter(action, DeprecationWarning) + __import__(module) except AttributeError as exc: if support.verbose: print("Can't import module %r: %s" % (module, exc)) @@ -510,22 +515,10 @@ def test_multiprocessing_exceptions(self): ('multiprocessing.context', name)) -def test_main(): - tests = [PyPickleTests, PyUnpicklerTests, PyPicklerTests, - PyPersPicklerTests, PyIdPersPicklerTests, - PyDispatchTableTests, PyChainDispatchTableTests, - CompatPickleTests, PyPicklerHookTests] - if has_c_implementation: - tests.extend([CPickleTests, CUnpicklerTests, CPicklerTests, - CPersPicklerTests, CIdPersPicklerTests, - CDumpPickle_LoadPickle, DumpPickle_CLoadPickle, - PyPicklerUnpicklerObjectTests, - CPicklerUnpicklerObjectTests, - CDispatchTableTests, CChainDispatchTableTests, - CPicklerHookTests, - InMemoryPickleTests, SizeofTests]) - support.run_unittest(*tests) - support.run_doctest(pickle) +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite()) + return tests + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_pickletools.py b/Lib/test/test_pickletools.py index f5e9ae41c3c1a4..d37af79e878a2e 100644 --- a/Lib/test/test_pickletools.py +++ b/Lib/test/test_pickletools.py @@ -2,9 +2,10 @@ import pickletools from test import support from test.pickletester import AbstractPickleTests +import doctest import unittest -class OptimizedPickleTests(AbstractPickleTests): +class OptimizedPickleTests(AbstractPickleTests, unittest.TestCase): def dumps(self, arg, proto=None, **kwargs): return pickletools.optimize(pickle.dumps(arg, proto, **kwargs)) @@ -94,11 +95,10 @@ def test__all__(self): support.check__all__(self, pickletools, not_exported=not_exported) -def test_main(): - support.run_unittest(OptimizedPickleTests) - support.run_unittest(MiscTestCase) - support.run_doctest(pickletools) +def load_tests(loader, tests, pattern): + tests.addTest(doctest.DocTestSuite(pickletools)) + return tests if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_pipes.py b/Lib/test/test_pipes.py index 6a13b36d1cb70e..6335e7cbe09c4e 100644 --- a/Lib/test/test_pipes.py +++ b/Lib/test/test_pipes.py @@ -3,7 +3,7 @@ import string import unittest import shutil -from test.support import run_unittest, reap_children, unix_shell +from test.support import reap_children, unix_shell from test.support.os_helper import TESTFN, unlink @@ -199,9 +199,10 @@ def testClone(self): self.assertNotEqual(id(t.steps), id(u.steps)) self.assertEqual(t.debugging, u.debugging) -def test_main(): - run_unittest(SimplePipeTests) + +def tearDownModule(): reap_children() + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 6e3618f6b0f98b..800fe38fb486a1 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -1,4 +1,3 @@ -from test.support import run_unittest from test.support.import_helper import unload, CleanImport from test.support.warnings_helper import check_warnings import unittest @@ -580,9 +579,7 @@ def test_iter_importers_avoids_emulation(self): self.assertEqual(len(w.warnings), 0) -def test_main(): - run_unittest(PkgutilTests, PkgutilPEP302Tests, ExtendPathTests, - NestedNamespacePackageTest, ImportlibMigrationTests) +def tearDownModule(): # this is necessary if test is run repeated (like when finding leaks) import zipimport import importlib @@ -591,4 +588,4 @@ def test_main(): if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py index de62350696a920..82bbb3af9f1b39 100644 --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -7,7 +7,7 @@ import threading import time import unittest -from test.support import run_unittest, cpython_only +from test.support import cpython_only from test.support import threading_helper from test.support.os_helper import TESTFN @@ -229,8 +229,5 @@ def test_poll_blocks_with_negative_ms(self): os.close(w) -def test_main(): - run_unittest(PollTests) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index c5ae9f77e4f006..1220ca32ef82e8 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -4,19 +4,24 @@ # a real test suite import poplib -import asyncore -import asynchat import socket import os import errno import threading +import unittest from unittest import TestCase, skipUnless from test import support as test_support from test.support import hashlib_helper from test.support import socket_helper from test.support import threading_helper +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asynchat + import asyncore + HOST = socket_helper.HOST PORT = 0 @@ -313,11 +318,11 @@ def test_noop(self): def test_rpop(self): self.assertOK(self.client.rpop('foo')) - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def test_apop_normal(self): self.assertOK(self.client.apop('foo', 'dummypassword')) - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def test_apop_REDOS(self): # Replace welcome with very long evil welcome. # NB The upper bound on welcome length is currently 2048. @@ -534,15 +539,10 @@ def testTimeoutValue(self): poplib.POP3(HOST, self.port, timeout=0) -def test_main(): - tests = [TestPOP3Class, TestTimeouts, - TestPOP3_SSLClass, TestPOP3_TLSClass] +def setUpModule(): thread_info = threading_helper.threading_setup() - try: - test_support.run_unittest(*tests) - finally: - threading_helper.threading_cleanup(*thread_info) + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index e4666884ce06a1..56b72f465c1c08 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -2171,17 +2171,9 @@ def test_utime(self): os.utime("path", dir_fd=0) -def test_main(): - try: - support.run_unittest( - PosixTester, - PosixGroupsTester, - TestPosixSpawn, - TestPosixSpawnP, - TestPosixWeaklinking - ) - finally: - support.reap_children() +def tearDownModule(): + support.reap_children() + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py index e8381122182e05..5f1bfd9e30db98 100644 --- a/Lib/test/test_print.py +++ b/Lib/test/test_print.py @@ -140,21 +140,24 @@ def test_normal_string(self): with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print("Hello World")', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) def test_string_with_soft_space(self): python2_print_str = 'print "Hello World",' with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print("Hello World", end=" ")', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) def test_string_with_excessive_whitespace(self): python2_print_str = 'print "Hello World", ' with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print("Hello World", end=" ")', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) def test_string_with_leading_whitespace(self): python2_print_str = '''if 1: @@ -163,7 +166,8 @@ def test_string_with_leading_whitespace(self): with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print("Hello World")', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) # bpo-32685: Suggestions for print statement should be proper when # it is in the same line as the header of a compound statement @@ -173,14 +177,16 @@ def test_string_with_semicolon(self): with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print(p)', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) def test_string_in_loop_on_same_line(self): python2_print_str = 'for i in s: print i' with self.assertRaises(SyntaxError) as context: exec(python2_print_str) - self.assertIn('print(i)', str(context.exception)) + self.assertIn("Missing parentheses in call to 'print'. Did you mean print(...)", + str(context.exception)) def test_stream_redirection_hint_for_py2_migration(self): # Test correct hint produced for Py2 redirection syntax diff --git a/Lib/test/test_profile.py b/Lib/test/test_profile.py index 7de7d52ff83650..d97fe447c38b01 100644 --- a/Lib/test/test_profile.py +++ b/Lib/test/test_profile.py @@ -6,7 +6,6 @@ import os from difflib import unified_diff from io import StringIO -from test.support import run_unittest from test.support.os_helper import TESTFN, unlink, temp_dir, change_cwd from contextlib import contextmanager @@ -156,12 +155,10 @@ def silent(): finally: sys.stdout = stdout -def test_main(): - run_unittest(ProfileTest) def main(): if '-r' not in sys.argv: - test_main() + unittest.main() else: regenerate_expected_output(__file__, ProfileTest) diff --git a/Lib/test/test_pstats.py b/Lib/test/test_pstats.py index acc2fa5385d923..c9a5fd5d0ed609 100644 --- a/Lib/test/test_pstats.py +++ b/Lib/test/test_pstats.py @@ -3,7 +3,6 @@ from test import support from io import StringIO from pstats import SortKey -from enum import StrEnum, _test_simple_enum import pstats import cProfile @@ -62,32 +61,6 @@ def test_sort_stats_partial(self): self.assertEqual(self.stats.sort_type, self.stats.sort_arg_dict_default[sortkey][-1]) - def test_sort_stats_enum(self): - for member in SortKey: - self.stats.sort_stats(member) - self.assertEqual( - self.stats.sort_type, - self.stats.sort_arg_dict_default[member.value][-1]) - class CheckedSortKey(StrEnum): - CALLS = 'calls', 'ncalls' - CUMULATIVE = 'cumulative', 'cumtime' - FILENAME = 'filename', 'module' - LINE = 'line' - NAME = 'name' - NFL = 'nfl' - PCALLS = 'pcalls' - STDNAME = 'stdname' - TIME = 'time', 'tottime' - def __new__(cls, *values): - value = values[0] - obj = str.__new__(cls, value) - obj._value_ = value - for other_value in values[1:]: - cls._value2member_map_[other_value] = obj - obj._all_values = values - return obj - _test_simple_enum(CheckedSortKey, SortKey) - def test_sort_starts_mix(self): self.assertRaises(TypeError, self.stats.sort_stats, 'calls', diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index 7585c42bf01338..0c178127571b07 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -5,8 +5,9 @@ import_module('termios') import errno -import pty import os +import pty +import tty import sys import select import signal @@ -123,12 +124,6 @@ def handle_sig(self, sig, frame): @staticmethod def handle_sighup(signum, frame): - # bpo-38547: if the process is the session leader, os.close(master_fd) - # of "master_fd, slave_name = pty.master_open()" raises SIGHUP - # signal: just ignore the signal. - # - # NOTE: the above comment is from an older version of the test; - # master_open() is not being used anymore. pass @expectedFailureIfStdinIsTTY @@ -141,7 +136,7 @@ def test_openpty(self): mode = None new_stdin_winsz = None - if self.stdin_rows != None and self.stdin_cols != None: + if self.stdin_rows is not None and self.stdin_cols is not None: try: # Modify pty.STDIN_FILENO window size; we need to # check if pty.openpty() is able to set pty slave @@ -190,13 +185,6 @@ def test_openpty(self): self.assertEqual(_get_term_winsz(slave_fd), new_stdin_winsz, "openpty() failed to set slave window size") - # Solaris requires reading the fd before anything is returned. - # My guess is that since we open and close the slave fd - # in master_open(), we need to read the EOF. - # - # NOTE: the above comment is from an older version of the test; - # master_open() is not being used anymore. - # Ensure the fd is non-blocking in case there's nothing to read. blocking = os.get_blocking(master_fd) try: @@ -324,22 +312,40 @@ def test_master_read(self): self.assertEqual(data, b"") + def test_spawn_doesnt_hang(self): + pty.spawn([sys.executable, '-c', 'print("hi there")']) + class SmallPtyTests(unittest.TestCase): """These tests don't spawn children or hang.""" def setUp(self): self.orig_stdin_fileno = pty.STDIN_FILENO self.orig_stdout_fileno = pty.STDOUT_FILENO + self.orig_pty_close = pty.close + self.orig_pty__copy = pty._copy + self.orig_pty_fork = pty.fork self.orig_pty_select = pty.select + self.orig_pty_setraw = pty.setraw + self.orig_pty_tcgetattr = pty.tcgetattr + self.orig_pty_tcsetattr = pty.tcsetattr + self.orig_pty_waitpid = pty.waitpid self.fds = [] # A list of file descriptors to close. self.files = [] self.select_rfds_lengths = [] self.select_rfds_results = [] + self.tcsetattr_mode_setting = None def tearDown(self): pty.STDIN_FILENO = self.orig_stdin_fileno pty.STDOUT_FILENO = self.orig_stdout_fileno + pty.close = self.orig_pty_close + pty._copy = self.orig_pty__copy + pty.fork = self.orig_pty_fork pty.select = self.orig_pty_select + pty.setraw = self.orig_pty_setraw + pty.tcgetattr = self.orig_pty_tcgetattr + pty.tcsetattr = self.orig_pty_tcsetattr + pty.waitpid = self.orig_pty_waitpid for file in self.files: try: file.close() @@ -367,6 +373,14 @@ def _mock_select(self, rfds, wfds, xfds, timeout=0): self.assertEqual(self.select_rfds_lengths.pop(0), len(rfds)) return self.select_rfds_results.pop(0), [], [] + def _make_mock_fork(self, pid): + def mock_fork(): + return (pid, 12) + return mock_fork + + def _mock_tcsetattr(self, fileno, opt, mode): + self.tcsetattr_mode_setting = mode + def test__copy_to_each(self): """Test the normal data case on both master_fd and stdin.""" read_from_stdout_fd, mock_stdout_fd = self._pipe() @@ -407,7 +421,6 @@ def test__copy_eof_on_all(self): socketpair[1].close() os.close(write_to_stdin_fd) - # Expect two select calls, the last one will cause IndexError pty.select = self._mock_select self.select_rfds_lengths.append(2) self.select_rfds_results.append([mock_stdin_fd, masters[0]]) @@ -415,12 +428,34 @@ def test__copy_eof_on_all(self): # both encountered an EOF before the second select call. self.select_rfds_lengths.append(0) - with self.assertRaises(IndexError): - pty._copy(masters[0]) + # We expect the function to return without error. + self.assertEqual(pty._copy(masters[0]), None) + + def test__restore_tty_mode_normal_return(self): + """Test that spawn resets the tty mode no when _copy returns normally.""" + + # PID 1 is returned from mocked fork to run the parent branch + # of code + pty.fork = self._make_mock_fork(1) + + status_sentinel = object() + pty.waitpid = lambda _1, _2: [None, status_sentinel] + pty.close = lambda _: None + + pty._copy = lambda _1, _2, _3: None + + mode_sentinel = object() + pty.tcgetattr = lambda fd: mode_sentinel + pty.tcsetattr = self._mock_tcsetattr + pty.setraw = lambda _: None + + self.assertEqual(pty.spawn([]), status_sentinel, "pty.waitpid process status not returned by pty.spawn") + self.assertEqual(self.tcsetattr_mode_setting, mode_sentinel, "pty.tcsetattr not called with original mode value") def tearDownModule(): reap_children() + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index b58f28a4bc8885..5ed98dbff1737e 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -276,7 +276,7 @@ def test_file_not_exists(self): rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists) self.assertEqual(rc, 1) self.assertEqual(stdout, b'') - self.assertIn(b'No such file or directory', stderr) + self.assertIn(b'no such file or directory', stderr.lower()) def test_file_not_exists_with_quiet(self): should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py') diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index c862a805bbcce8..44c16989716a0d 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -453,7 +453,7 @@ class BinaryInteger(enum.IntEnum): zero = 0 one = 1 doc = pydoc.render_doc(BinaryInteger) - self.assertIn('BinaryInteger.zero', doc) + self.assertIn('', doc) def test_mixed_case_module_names_are_lower_cased(self): # issue16484 @@ -1571,20 +1571,11 @@ def test_sys_path_adjustment_when_curdir_already_included(self): self.assertIsNone(self._get_revised_path(trailing_argv0dir)) -@threading_helper.reap_threads -def test_main(): - try: - test.support.run_unittest(PydocDocTest, - PydocImportTest, - TestDescriptions, - PydocServerTest, - PydocUrlHandlerTest, - TestHelper, - PydocWithMetaClasses, - TestInternalUtilities, - ) - finally: - reap_children() +def setUpModule(): + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) + unittest.addModuleCleanup(reap_children) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py index 508b739019593d..cfa6003a867daf 100644 --- a/Lib/test/test_queue.py +++ b/Lib/test/test_queue.py @@ -6,6 +6,7 @@ import time import unittest import weakref +from test.support import gc_collect from test.support import import_helper from test.support import threading_helper @@ -419,11 +420,12 @@ class BaseSimpleQueueTest: def setUp(self): self.q = self.type2test() - def feed(self, q, seq, rnd): + def feed(self, q, seq, rnd, sentinel): while True: try: val = seq.pop() except IndexError: + q.put(sentinel) return q.put(val) if rnd.random() > 0.5: @@ -462,11 +464,10 @@ def consume_timeout(self, q, results, sentinel): return results.append(val) - def run_threads(self, n_feeders, n_consumers, q, inputs, - feed_func, consume_func): + def run_threads(self, n_threads, q, inputs, feed_func, consume_func): results = [] sentinel = None - seq = inputs + [sentinel] * n_consumers + seq = inputs.copy() seq.reverse() rnd = random.Random(42) @@ -480,11 +481,11 @@ def wrapper(*args, **kwargs): return wrapper feeders = [threading.Thread(target=log_exceptions(feed_func), - args=(q, seq, rnd)) - for i in range(n_feeders)] + args=(q, seq, rnd, sentinel)) + for i in range(n_threads)] consumers = [threading.Thread(target=log_exceptions(consume_func), args=(q, results, sentinel)) - for i in range(n_consumers)] + for i in range(n_threads)] with threading_helper.start_threads(feeders + consumers): pass @@ -542,7 +543,7 @@ def test_order(self): # Test a pair of concurrent put() and get() q = self.q inputs = list(range(100)) - results = self.run_threads(1, 1, q, inputs, self.feed, self.consume) + results = self.run_threads(1, q, inputs, self.feed, self.consume) # One producer, one consumer => results appended in well-defined order self.assertEqual(results, inputs) @@ -552,7 +553,7 @@ def test_many_threads(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, self.feed, self.consume) + results = self.run_threads(N, q, inputs, self.feed, self.consume) # Multiple consumers without synchronization append the # results in random order @@ -563,7 +564,7 @@ def test_many_threads_nonblock(self): N = 50 q = self.q inputs = list(range(10000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_nonblock) self.assertEqual(sorted(results), inputs) @@ -573,7 +574,7 @@ def test_many_threads_timeout(self): N = 50 q = self.q inputs = list(range(1000)) - results = self.run_threads(N, N, q, inputs, + results = self.run_threads(N, q, inputs, self.feed, self.consume_timeout) self.assertEqual(sorted(results), inputs) @@ -590,6 +591,7 @@ class C: q.put(C()) for i in range(N): wr = weakref.ref(q.get()) + gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index 57da0e15a756b6..8dc62a933e872e 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -438,6 +438,7 @@ def f(): f() def test_3611(self): + import gc # A re-raised exception in a __del__ caused the __context__ # to be cleared class C: @@ -451,9 +452,11 @@ def f(): x = C() try: try: - x.x + f.x except AttributeError: + # make x.__del__ trigger del x + gc.collect() # For PyPy or other GCs. raise TypeError except Exception as e: self.assertNotEqual(e.__context__, None) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 66908868a6e9ef..5354eddab6958e 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -57,6 +57,11 @@ def __hash__(self): self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4) self.assertRaises(TypeError, type(self.gen), []) + def test_seed_no_mutate_bug_44018(self): + a = bytearray(b'1234') + self.gen.seed(a) + self.assertEqual(a, bytearray(b'1234')) + @unittest.mock.patch('random._urandom') # os.urandom def test_seed_when_randomness_source_not_found(self, urandom_mock): # Random.seed() uses time.time() when an operating system specific diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 107c0e2e11c7ce..851ad5b7c2f485 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -374,26 +374,47 @@ def test_pickling(self): list(r)) def test_iterator_pickling(self): - testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), - (13, 21, 3), (-2, 2, 2), (2**65, 2**65+2)] + testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), (13, 21, 3), + (-2, 2, 2)] + for M in 2**31, 2**63: + testcases += [ + (M-3, M-1), (4*M, 4*M+2), + (M-2, M-1, 2), (-M+1, -M, -2), + (1, 2, M-1), (-1, -2, -M), + (1, M-1, M-1), (-1, -M, -M), + ] for proto in range(pickle.HIGHEST_PROTOCOL + 1): for t in testcases: - it = itorg = iter(range(*t)) - data = list(range(*t)) - - d = pickle.dumps(it, proto) - it = pickle.loads(d) - self.assertEqual(type(itorg), type(it)) - self.assertEqual(list(it), data) - - it = pickle.loads(d) - try: - next(it) - except StopIteration: - continue + with self.subTest(proto=proto, t=t): + it = itorg = iter(range(*t)) + data = list(range(*t)) + + d = pickle.dumps(it, proto) + it = pickle.loads(d) + self.assertEqual(type(itorg), type(it)) + self.assertEqual(list(it), data) + + it = pickle.loads(d) + try: + next(it) + except StopIteration: + continue + d = pickle.dumps(it, proto) + it = pickle.loads(d) + self.assertEqual(list(it), data[1:]) + + def test_iterator_pickling_overflowing_index(self): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + it = iter(range(2**32 + 2)) + _, _, idx = it.__reduce__() + self.assertEqual(idx, 0) + it.__setstate__(2**32 + 1) # undocumented way to set r->index + _, _, idx = it.__reduce__() + self.assertEqual(idx, 2**32 + 1) d = pickle.dumps(it, proto) it = pickle.loads(d) - self.assertEqual(list(it), data[1:]) + self.assertEqual(next(it), 2**32 + 1) def test_exhausted_iterator_pickling(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index e1b2c794291848..588cc7930c327c 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,5 +1,6 @@ from test.support import (gc_collect, bigmemtest, _2G, - cpython_only, captured_stdout) + cpython_only, captured_stdout, + check_disallow_instantiation) import locale import re import sre_compile @@ -2176,13 +2177,11 @@ def test_flags_repr(self): "re.IGNORECASE|re.DOTALL|re.VERBOSE") self.assertEqual(repr(re.I|re.S|re.X|(1<<20)), "re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000") - self.assertEqual( - repr(~re.I), - "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DOTALL|re.VERBOSE|re.TEMPLATE|re.DEBUG") + self.assertEqual(repr(~re.I), "~re.IGNORECASE") self.assertEqual(repr(~(re.I|re.S|re.X)), - "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG") + "~(re.IGNORECASE|re.DOTALL|re.VERBOSE)") self.assertEqual(repr(~(re.I|re.S|re.X|(1<<20))), - "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG|0xffe00") + "~(re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000)") class ImplementationTest(unittest.TestCase): @@ -2218,11 +2217,10 @@ def test_signedness(self): @cpython_only def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) - self.assertRaises(TypeError, re.Match) - self.assertRaises(TypeError, re.Pattern) + check_disallow_instantiation(self, re.Match) + check_disallow_instantiation(self, re.Pattern) pat = re.compile("") - tp = type(pat.scanner("")) - self.assertRaises(TypeError, tp) + check_disallow_instantiation(self, type(pat.scanner(""))) class ExternalTests(unittest.TestCase): diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index f3e404da6f0b87..59dbef90380053 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -156,11 +156,15 @@ def test_init(self): def test_auto_history_enabled(self): output = run_pty(self.auto_history_script.format(True)) - self.assertIn(b"History length: 1\r\n", output) + # bpo-44949: Sometimes, the newline character is not written at the + # end, so don't expect it in the output. + self.assertIn(b"History length: 1", output) def test_auto_history_disabled(self): output = run_pty(self.auto_history_script.format(False)) - self.assertIn(b"History length: 0\r\n", output) + # bpo-44949: Sometimes, the newline character is not written at the + # end, so don't expect it in the output. + self.assertIn(b"History length: 0", output) def test_nonascii(self): loc = locale.setlocale(locale.LC_CTYPE, None) @@ -251,7 +255,9 @@ def display(substitution, matches, longest_match_length): self.assertIn(b"matches ['t\\xebnt', 't\\xebxt']\r\n", output) expected = br"'[\xefnserted]|t\xebxt[after]'" self.assertIn(b"result " + expected + b"\r\n", output) - self.assertIn(b"history " + expected + b"\r\n", output) + # bpo-45195: Sometimes, the newline character is not written at the + # end, so don't expect it in the output. + self.assertIn(b"history " + expected, output) # We have 2 reasons to skip this test: # - readline: history size was added in 6.0 diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py index 054776ccf4808a..3780feeda30e1b 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -15,11 +15,12 @@ import sysconfig import tempfile import textwrap +import time import unittest from test import libregrtest from test import support from test.support import os_helper -from test.libregrtest import utils +from test.libregrtest import utils, setup Py_DEBUG = hasattr(sys, 'gettotalrefcount') @@ -414,7 +415,7 @@ def parse_executed_tests(self, output): def check_executed_tests(self, output, tests, skipped=(), failed=(), env_changed=(), omitted=(), - rerun=(), no_test_ran=(), + rerun={}, no_test_ran=(), randomize=False, interrupted=False, fail_env_changed=False): if isinstance(tests, str): @@ -427,8 +428,6 @@ def check_executed_tests(self, output, tests, skipped=(), failed=(), env_changed = [env_changed] if isinstance(omitted, str): omitted = [omitted] - if isinstance(rerun, str): - rerun = [rerun] if isinstance(no_test_ran, str): no_test_ran = [no_test_ran] @@ -466,12 +465,12 @@ def list_regex(line_format, tests): self.check_line(output, regex) if rerun: - regex = list_regex('%s re-run test%s', rerun) + regex = list_regex('%s re-run test%s', rerun.keys()) self.check_line(output, regex) regex = LOG_PREFIX + r"Re-running failed tests in verbose mode" self.check_line(output, regex) - for test_name in rerun: - regex = LOG_PREFIX + f"Re-running {test_name} in verbose mode" + for name, match in rerun.items(): + regex = LOG_PREFIX + f"Re-running {name} in verbose mode \\(matching: {match}\\)" self.check_line(output, regex) if no_test_ran: @@ -549,11 +548,10 @@ def run_python(self, args, **kw): class CheckActualTests(BaseTestCase): - """ - Check that regrtest appears to find the expected set of tests. - """ - def test_finds_expected_number_of_tests(self): + """ + Check that regrtest appears to find the expected set of tests. + """ args = ['-Wd', '-E', '-bb', '-m', 'test.regrtest', '--list-tests'] output = self.run_python(args) rough_number_of_tests_found = len(output.splitlines()) @@ -1081,15 +1079,18 @@ def test_rerun_fail(self): import unittest class Tests(unittest.TestCase): - def test_bug(self): - # test always fail + def test_succeed(self): + return + + def test_fail_always(self): + # test that always fails self.fail("bug") """) testname = self.create_test(code=code) output = self.run_tests("-w", testname, exitcode=2) self.check_executed_tests(output, [testname], - failed=testname, rerun=testname) + failed=testname, rerun={testname: "test_fail_always"}) def test_rerun_success(self): # FAILURE then SUCCESS @@ -1098,7 +1099,8 @@ def test_rerun_success(self): import unittest class Tests(unittest.TestCase): - failed = False + def test_succeed(self): + return def test_fail_once(self): if not hasattr(builtins, '_test_failed'): @@ -1109,7 +1111,7 @@ def test_fail_once(self): output = self.run_tests("-w", testname, exitcode=0) self.check_executed_tests(output, [testname], - rerun=testname) + rerun={testname: "test_fail_once"}) def test_no_tests_ran(self): code = textwrap.dedent(""" @@ -1298,6 +1300,14 @@ def test_threading_excepthook(self): self.assertIn("Warning -- Uncaught thread exception", output) self.assertIn("Exception: bug in thread", output) + def test_unicode_guard_env(self): + guard = os.environ.get(setup.UNICODE_GUARD_ENV) + self.assertIsNotNone(guard, f"{setup.UNICODE_GUARD_ENV} not set") + if guard != "\N{SMILING FACE WITH SUNGLASSES}": + # Skip to signify that the env var value was changed by the user; + # possibly to something ASCII to work around Unicode issues. + self.skipTest("Modified guard") + def test_cleanup(self): dirname = os.path.join(self.tmptestdir, "test_python_123") os.mkdir(dirname) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index d909e316b7fd65..f2642c6ba181db 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -174,8 +174,5 @@ def __getitem__(self, key): limits) -def test_main(verbose=None): - support.run_unittest(ResourceTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py index ee3019d8782d17..1f7a6ed3f639e0 100644 --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -81,17 +81,41 @@ def test_attr_matches(self): if x.startswith('s')]) def test_excessive_getattr(self): - # Ensure getattr() is invoked no more than once per attribute + """Ensure getattr() is invoked no more than once per attribute""" + + # note the special case for @property methods below; that is why + # 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: calls = 0 + bar = '' + 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) + + def test_property_method_not_called(self): + class Foo: + _bar = 0 + property_called = False + @property def bar(self): - self.calls += 1 - return None + self.property_called = True + return self._bar + f = Foo() completer = rlcompleter.Completer(dict(f=f)) self.assertEqual(completer.complete('f.b', 0), 'f.bar') - self.assertEqual(f.calls, 1) + self.assertFalse(f.property_called) + def test_uncreated_attr(self): # Attributes like properties and slots should be completed even when diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py index 801143f9b5f810..eda4e6a46df437 100644 --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -24,7 +24,7 @@ from urllib.error import URLError import urllib.request from test.support import os_helper -from test.support import findfile, run_unittest +from test.support import findfile from test.support.os_helper import FakePath, TESTFN @@ -1506,22 +1506,5 @@ def characters(self, content): self.assertEqual(self.char_index, 2) -def test_main(): - run_unittest(MakeParserTest, - ParseTest, - SaxutilsTest, - PrepareInputSourceTest, - StringXmlgenTest, - BytesXmlgenTest, - WriterXmlgenTest, - StreamWriterXmlgenTest, - StreamReaderWriterXmlgenTest, - ExpatReaderTest, - ErrorReportingTest, - XmlReaderTest, - LexicalHandlerTest, - CDATAHandlerTest) - - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index 4239b26408ecdf..59d59127982e3c 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -2,6 +2,7 @@ import weakref from test.support import check_syntax_error, cpython_only +from test.support import gc_collect class ScopeTests(unittest.TestCase): @@ -422,6 +423,7 @@ def f2(): for i in range(100): f1() + gc_collect() # For PyPy or other GCs. self.assertEqual(Foo.count, 0) def testClassAndGlobal(self): @@ -754,6 +756,7 @@ def dig(self): tester.dig() ref = weakref.ref(tester) del tester + gc_collect() # For PyPy or other GCs. self.assertIsNone(ref()) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py index 957a633f3230e7..cf32cf2f6a6f8b 100644 --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -88,12 +88,10 @@ def fileno(self): self.assertEqual(select.select([], a, []), ([], a[:5], [])) def test_disallow_instantiation(self): - tp = type(select.poll()) - self.assertRaises(TypeError, tp) + support.check_disallow_instantiation(self, type(select.poll())) if hasattr(select, 'devpoll'): - tp = type(select.devpoll()) - self.assertRaises(TypeError, tp) + support.check_disallow_instantiation(self, type(select.devpoll())) def tearDownModule(): support.reap_children() diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 851b1fc1b9e0c4..fe6b725a4bd050 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -49,7 +49,7 @@ def find_ready_matching(ready, flag): return match -class BaseSelectorTestCase(unittest.TestCase): +class BaseSelectorTestCase: def make_socketpair(self): rd, wr = socketpair() @@ -493,26 +493,28 @@ def test_above_fd_setsize(self): self.assertEqual(NUM_FDS // 2, len(fds)) -class DefaultSelectorTestCase(BaseSelectorTestCase): +class DefaultSelectorTestCase(BaseSelectorTestCase, unittest.TestCase): SELECTOR = selectors.DefaultSelector -class SelectSelectorTestCase(BaseSelectorTestCase): +class SelectSelectorTestCase(BaseSelectorTestCase, unittest.TestCase): SELECTOR = selectors.SelectSelector @unittest.skipUnless(hasattr(selectors, 'PollSelector'), "Test needs selectors.PollSelector") -class PollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): +class PollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, + unittest.TestCase): SELECTOR = getattr(selectors, 'PollSelector', None) @unittest.skipUnless(hasattr(selectors, 'EpollSelector'), "Test needs selectors.EpollSelector") -class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): +class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, + unittest.TestCase): SELECTOR = getattr(selectors, 'EpollSelector', None) @@ -529,7 +531,8 @@ def test_register_file(self): @unittest.skipUnless(hasattr(selectors, 'KqueueSelector'), "Test needs selectors.KqueueSelector)") -class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): +class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, + unittest.TestCase): SELECTOR = getattr(selectors, 'KqueueSelector', None) @@ -561,19 +564,15 @@ def test_empty_select_timeout(self): @unittest.skipUnless(hasattr(selectors, 'DevpollSelector'), "Test needs selectors.DevpollSelector") -class DevpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): +class DevpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, + unittest.TestCase): SELECTOR = getattr(selectors, 'DevpollSelector', None) - -def test_main(): - tests = [DefaultSelectorTestCase, SelectSelectorTestCase, - PollSelectorTestCase, EpollSelectorTestCase, - KqueueSelectorTestCase, DevpollSelectorTestCase] - support.run_unittest(*tests) +def tearDownModule(): support.reap_children() if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index e45f018d2da71b..29bb39df76c8a5 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -362,8 +362,8 @@ def test_init(self): self.assertEqual(s, set(self.word)) s.__init__(self.otherword) self.assertEqual(s, set(self.otherword)) - self.assertRaises(TypeError, s.__init__, s, 2); - self.assertRaises(TypeError, s.__init__, 1); + self.assertRaises(TypeError, s.__init__, s, 2) + self.assertRaises(TypeError, s.__init__, 1) def test_constructor_identity(self): s = self.thetype(range(3)) @@ -593,6 +593,7 @@ def test_weakref(self): p = weakref.proxy(s) self.assertEqual(str(p), str(s)) s = None + support.gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, str, p) def test_rich_compare(self): diff --git a/Lib/test/test_shelve.py b/Lib/test/test_shelve.py index cfdd67c26c5f51..dcb5aefc3bae17 100644 --- a/Lib/test/test_shelve.py +++ b/Lib/test/test_shelve.py @@ -1,4 +1,6 @@ import unittest +import dbm +import os import shelve import glob import pickle @@ -43,12 +45,8 @@ def copy(self): class TestCase(unittest.TestCase): - - fn = "shelftemp.db" - - def tearDown(self): - for f in glob.glob(self.fn+"*"): - os_helper.unlink(f) + dirname = os_helper.TESTFN + fn = os.path.join(os_helper.TESTFN, "shelftemp.db") def test_close(self): d1 = {} @@ -65,29 +63,24 @@ def test_close(self): else: self.fail('Closed shelf should not find a key') - def test_ascii_file_shelf(self): - s = shelve.open(self.fn, protocol=0) + def test_open_template(self, protocol=None): + os.mkdir(self.dirname) + self.addCleanup(os_helper.rmtree, self.dirname) + s = shelve.open(self.fn, protocol=protocol) try: s['key1'] = (1,2,3,4) self.assertEqual(s['key1'], (1,2,3,4)) finally: s.close() + def test_ascii_file_shelf(self): + self.test_open_template(protocol=0) + def test_binary_file_shelf(self): - s = shelve.open(self.fn, protocol=1) - try: - s['key1'] = (1,2,3,4) - self.assertEqual(s['key1'], (1,2,3,4)) - finally: - s.close() + self.test_open_template(protocol=1) def test_proto2_file_shelf(self): - s = shelve.open(self.fn, protocol=2) - try: - s['key1'] = (1,2,3,4) - self.assertEqual(s['key1'], (1,2,3,4)) - finally: - s.close() + self.test_open_template(protocol=2) def test_in_memory_shelf(self): d1 = byteskeydict() @@ -164,63 +157,52 @@ def test_default_protocol(self): with shelve.Shelf({}) as s: self.assertEqual(s._protocol, pickle.DEFAULT_PROTOCOL) -from test import mapping_tests -class TestShelveBase(mapping_tests.BasicTestMappingProtocol): - fn = "shelftemp.db" - counter = 0 - def __init__(self, *args, **kw): - self._db = [] - mapping_tests.BasicTestMappingProtocol.__init__(self, *args, **kw) +class TestShelveBase: type2test = shelve.Shelf + def _reference(self): return {"key1":"value1", "key2":2, "key3":(1,2,3)} + + +class TestShelveInMemBase(TestShelveBase): def _empty_mapping(self): - if self._in_mem: - x= shelve.Shelf(byteskeydict(), **self._args) - else: - self.counter+=1 - x= shelve.open(self.fn+str(self.counter), **self._args) - self._db.append(x) + return shelve.Shelf(byteskeydict(), **self._args) + + +class TestShelveFileBase(TestShelveBase): + counter = 0 + + def _empty_mapping(self): + self.counter += 1 + x = shelve.open(self.base_path + str(self.counter), **self._args) + self.addCleanup(x.close) return x - def tearDown(self): - for db in self._db: - db.close() - self._db = [] - if not self._in_mem: - for f in glob.glob(self.fn+"*"): - os_helper.unlink(f) - -class TestAsciiFileShelve(TestShelveBase): - _args={'protocol':0} - _in_mem = False -class TestBinaryFileShelve(TestShelveBase): - _args={'protocol':1} - _in_mem = False -class TestProto2FileShelve(TestShelveBase): - _args={'protocol':2} - _in_mem = False -class TestAsciiMemShelve(TestShelveBase): - _args={'protocol':0} - _in_mem = True -class TestBinaryMemShelve(TestShelveBase): - _args={'protocol':1} - _in_mem = True -class TestProto2MemShelve(TestShelveBase): - _args={'protocol':2} - _in_mem = True - -def test_main(): - for module in dbm_iterator(): - support.run_unittest( - TestAsciiFileShelve, - TestBinaryFileShelve, - TestProto2FileShelve, - TestAsciiMemShelve, - TestBinaryMemShelve, - TestProto2MemShelve, - TestCase - ) + + def setUp(self): + dirname = os_helper.TESTFN + os.mkdir(dirname) + self.addCleanup(os_helper.rmtree, dirname) + self.base_path = os.path.join(dirname, "shelftemp.db") + self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod) + dbm._defaultmod = self.dbm_mod + + +from test import mapping_tests + +for proto in range(pickle.HIGHEST_PROTOCOL + 1): + bases = (TestShelveInMemBase, mapping_tests.BasicTestMappingProtocol) + name = f'TestProto{proto}MemShelve' + globals()[name] = type(name, bases, + {'_args': {'protocol': proto}}) + bases = (TestShelveFileBase, mapping_tests.BasicTestMappingProtocol) + for dbm_mod in dbm_iterator(): + assert dbm_mod.__name__.startswith('dbm.') + suffix = dbm_mod.__name__[4:] + name = f'TestProto{proto}File_{suffix}Shelve' + globals()[name] = type(name, bases, + {'dbm_mod': dbm_mod, '_args': {'protocol': proto}}) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 493c7e5f9f1379..7669b94ac35a68 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -37,6 +37,7 @@ TESTFN_SRC = TESTFN + "_SRC" TESTFN_DST = TESTFN + "_DST" MACOS = sys.platform.startswith("darwin") +SOLARIS = sys.platform.startswith("sunos") AIX = sys.platform[:3] == 'aix' try: import grp @@ -1150,6 +1151,28 @@ def test_copy_return_value(self): rv = fn(src, os.path.join(dst_dir, 'bar')) self.assertEqual(rv, os.path.join(dst_dir, 'bar')) + def test_copy_dir(self): + self._test_copy_dir(shutil.copy) + + def test_copy2_dir(self): + self._test_copy_dir(shutil.copy2) + + def _test_copy_dir(self, copy_func): + src_dir = self.mkdtemp() + src_file = os.path.join(src_dir, 'foo') + dir2 = self.mkdtemp() + dst = os.path.join(src_dir, 'does_not_exist/') + write_file(src_file, 'foo') + if sys.platform == "win32": + err = PermissionError + else: + err = IsADirectoryError + self.assertRaises(err, copy_func, dir2, src_dir) + + # raise *err* because of src rather than FileNotFoundError because of dst + self.assertRaises(err, copy_func, dir2, dst) + copy_func(src_file, dir2) # should not raise exceptions + ### shutil.copyfile @os_helper.skip_unless_symlink @@ -1249,6 +1272,33 @@ def test_copyfile_same_file(self): # Make sure file is not corrupted. self.assertEqual(read_file(src_file), 'foo') + @unittest.skipIf(MACOS or SOLARIS or _winapi, 'On MACOS, Solaris and Windows the errors are not confusing (though different)') + def test_copyfile_nonexistent_dir(self): + # Issue 43219 + src_dir = self.mkdtemp() + src_file = os.path.join(src_dir, 'foo') + dst = os.path.join(src_dir, 'does_not_exist/') + write_file(src_file, 'foo') + self.assertRaises(FileNotFoundError, shutil.copyfile, src_file, dst) + + def test_copyfile_copy_dir(self): + # Issue 45234 + # test copy() and copyfile() raising proper exceptions when src and/or + # dst are directories + src_dir = self.mkdtemp() + src_file = os.path.join(src_dir, 'foo') + dir2 = self.mkdtemp() + dst = os.path.join(src_dir, 'does_not_exist/') + write_file(src_file, 'foo') + if sys.platform == "win32": + err = PermissionError + else: + err = IsADirectoryError + + self.assertRaises(err, shutil.copyfile, src_dir, dst) + self.assertRaises(err, shutil.copyfile, src_file, src_dir) + self.assertRaises(err, shutil.copyfile, dir2, src_dir) + class TestArchives(BaseTest, unittest.TestCase): diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index daecf196fa1461..c2b5861fc3e9ca 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,5 +1,5 @@ -import enum import errno +import inspect import os import random import signal @@ -34,31 +34,13 @@ def test_enums(self): self.assertIsInstance(sig, signal.Signals) self.assertEqual(sys.platform, "win32") - CheckedSignals = enum._old_convert_( - enum.IntEnum, 'Signals', 'signal', - lambda name: - name.isupper() - and (name.startswith('SIG') and not name.startswith('SIG_')) - or name.startswith('CTRL_'), - source=signal, - ) - enum._test_simple_enum(CheckedSignals, signal.Signals) - - CheckedHandlers = enum._old_convert_( - enum.IntEnum, 'Handlers', 'signal', - lambda name: name in ('SIG_DFL', 'SIG_IGN'), - source=signal, - ) - enum._test_simple_enum(CheckedHandlers, signal.Handlers) - - Sigmasks = getattr(signal, 'Sigmasks', None) - if Sigmasks is not None: - CheckedSigmasks = enum._old_convert_( - enum.IntEnum, 'Sigmasks', 'signal', - lambda name: name in ('SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'), - source=signal, - ) - enum._test_simple_enum(CheckedSigmasks, Sigmasks) + def test_functions_module_attr(self): + # Issue #27718: If __all__ is not defined all non-builtin functions + # should have correct __module__ to be displayed by pydoc. + for name in dir(signal): + value = getattr(signal, name) + if inspect.isroutine(value) and not inspect.isbuiltin(value): + self.assertEqual(value.__module__, 'signal') @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") @@ -899,7 +881,7 @@ def handler(signum, frame): %s - blocked = %r + blocked = %s signum = signal.SIGALRM # child: block and wait the signal diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 9b4ab42a727b4f..fa74e7770ede29 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -79,8 +79,10 @@ def tearDown(self): site.USER_SITE = self.old_site site.PREFIXES = self.old_prefixes sysconfig._CONFIG_VARS = self.original_vars - sysconfig._CONFIG_VARS.clear() - sysconfig._CONFIG_VARS.update(self.old_vars) + # _CONFIG_VARS is None before get_config_vars() is called + if sysconfig._CONFIG_VARS is not None: + sysconfig._CONFIG_VARS.clear() + sysconfig._CONFIG_VARS.update(self.old_vars) def test_makepath(self): # Test makepath() have an absolute path for its first return value diff --git a/Lib/test/test_smtpd.py b/Lib/test/test_smtpd.py index 6303192d1b26cc..d2e150d535ff6c 100644 --- a/Lib/test/test_smtpd.py +++ b/Lib/test/test_smtpd.py @@ -5,8 +5,12 @@ from test.support import warnings_helper import socket import io -import smtpd -import asyncore + +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import smtpd + import asyncore class DummyServer(smtpd.SMTPServer): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index f3d33ab0772dd3..1a60fef8a428b7 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -1,4 +1,3 @@ -import asyncore import base64 import email.mime.text from email.message import EmailMessage @@ -7,7 +6,6 @@ import hashlib import hmac import socket -import smtpd import smtplib import io import re @@ -25,6 +23,12 @@ from test.support import threading_helper from unittest.mock import Mock +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + import smtpd + HOST = socket_helper.HOST if sys.platform == 'darwin': @@ -332,6 +336,16 @@ def testEXPNNotImplemented(self): self.assertEqual(smtp.getreply(), expected) smtp.quit() + def test_issue43124_putcmd_escapes_newline(self): + # see: https://bugs.python.org/issue43124 + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', + timeout=support.LOOPBACK_TIMEOUT) + self.addCleanup(smtp.close) + with self.assertRaises(ValueError) as exc: + smtp.putcmd('helo\nX-INJECTED') + self.assertIn("prohibited newline characters", str(exc.exception)) + smtp.quit() + def testVRFY(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=support.LOOPBACK_TIMEOUT) @@ -413,6 +427,51 @@ def testSendNeedingDotQuote(self): mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END) self.assertEqual(self.output.getvalue(), mexpect) + def test_issue43124_escape_localhostname(self): + # see: https://bugs.python.org/issue43124 + # connect and send mail + m = 'wazzuuup\nlinetwo' + smtp = smtplib.SMTP(HOST, self.port, local_hostname='hi\nX-INJECTED', + timeout=support.LOOPBACK_TIMEOUT) + self.addCleanup(smtp.close) + with self.assertRaises(ValueError) as exc: + smtp.sendmail("hi@me.com", "you@me.com", m) + self.assertIn( + "prohibited newline characters: ehlo hi\\nX-INJECTED", + str(exc.exception), + ) + # XXX (see comment in testSend) + time.sleep(0.01) + smtp.quit() + + debugout = smtpd.DEBUGSTREAM.getvalue() + self.assertNotIn("X-INJECTED", debugout) + + def test_issue43124_escape_options(self): + # see: https://bugs.python.org/issue43124 + # connect and send mail + m = 'wazzuuup\nlinetwo' + smtp = smtplib.SMTP( + HOST, self.port, local_hostname='localhost', + timeout=support.LOOPBACK_TIMEOUT) + + self.addCleanup(smtp.close) + smtp.sendmail("hi@me.com", "you@me.com", m) + with self.assertRaises(ValueError) as exc: + smtp.mail("hi@me.com", ["X-OPTION\nX-INJECTED-1", "X-OPTION2\nX-INJECTED-2"]) + msg = str(exc.exception) + self.assertIn("prohibited newline characters", msg) + self.assertIn("X-OPTION\\nX-INJECTED-1 X-OPTION2\\nX-INJECTED-2", msg) + # XXX (see comment in testSend) + time.sleep(0.01) + smtp.quit() + + debugout = smtpd.DEBUGSTREAM.getvalue() + self.assertNotIn("X-OPTION", debugout) + self.assertNotIn("X-OPTION2", debugout) + self.assertNotIn("X-INJECTED-1", debugout) + self.assertNotIn("X-INJECTED-2", debugout) + def testSendNullSender(self): m = 'A test message' smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', @@ -1112,7 +1171,7 @@ def auth_buggy(challenge=None): finally: smtp.close() - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def testAUTH_CRAM_MD5(self): self.serv.add_feature("AUTH CRAM-MD5") smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', @@ -1121,7 +1180,7 @@ def testAUTH_CRAM_MD5(self): self.assertEqual(resp, (235, b'Authentication Succeeded')) smtp.close() - @hashlib_helper.requires_hashdigest('md5') + @hashlib_helper.requires_hashdigest('md5', openssl=True) def testAUTH_multiple(self): # Test that multiple authentication methods are tried. self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5") diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 3c45278748a941..5c15648b605c67 100755 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -199,7 +199,7 @@ def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDPLITE) self.port = socket_helper.bind_port(self.serv) -class ThreadSafeCleanupTestCase(unittest.TestCase): +class ThreadSafeCleanupTestCase: """Subclass of unittest.TestCase with thread-safe cleanup methods. This subclass protects the addCleanup() and doCleanups() methods @@ -224,7 +224,7 @@ class SocketCANTest(unittest.TestCase): the following commands: # modprobe vcan # ip link add dev vcan0 type vcan - # ifconfig vcan0 up + # ip link set up vcan0 """ interface = 'vcan0' bufsize = 128 @@ -326,9 +326,7 @@ def _testFoo(self): def __init__(self): # Swap the true setup function self.__setUp = self.setUp - self.__tearDown = self.tearDown self.setUp = self._setUp - self.tearDown = self._tearDown def serverExplicitReady(self): """This method allows the server to explicitly indicate that @@ -340,6 +338,7 @@ def serverExplicitReady(self): def _setUp(self): self.wait_threads = threading_helper.wait_threads_exit() self.wait_threads.__enter__() + self.addCleanup(self.wait_threads.__exit__, None, None, None) self.server_ready = threading.Event() self.client_ready = threading.Event() @@ -347,6 +346,11 @@ def _setUp(self): self.queue = queue.Queue(1) self.server_crashed = False + def raise_queued_exception(): + if self.queue.qsize(): + raise self.queue.get() + self.addCleanup(raise_queued_exception) + # Do some munging to start the client test. methodname = self.id() i = methodname.rfind('.') @@ -363,15 +367,7 @@ def _setUp(self): finally: self.server_ready.set() self.client_ready.wait() - - def _tearDown(self): - self.__tearDown() - self.done.wait() - self.wait_threads.__exit__(None, None, None) - - if self.queue.qsize(): - exc = self.queue.get() - raise exc + self.addCleanup(self.done.wait) def clientRun(self, test_func): self.server_ready.wait() @@ -870,6 +866,7 @@ def test_weakref(self): p = proxy(s) self.assertEqual(p.fileno(), s.fileno()) s = None + support.gc_collect() # For PyPy or other GCs. try: p.fileno() except ReferenceError: @@ -1518,9 +1515,9 @@ def testGetaddrinfo(self): infos = socket.getaddrinfo(HOST, 80, socket.AF_INET, socket.SOCK_STREAM) for family, type, _, _, _ in infos: self.assertEqual(family, socket.AF_INET) - self.assertEqual(str(family), 'AF_INET') + self.assertEqual(str(family), 'AddressFamily.AF_INET') self.assertEqual(type, socket.SOCK_STREAM) - self.assertEqual(str(type), 'SOCK_STREAM') + self.assertEqual(str(type), 'SocketKind.SOCK_STREAM') infos = socket.getaddrinfo(HOST, None, 0, socket.SOCK_STREAM) for _, socktype, _, _, _ in infos: self.assertEqual(socktype, socket.SOCK_STREAM) @@ -1794,8 +1791,8 @@ def test_str_for_enums(self): # Make sure that the AF_* and SOCK_* constants have enum-like string # reprs. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - self.assertEqual(str(s.family), 'AF_INET') - self.assertEqual(str(s.type), 'SOCK_STREAM') + self.assertEqual(str(s.family), 'AddressFamily.AF_INET') + self.assertEqual(str(s.type), 'SocketKind.SOCK_STREAM') def test_socket_consistent_sock_type(self): SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0) @@ -1942,41 +1939,6 @@ def test_socket_fileno_requires_socket_fd(self): fileno=afile.fileno()) self.assertEqual(cm.exception.errno, errno.ENOTSOCK) - def test_addressfamily_enum(self): - import _socket, enum - CheckedAddressFamily = enum._old_convert_( - enum.IntEnum, 'AddressFamily', 'socket', - lambda C: C.isupper() and C.startswith('AF_'), - source=_socket, - ) - enum._test_simple_enum(CheckedAddressFamily, socket.AddressFamily) - - def test_socketkind_enum(self): - import _socket, enum - CheckedSocketKind = enum._old_convert_( - enum.IntEnum, 'SocketKind', 'socket', - lambda C: C.isupper() and C.startswith('SOCK_'), - source=_socket, - ) - enum._test_simple_enum(CheckedSocketKind, socket.SocketKind) - - def test_msgflag_enum(self): - import _socket, enum - CheckedMsgFlag = enum._old_convert_( - enum.IntFlag, 'MsgFlag', 'socket', - lambda C: C.isupper() and C.startswith('MSG_'), - source=_socket, - ) - enum._test_simple_enum(CheckedMsgFlag, socket.MsgFlag) - - def test_addressinfo_enum(self): - import _socket, enum - CheckedAddressInfo = enum._old_convert_( - enum.IntFlag, 'AddressInfo', 'socket', - lambda C: C.isupper() and C.startswith('AI_'), - source=_socket) - enum._test_simple_enum(CheckedAddressInfo, socket.AddressInfo) - @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.') class BasicCANTest(unittest.TestCase): @@ -2085,7 +2047,6 @@ def testSendFrame(self): cf, addr = self.s.recvfrom(self.bufsize) self.assertEqual(self.cf, cf) self.assertEqual(addr[0], self.interface) - self.assertEqual(addr[1], socket.AF_CAN) def _testSendFrame(self): self.cf = self.build_can_frame(0x00, b'\x01\x02\x03\x04\x05') @@ -4452,7 +4413,7 @@ class RecvmsgIntoSCMRightsStreamTest(RecvmsgIntoMixin, SCMRightsTest, # threads alive during the test so that the OS cannot deliver the # signal to the wrong one. -class InterruptedTimeoutBase(unittest.TestCase): +class InterruptedTimeoutBase: # Base class for interrupted send/receive tests. Installs an # empty handler for SIGALRM and removes it on teardown, along with # any scheduled alarms. @@ -6211,6 +6172,7 @@ def _testWithTimeoutTriggeredSend(self): def testWithTimeoutTriggeredSend(self): conn = self.accept_conn() conn.recv(88192) + time.sleep(1) # errors @@ -6447,6 +6409,12 @@ def test_length_restriction(self): sock.bind(("type", "n" * 64)) +@unittest.skipUnless(sys.platform == 'darwin', 'macOS specific test') +class TestMacOSTCPFlags(unittest.TestCase): + def test_tcp_keepalive(self): + self.assertTrue(socket.TCP_KEEPALIVE) + + @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") class TestMSWindowsTCPFlags(unittest.TestCase): knownTCPFlags = { @@ -6524,13 +6492,6 @@ def test_dualstack_ipv6_family(self): class CreateServerFunctionalTest(unittest.TestCase): timeout = support.LOOPBACK_TIMEOUT - def setUp(self): - self.thread = None - - def tearDown(self): - if self.thread is not None: - self.thread.join(self.timeout) - def echo_server(self, sock): def run(sock): with sock: @@ -6544,8 +6505,9 @@ def run(sock): event = threading.Event() sock.settimeout(self.timeout) - self.thread = threading.Thread(target=run, args=(sock, )) - self.thread.start() + thread = threading.Thread(target=run, args=(sock, )) + thread.start() + self.addCleanup(thread.join, self.timeout) event.set() def echo_client(self, addr, family): @@ -6633,83 +6595,10 @@ def close_fds(fds): self.assertEqual(data, str(index).encode()) -def test_main(): - tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, - TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, - UDPTimeoutTest, CreateServerTest, CreateServerFunctionalTest, - SendRecvFdsTests] - - tests.extend([ - NonBlockingTCPTests, - FileObjectClassTestCase, - UnbufferedFileObjectClassTestCase, - LineBufferedFileObjectClassTestCase, - SmallBufferedFileObjectClassTestCase, - UnicodeReadFileObjectClassTestCase, - UnicodeWriteFileObjectClassTestCase, - UnicodeReadWriteFileObjectClassTestCase, - NetworkConnectionNoServer, - NetworkConnectionAttributesTest, - NetworkConnectionBehaviourTest, - ContextManagersTest, - InheritanceTest, - NonblockConstantTest - ]) - tests.append(BasicSocketPairTest) - tests.append(TestUnixDomain) - tests.append(TestLinuxAbstractNamespace) - tests.extend([TIPCTest, TIPCThreadableTest]) - tests.extend([BasicCANTest, CANTest]) - tests.extend([BasicRDSTest, RDSTest]) - tests.append(LinuxKernelCryptoAPI) - tests.append(BasicQIPCRTRTest) - tests.extend([ - BasicVSOCKTest, - ThreadedVSOCKSocketStreamTest, - ]) - tests.append(BasicBluetoothTest) - tests.extend([ - CmsgMacroTests, - SendmsgUDPTest, - RecvmsgUDPTest, - RecvmsgIntoUDPTest, - SendmsgUDP6Test, - RecvmsgUDP6Test, - RecvmsgRFC3542AncillaryUDP6Test, - RecvmsgIntoRFC3542AncillaryUDP6Test, - RecvmsgIntoUDP6Test, - SendmsgUDPLITETest, - RecvmsgUDPLITETest, - RecvmsgIntoUDPLITETest, - SendmsgUDPLITE6Test, - RecvmsgUDPLITE6Test, - RecvmsgRFC3542AncillaryUDPLITE6Test, - RecvmsgIntoRFC3542AncillaryUDPLITE6Test, - RecvmsgIntoUDPLITE6Test, - SendmsgTCPTest, - RecvmsgTCPTest, - RecvmsgIntoTCPTest, - SendmsgSCTPStreamTest, - RecvmsgSCTPStreamTest, - RecvmsgIntoSCTPStreamTest, - SendmsgUnixStreamTest, - RecvmsgUnixStreamTest, - RecvmsgIntoUnixStreamTest, - RecvmsgSCMRightsStreamTest, - RecvmsgIntoSCMRightsStreamTest, - # These are slow when setitimer() is not available - InterruptedRecvTimeoutTest, - InterruptedSendTimeoutTest, - TestSocketSharing, - SendfileUsingSendTest, - SendfileUsingSendfileTest, - ]) - tests.append(TestMSWindowsTCPFlags) - +def setUpModule(): thread_info = threading_helper.threading_setup() - support.run_unittest(*tests) - threading_helper.threading_cleanup(*thread_info) + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 00d5eff81537d1..873db6403d1a00 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -13,7 +13,6 @@ import select import time import datetime -import enum import gc import os import errno @@ -21,7 +20,6 @@ import urllib.request import threading import traceback -import asyncore import weakref import platform import sysconfig @@ -31,6 +29,11 @@ except ImportError: ctypes = None +import warnings +with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + import asyncore + ssl = import_helper.import_module("ssl") import _ssl @@ -62,7 +65,7 @@ def data_file(*name): # The custom key and certificate files used in test_ssl are generated # using Lib/test/make_ssl_certs.py. -# Other certificates are simply fetched from the Internet servers they +# Other certificates are simply fetched from the internet servers they # are meant to authenticate. CERTFILE = data_file("keycert.pem") @@ -358,11 +361,7 @@ def test_ssl_types(self): with self.subTest(ssl_type=ssl_type): with self.assertRaisesRegex(TypeError, "immutable type"): ssl_type.value = None - with self.assertRaisesRegex( - TypeError, - "cannot create '_ssl.Certificate' instances" - ): - _ssl.Certificate() + support.check_disallow_instantiation(self, _ssl.Certificate) def test_private_init(self): with self.assertRaisesRegex(TypeError, "public constructor"): @@ -373,7 +372,7 @@ def test_str_for_enums(self): # Make sure that the PROTOCOL_* constants have enum-like string # reprs. proto = ssl.PROTOCOL_TLS_CLIENT - self.assertEqual(str(proto), 'PROTOCOL_TLS_CLIENT') + self.assertEqual(str(proto), '_SSLMethod.PROTOCOL_TLS_CLIENT') ctx = ssl.SSLContext(proto) self.assertIs(ctx.protocol, proto) @@ -540,7 +539,11 @@ def test_openssl_version(self): self.assertLessEqual(status, 15) libressl_ver = f"LibreSSL {major:d}" - openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" + if major >= 3: + # 3.x uses 0xMNN00PP0L + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{patch:d}" + else: + openssl_ver = f"OpenSSL {major:d}.{minor:d}.{fix:d}" self.assertTrue( s.startswith((openssl_ver, libressl_ver)), (s, t, hex(n)) @@ -584,6 +587,54 @@ def test_timeout(self): with test_wrap_socket(s) as ss: self.assertEqual(timeout, ss.gettimeout()) + def test_openssl111_deprecations(self): + options = [ + ssl.OP_NO_TLSv1, + ssl.OP_NO_TLSv1_1, + ssl.OP_NO_TLSv1_2, + ssl.OP_NO_TLSv1_3 + ] + protocols = [ + ssl.PROTOCOL_TLSv1, + ssl.PROTOCOL_TLSv1_1, + ssl.PROTOCOL_TLSv1_2, + ssl.PROTOCOL_TLS + ] + versions = [ + ssl.TLSVersion.SSLv3, + ssl.TLSVersion.TLSv1, + ssl.TLSVersion.TLSv1_1, + ] + + for option in options: + with self.subTest(option=option): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + with self.assertWarns(DeprecationWarning) as cm: + ctx.options |= option + self.assertEqual( + 'ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated', + str(cm.warning) + ) + + for protocol in protocols: + with self.subTest(protocol=protocol): + with self.assertWarns(DeprecationWarning) as cm: + ssl.SSLContext(protocol) + self.assertEqual( + f'ssl.{protocol.name} is deprecated', + str(cm.warning) + ) + + for version in versions: + with self.subTest(version=version): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + with self.assertWarns(DeprecationWarning) as cm: + ctx.minimum_version = version + self.assertEqual( + f'ssl.{version!s} is deprecated', + str(cm.warning) + ) + @ignore_deprecation def test_errors_sslwrap(self): sock = socket.socket() @@ -1754,7 +1805,7 @@ class MySSLObject(ssl.SSLObject): with ctx.wrap_socket(socket.socket(), server_side=True) as sock: self.assertIsInstance(sock, MySSLSocket) - obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO()) + obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), server_side=True) self.assertIsInstance(obj, MySSLObject) def test_num_tickest(self): @@ -2296,6 +2347,7 @@ def test_bio_read_write_data(self): self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap) +@support.requires_resource('network') class NetworkedTests(unittest.TestCase): def test_timeout_connect_ex(self): @@ -2399,9 +2451,14 @@ def wrap_conn(self): self.server.conn_errors.append(str(e)) if self.server.chatty: handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") - self.running = False - self.server.stop() - self.close() + + # bpo-44229, bpo-43855, bpo-44237, and bpo-33450: + # Ignore spurious EPROTOTYPE returned by write() on macOS. + # See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ + if e.errno != errno.EPROTOTYPE and sys.platform != "darwin": + self.running = False + self.server.stop() + self.close() return False else: self.server.shared_ciphers.append(self.sslconn.shared_ciphers()) @@ -2888,24 +2945,29 @@ def test_echo(self): server_context=client_context, chatty=True, connectionchatty=True, sni_name=hostname) - self.assertIn('called a function you should not call', - str(e.exception)) + self.assertIn( + 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context', + str(e.exception) + ) with self.subTest(client=ssl.PROTOCOL_TLS_SERVER, server=ssl.PROTOCOL_TLS_SERVER): with self.assertRaises(ssl.SSLError) as e: server_params_test(client_context=server_context, server_context=server_context, chatty=True, connectionchatty=True) - self.assertIn('called a function you should not call', - str(e.exception)) + self.assertIn( + 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context', + str(e.exception) + ) with self.subTest(client=ssl.PROTOCOL_TLS_CLIENT, server=ssl.PROTOCOL_TLS_CLIENT): with self.assertRaises(ssl.SSLError) as e: server_params_test(client_context=server_context, server_context=client_context, chatty=True, connectionchatty=True) - self.assertIn('called a function you should not call', - str(e.exception)) + self.assertIn( + 'Cannot create a client socket with a PROTOCOL_TLS_SERVER context', + str(e.exception)) def test_getpeercert(self): if support.verbose: @@ -3066,7 +3128,7 @@ def test_dual_rsa_ecc(self): client_context.load_verify_locations(SIGNING_CA) # TODO: fix TLSv1.3 once SSLContext can restrict signature # algorithms. - client_context.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 # only ECDSA certs client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA') hostname = SIGNED_CERTFILE_ECC_HOSTNAME @@ -3194,7 +3256,8 @@ def test_wrong_cert_tls13(self): ) with server, \ client_context.wrap_socket(socket.socket(), - server_hostname=hostname) as s: + server_hostname=hostname, + suppress_ragged_eofs=False) as s: # TLS 1.3 perform client cert exchange after handshake s.connect((HOST, server.port)) try: @@ -3211,13 +3274,7 @@ def test_wrong_cert_tls13(self): if support.verbose: sys.stdout.write("\nsocket.error is %r\n" % e) else: - if sys.platform == "win32": - self.skipTest( - "Ignoring failed test_wrong_cert_tls13 test case. " - "The test is flaky on Windows, see bpo-43921." - ) - else: - self.fail("Use of invalid cert should have failed!") + self.fail("Use of invalid cert should have failed!") def test_rude_shutdown(self): """A brutal shutdown of an SSL server should raise an OSError @@ -3817,7 +3874,7 @@ def test_do_handshake_enotconn(self): def test_no_shared_ciphers(self): client_context, server_context, hostname = testing_context() # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test - client_context.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 # Force different suites on client and server client_context.set_ciphers("AES128") server_context.set_ciphers("AES256") @@ -4032,10 +4089,10 @@ def test_dh_params(self): # Check we can get a connection with ephemeral Diffie-Hellman client_context, server_context, hostname = testing_context() # test scenario needs TLS <= 1.2 - client_context.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 server_context.load_dh_params(DHFILE) server_context.set_ciphers("kEDH") - server_context.options |= ssl.OP_NO_TLSv1_3 + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 stats = server_params_test(client_context, server_context, chatty=True, connectionchatty=True, sni_name=hostname) @@ -4281,7 +4338,7 @@ def test_sendfile(self): def test_session(self): client_context, server_context, hostname = testing_context() # TODO: sessions aren't compatible with TLSv1.3 yet - client_context.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 # first connection without session stats = server_params_test(client_context, server_context, @@ -4340,8 +4397,8 @@ def test_session_handling(self): client_context2, _, _ = testing_context() # TODO: session reuse does not work with TLSv1.3 - client_context.options |= ssl.OP_NO_TLSv1_3 - client_context2.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 + client_context2.maximum_version = ssl.TLSVersion.TLSv1_2 server = ThreadedEchoServer(context=server_context, chatty=False) with server: @@ -4454,7 +4511,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): server = ThreadedEchoServer(context=server_context, chatty=True) with server: with client_context.wrap_socket(socket.socket(), - server_hostname=hostname) as s: + server_hostname=hostname, + suppress_ragged_eofs=False) as s: s.connect((HOST, server.port)) s.write(b'PHA') # test sometimes fails with EOF error. Test passes as long as @@ -4464,9 +4522,12 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): '(certificate required|EOF occurred)' ): # receive CertificateRequest - self.assertEqual(s.recv(1024), b'OK\n') + data = s.recv(1024) + self.assertEqual(data, b'OK\n') + # send empty Certificate + Finish s.write(b'HASCERT') + # receive alert s.recv(1024) @@ -4761,7 +4822,7 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): def test_msg_callback_tls12(self): client_context, server_context, hostname = testing_context() - client_context.options |= ssl.OP_NO_TLSv1_3 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 msg = [] @@ -4813,156 +4874,7 @@ def sni_cb(sock, servername, ctx): s.connect((HOST, server.port)) -class TestEnumerations(unittest.TestCase): - - def test_tlsversion(self): - class CheckedTLSVersion(enum.IntEnum): - MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED - SSLv3 = _ssl.PROTO_SSLv3 - TLSv1 = _ssl.PROTO_TLSv1 - TLSv1_1 = _ssl.PROTO_TLSv1_1 - TLSv1_2 = _ssl.PROTO_TLSv1_2 - TLSv1_3 = _ssl.PROTO_TLSv1_3 - MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED - enum._test_simple_enum(CheckedTLSVersion, TLSVersion) - - def test_tlscontenttype(self): - class Checked_TLSContentType(enum.IntEnum): - """Content types (record layer) - - See RFC 8446, section B.1 - """ - CHANGE_CIPHER_SPEC = 20 - ALERT = 21 - HANDSHAKE = 22 - APPLICATION_DATA = 23 - # pseudo content types - HEADER = 0x100 - INNER_CONTENT_TYPE = 0x101 - enum._test_simple_enum(Checked_TLSContentType, _TLSContentType) - - def test_tlsalerttype(self): - class Checked_TLSAlertType(enum.IntEnum): - """Alert types for TLSContentType.ALERT messages - - See RFC 8466, section B.2 - """ - CLOSE_NOTIFY = 0 - UNEXPECTED_MESSAGE = 10 - BAD_RECORD_MAC = 20 - DECRYPTION_FAILED = 21 - RECORD_OVERFLOW = 22 - DECOMPRESSION_FAILURE = 30 - HANDSHAKE_FAILURE = 40 - NO_CERTIFICATE = 41 - BAD_CERTIFICATE = 42 - UNSUPPORTED_CERTIFICATE = 43 - CERTIFICATE_REVOKED = 44 - CERTIFICATE_EXPIRED = 45 - CERTIFICATE_UNKNOWN = 46 - ILLEGAL_PARAMETER = 47 - UNKNOWN_CA = 48 - ACCESS_DENIED = 49 - DECODE_ERROR = 50 - DECRYPT_ERROR = 51 - EXPORT_RESTRICTION = 60 - PROTOCOL_VERSION = 70 - INSUFFICIENT_SECURITY = 71 - INTERNAL_ERROR = 80 - INAPPROPRIATE_FALLBACK = 86 - USER_CANCELED = 90 - NO_RENEGOTIATION = 100 - MISSING_EXTENSION = 109 - UNSUPPORTED_EXTENSION = 110 - CERTIFICATE_UNOBTAINABLE = 111 - UNRECOGNIZED_NAME = 112 - BAD_CERTIFICATE_STATUS_RESPONSE = 113 - BAD_CERTIFICATE_HASH_VALUE = 114 - UNKNOWN_PSK_IDENTITY = 115 - CERTIFICATE_REQUIRED = 116 - NO_APPLICATION_PROTOCOL = 120 - enum._test_simple_enum(Checked_TLSAlertType, _TLSAlertType) - - def test_tlsmessagetype(self): - class Checked_TLSMessageType(enum.IntEnum): - """Message types (handshake protocol) - - See RFC 8446, section B.3 - """ - HELLO_REQUEST = 0 - CLIENT_HELLO = 1 - SERVER_HELLO = 2 - HELLO_VERIFY_REQUEST = 3 - NEWSESSION_TICKET = 4 - END_OF_EARLY_DATA = 5 - HELLO_RETRY_REQUEST = 6 - ENCRYPTED_EXTENSIONS = 8 - CERTIFICATE = 11 - SERVER_KEY_EXCHANGE = 12 - CERTIFICATE_REQUEST = 13 - SERVER_DONE = 14 - CERTIFICATE_VERIFY = 15 - CLIENT_KEY_EXCHANGE = 16 - FINISHED = 20 - CERTIFICATE_URL = 21 - CERTIFICATE_STATUS = 22 - SUPPLEMENTAL_DATA = 23 - KEY_UPDATE = 24 - NEXT_PROTO = 67 - MESSAGE_HASH = 254 - CHANGE_CIPHER_SPEC = 0x0101 - enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType) - - def test_sslmethod(self): - Checked_SSLMethod = enum._old_convert_( - enum.IntEnum, '_SSLMethod', 'ssl', - lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23', - source=ssl._ssl, - ) - enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod) - - def test_options(self): - CheckedOptions = enum._old_convert_( - enum.FlagEnum, 'Options', 'ssl', - lambda name: name.startswith('OP_'), - source=ssl._ssl, - ) - enum._test_simple_enum(CheckedOptions, ssl.Options) - - - def test_alertdescription(self): - CheckedAlertDescription = enum._old_convert_( - enum.IntEnum, 'AlertDescription', 'ssl', - lambda name: name.startswith('ALERT_DESCRIPTION_'), - source=ssl._ssl, - ) - enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription) - - def test_sslerrornumber(self): - Checked_SSLMethod = enum._old_convert_( - enum.IntEnum, '_SSLMethod', 'ssl', - lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23', - source=ssl._ssl, - ) - enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod) - - def test_verifyflags(self): - CheckedVerifyFlags = enum._old_convert_( - enum.FlagEnum, 'VerifyFlags', 'ssl', - lambda name: name.startswith('VERIFY_'), - source=ssl._ssl, - ) - enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags) - - def test_verifymode(self): - CheckedVerifyMode = enum._old_convert_( - enum.IntEnum, 'VerifyMode', 'ssl', - lambda name: name.startswith('CERT_'), - source=ssl._ssl, - ) - enum._test_simple_enum(CheckedVerifyMode, ssl.VerifyMode) - -def test_main(verbose=False): +def setUpModule(): if support.verbose: plats = { 'Mac': platform.mac_ver, @@ -4993,20 +4905,9 @@ def test_main(verbose=False): if not os.path.exists(filename): raise support.TestFailed("Can't read certificate file %r" % filename) - tests = [ - ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests, - SSLObjectTests, SimpleBackgroundTests, ThreadedTests, - TestPostHandshakeAuth, TestSSLDebug - ] - - if support.is_resource_enabled('network'): - tests.append(NetworkedTests) - thread_info = threading_helper.threading_setup() - try: - support.run_unittest(*tests) - finally: - threading_helper.threading_cleanup(*thread_info) + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 70d269dea732de..2853b1b2b2f4f6 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1247,20 +1247,14 @@ def test_empty_data(self): # Override test for empty data. for data in ([], (), iter([])): self.assertEqual(self.func(data), (int, Fraction(0), 0)) - self.assertEqual(self.func(data, 23), (int, Fraction(23), 0)) - self.assertEqual(self.func(data, 2.3), (float, Fraction(2.3), 0)) def test_ints(self): self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]), (int, Fraction(60), 8)) - self.assertEqual(self.func([4, 2, 3, -8, 7], 1000), - (int, Fraction(1008), 5)) def test_floats(self): self.assertEqual(self.func([0.25]*20), (float, Fraction(5.0), 20)) - self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5), - (float, Fraction(3.125), 4)) def test_fractions(self): self.assertEqual(self.func([Fraction(1, 1000)]*500), @@ -1281,14 +1275,6 @@ def test_compare_with_math_fsum(self): data = [random.uniform(-100, 1000) for _ in range(1000)] self.assertApproxEqual(float(self.func(data)[1]), math.fsum(data), rel=2e-16) - def test_start_argument(self): - # Test that the optional start argument works correctly. - data = [random.uniform(1, 1000) for _ in range(100)] - t = self.func(data)[1] - self.assertEqual(t+42, self.func(data, 42)[1]) - self.assertEqual(t-23, self.func(data, -23)[1]) - self.assertEqual(t+Fraction(1e20), self.func(data, 1e20)[1]) - def test_strings_fail(self): # Sum of strings should fail. self.assertRaises(TypeError, self.func, [1, 2, 3], '999') @@ -1911,10 +1897,13 @@ def test_none_data(self): def test_counter_data(self): # Test that a Counter is treated like any other iterable. - data = collections.Counter([1, 1, 1, 2]) - # Since the keys of the counter are treated as data points, not the - # counts, this should return the first mode encountered, 1 - self.assertEqual(self.func(data), 1) + # We're making sure mode() first calls iter() on its input. + # The concern is that a Counter of a Counter returns the original + # unchanged rather than counting its keys. + c = collections.Counter(a=1, b=2) + # If iter() is called, mode(c) loops over the keys, ['a', 'b'], + # all the counts will be 1, and the first encountered mode is 'a'. + self.assertEqual(self.func(c), 'a') class TestMultiMode(unittest.TestCase): @@ -2077,6 +2066,13 @@ def test_decimals(self): self.assertEqual(result, exact) self.assertIsInstance(result, Decimal) + def test_accuracy_bug_20499(self): + data = [0, 0, 1] + exact = 2 / 9 + result = self.func(data) + self.assertEqual(result, exact) + self.assertIsInstance(result, float) + class TestVariance(VarianceStdevMixin, NumericTestCase, UnivariateTypeMixin): # Tests for sample variance. @@ -2117,6 +2113,13 @@ def test_center_not_at_mean(self): self.assertEqual(self.func(data), 0.5) self.assertEqual(self.func(data, xbar=2.0), 1.0) + def test_accuracy_bug_20499(self): + data = [0, 0, 2] + exact = 4 / 3 + result = self.func(data) + self.assertEqual(result, exact) + self.assertIsInstance(result, float) + class TestPStdev(VarianceStdevMixin, NumericTestCase): # Tests for population standard deviation. def setUp(self): @@ -2480,7 +2483,7 @@ def test_results(self): ([1, 2, 3], [21, 22, 23], 20, 1), ([1, 2, 3], [5.1, 5.2, 5.3], 5, 0.1), ]: - intercept, slope = statistics.linear_regression(x, y) + slope, intercept = statistics.linear_regression(x, y) self.assertAlmostEqual(intercept, true_intercept) self.assertAlmostEqual(slope, true_slope) diff --git a/Lib/test/test_strftime.py b/Lib/test/test_strftime.py index ec305e54ff24f0..be43c49e40aa50 100644 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -114,7 +114,7 @@ def strftest1(self, now): ) for e in expectations: - # musn't raise a value error + # mustn't raise a value error try: result = time.strftime(e[0], now) except ValueError as error: diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index f0f0e6f6069da7..7bb049296912b9 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -3022,6 +3022,7 @@ def test_leak_fast_process_del_killed(self): pid = p.pid with warnings_helper.check_warnings(('', ResourceWarning)): p = None + support.gc_collect() # For PyPy or other GCs. os.kill(pid, signal.SIGKILL) if mswindows: diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 55d78b733353d2..79290986c494d5 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -11,6 +11,8 @@ import textwrap import time import unittest +import warnings + from test import support from test.support import import_helper from test.support import os_helper @@ -22,6 +24,33 @@ class TestSupport(unittest.TestCase): + @classmethod + def setUpClass(cls): + orig_filter_len = len(warnings.filters) + cls._warnings_helper_token = support.ignore_deprecations_from( + "test.support.warnings_helper", like=".*used in test_support.*" + ) + cls._test_support_token = support.ignore_deprecations_from( + "test.test_support", like=".*You should NOT be seeing this.*" + ) + assert len(warnings.filters) == orig_filter_len + 2 + + @classmethod + def tearDownClass(cls): + orig_filter_len = len(warnings.filters) + support.clear_ignored_deprecations( + cls._warnings_helper_token, + cls._test_support_token, + ) + assert len(warnings.filters) == orig_filter_len - 2 + + def test_ignored_deprecations_are_silent(self): + """Test support.ignore_deprecations_from() silences warnings""" + with warnings.catch_warnings(record=True) as warning_objs: + warnings_helper._warn_about_deprecation() + warnings.warn("You should NOT be seeing this.", DeprecationWarning) + messages = [str(w.message) for w in warning_objs] + self.assertEqual(len(messages), 0, messages) def test_import_module(self): import_helper.import_module("ftplib") @@ -292,8 +321,8 @@ def test_check_syntax_error(self): def test_CleanImport(self): import importlib - with import_helper.CleanImport("asyncore"): - importlib.import_module("asyncore") + with import_helper.CleanImport("pprint"): + importlib.import_module("pprint") def test_DirsOnSysPath(self): with import_helper.DirsOnSysPath('foo', 'bar'): @@ -680,9 +709,5 @@ def test_print_warning(self): # SuppressCrashReport -def test_main(): - tests = [TestSupport] - support.run_unittest(*tests) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 0a910bcf5bd771..b5bebb3d0bdfa1 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -59,6 +59,10 @@ Traceback (most recent call last): SyntaxError: cannot assign to __debug__ +>>> del __debug__ +Traceback (most recent call last): +SyntaxError: cannot delete __debug__ + >>> f() = 1 Traceback (most recent call last): SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='? @@ -93,7 +97,7 @@ >>> ... = 1 Traceback (most recent call last): -SyntaxError: cannot assign to Ellipsis here. Maybe you meant '==' instead of '='? +SyntaxError: cannot assign to ellipsis here. Maybe you meant '==' instead of '='? >>> `1` = 1 Traceback (most recent call last): @@ -140,6 +144,26 @@ Traceback (most recent call last): SyntaxError: cannot assign to conditional expression +>>> a = 42 if True +Traceback (most recent call last): +SyntaxError: expected 'else' after 'if' expression + +>>> a = (42 if True) +Traceback (most recent call last): +SyntaxError: expected 'else' after 'if' expression + +>>> a = [1, 42 if True, 4] +Traceback (most recent call last): +SyntaxError: expected 'else' after 'if' expression + +>>> if True: +... print("Hello" +... +... if 2: +... print(123)) +Traceback (most recent call last): +SyntaxError: invalid syntax + >>> True = True = 3 Traceback (most recent call last): SyntaxError: cannot assign to True @@ -267,7 +291,7 @@ SyntaxError: invalid syntax. Perhaps you forgot a comma? # Make sure soft keywords constructs don't raise specialized -# errors regarding missing commas +# errors regarding missing commas or other spezialiced errors >>> match x: ... y = 3 @@ -280,6 +304,24 @@ Traceback (most recent call last): SyntaxError: invalid syntax +>>> match x: +... case $: +... ... +Traceback (most recent call last): +SyntaxError: invalid syntax + +>>> match ...: +... case {**rest, "key": value}: +... ... +Traceback (most recent call last): +SyntaxError: invalid syntax + +>>> match ...: +... case {**_}: +... ... +Traceback (most recent call last): +SyntaxError: invalid syntax + From compiler_complex_args(): >>> def f(None=1): @@ -458,28 +500,39 @@ ... 290, 291, 292, 293, 294, 295, 296, 297, 298, 299) # doctest: +ELLIPSIS (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ..., 297, 298, 299) -# >>> f(lambda x: x[0] = 3) -# Traceback (most recent call last): -# SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +>>> f(lambda x: x[0] = 3) +Traceback (most recent call last): +SyntaxError: expression cannot contain assignment, perhaps you meant "=="? + +# Check that this error doesn't trigger for names: +>>> f(a={x: for x in {}}) +Traceback (most recent call last): +SyntaxError: invalid syntax The grammar accepts any test (basically, any expression) in the keyword slot of a call site. Test a few different options. -# >>> f(x()=2) -# Traceback (most recent call last): -# SyntaxError: expression cannot contain assignment, perhaps you meant "=="? -# >>> f(a or b=1) -# Traceback (most recent call last): -# SyntaxError: expression cannot contain assignment, perhaps you meant "=="? -# >>> f(x.y=1) -# Traceback (most recent call last): -# SyntaxError: expression cannot contain assignment, perhaps you meant "=="? -# >>> f((x)=2) -# Traceback (most recent call last): -# SyntaxError: expression cannot contain assignment, perhaps you meant "=="? -# >>> f(True=2) -# Traceback (most recent call last): -# SyntaxError: cannot assign to True here. Maybe you meant '==' instead of '='? +>>> f(x()=2) +Traceback (most recent call last): +SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +>>> f(a or b=1) +Traceback (most recent call last): +SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +>>> f(x.y=1) +Traceback (most recent call last): +SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +>>> f((x)=2) +Traceback (most recent call last): +SyntaxError: expression cannot contain assignment, perhaps you meant "=="? +>>> f(True=1) +Traceback (most recent call last): +SyntaxError: cannot assign to True +>>> f(False=1) +Traceback (most recent call last): +SyntaxError: cannot assign to False +>>> f(None=1) +Traceback (most recent call last): +SyntaxError: cannot assign to None >>> f(__debug__=1) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ @@ -582,38 +635,6 @@ ... SyntaxError: 'break' outside loop -This raises a SyntaxError, it used to raise a SystemError. -Context for this change can be found on issue #27514 - -In 2.5 there was a missing exception and an assert was triggered in a debug -build. The number of blocks must be greater than CO_MAXBLOCKS. SF #1565514 - - >>> while 1: - ... while 2: - ... while 3: - ... while 4: - ... while 5: - ... while 6: - ... while 8: - ... while 9: - ... while 10: - ... while 11: - ... while 12: - ... while 13: - ... while 14: - ... while 15: - ... while 16: - ... while 17: - ... while 18: - ... while 19: - ... while 20: - ... while 21: - ... while 22: - ... break - Traceback (most recent call last): - ... - SyntaxError: too many statically nested blocks - Misuse of the nonlocal and global statement can lead to a few unique syntax errors. >>> def f(): @@ -877,6 +898,14 @@ Traceback (most recent call last): SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='? +Custom error messages for try blocks that are not followed by except/finally + + >>> try: + ... x = 34 + ... + Traceback (most recent call last): + SyntaxError: expected 'except' or 'finally' block + Ensure that early = are not matched by the parser as invalid comparisons >>> f(2, 4, x=34); 1 $ 2 Traceback (most recent call last): @@ -1068,7 +1097,7 @@ ... SyntaxError: invalid syntax -Check that an exception group with missing parentheses +Check that an multiple exception types with missing parentheses raise a custom exception >>> try: @@ -1076,21 +1105,21 @@ ... except A, B: ... pass Traceback (most recent call last): - SyntaxError: exception group must be parenthesized + SyntaxError: multiple exception types must be parenthesized >>> try: ... pass ... except A, B, C: ... pass Traceback (most recent call last): - SyntaxError: exception group must be parenthesized + SyntaxError: multiple exception types must be parenthesized >>> try: ... pass ... except A, B, C as blech: ... pass Traceback (most recent call last): - SyntaxError: exception group must be parenthesized + SyntaxError: multiple exception types must be parenthesized >>> try: ... pass @@ -1099,7 +1128,7 @@ ... finally: ... pass Traceback (most recent call last): - SyntaxError: exception group must be parenthesized + SyntaxError: multiple exception types must be parenthesized >>> f(a=23, a=234) @@ -1123,6 +1152,26 @@ Traceback (most recent call last): SyntaxError: cannot assign to f-string expression here. Maybe you meant '==' instead of '='? +>>> (x, y, z=3, d, e) +Traceback (most recent call last): +SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + +>>> [x, y, z=3, d, e] +Traceback (most recent call last): +SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + +>>> [z=3] +Traceback (most recent call last): +SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + +>>> {x, y, z=3, d, e} +Traceback (most recent call last): +SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + +>>> {z=3} +Traceback (most recent call last): +SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='? + >>> from t import x, Traceback (most recent call last): SyntaxError: trailing comma not allowed without surrounding parentheses @@ -1131,6 +1180,13 @@ Traceback (most recent call last): SyntaxError: trailing comma not allowed without surrounding parentheses +# Check that we dont raise the "trailing comma" error if there is more +# input to the left of the valid part that we parsed. + +>>> from t import x,y, and 3 +Traceback (most recent call last): +SyntaxError: invalid syntax + >>> (): int Traceback (most recent call last): SyntaxError: only single target (not tuple) can be annotated @@ -1175,6 +1231,44 @@ >>> import ä £ Traceback (most recent call last): SyntaxError: invalid character '£' (U+00A3) + + Invalid pattern matching constructs: + + >>> match ...: + ... case 42 as _: + ... ... + Traceback (most recent call last): + SyntaxError: cannot use '_' as a target + + >>> match ...: + ... case 42 as 1+2+4: + ... ... + Traceback (most recent call last): + SyntaxError: invalid pattern target + + >>> match ...: + ... case Foo(z=1, y=2, x): + ... ... + Traceback (most recent call last): + SyntaxError: positional patterns follow keyword patterns + + >>> match ...: + ... case Foo(a, z=1, y=2, x): + ... ... + Traceback (most recent call last): + SyntaxError: positional patterns follow keyword patterns + + >>> match ...: + ... case Foo(z=1, x, y=2): + ... ... + Traceback (most recent call last): + SyntaxError: positional patterns follow keyword patterns + + >>> match ...: + ... case C(a=b, c, d=e, f, g=h, i, j=k, ...): + ... ... + Traceback (most recent call last): + SyntaxError: positional patterns follow keyword patterns """ import re @@ -1185,7 +1279,8 @@ class SyntaxTestCase(unittest.TestCase): def _check_error(self, code, errtext, - filename="", mode="exec", subclass=None, lineno=None, offset=None): + filename="", mode="exec", subclass=None, + lineno=None, offset=None, end_lineno=None, end_offset=None): """Check that compiling code raises SyntaxError with errtext. errtest is a regular expression that must be present in the @@ -1205,6 +1300,11 @@ def _check_error(self, code, errtext, self.assertEqual(err.lineno, lineno) if offset is not None: self.assertEqual(err.offset, offset) + if end_lineno is not None: + self.assertEqual(err.end_lineno, end_lineno) + if end_offset is not None: + self.assertEqual(err.end_offset, end_offset) + else: self.fail("compile() did not raise SyntaxError") @@ -1216,7 +1316,7 @@ def test_expression_with_assignment(self): ) def test_curly_brace_after_primary_raises_immediately(self): - self._check_error("f{", "invalid syntax", mode="single") + self._check_error("f{}", "invalid syntax", mode="single") def test_assign_call(self): self._check_error("f() = 1", "assign") @@ -1345,6 +1445,11 @@ def test_kwargs_last3(self): "iterable argument unpacking follows " "keyword argument unpacking") + def test_generator_in_function_call(self): + self._check_error("foo(x, y for y in range(3) for z in range(2) if z , p)", + "Generator expression must be parenthesized", + lineno=1, end_lineno=1, offset=11, end_offset=53) + def test_empty_line_after_linecont(self): # See issue-40847 s = r"""\ @@ -1388,7 +1493,13 @@ def func2(): def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", - lineno=1, offset=9) + lineno=1, offset=8) + self._check_error('1,\\#\n2', + "unexpected character after line continuation character", + lineno=1, offset=4) + self._check_error('\nfgdfgf\n1,\\#\n2\n', + "unexpected character after line continuation character", + lineno=3, offset=4) def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules @@ -1423,6 +1534,56 @@ def case(x): """ compile(code, "", "exec") + def test_multiline_compiler_error_points_to_the_end(self): + self._check_error( + "call(\na=1,\na=1\n)", + "keyword argument repeated", + lineno=3 + ) + + @support.cpython_only + def test_syntax_error_on_deeply_nested_blocks(self): + # This raises a SyntaxError, it used to raise a SystemError. Context + # for this change can be found on issue #27514 + + # In 2.5 there was a missing exception and an assert was triggered in a + # debug build. The number of blocks must be greater than CO_MAXBLOCKS. + # SF #1565514 + + source = """ +while 1: + while 2: + while 3: + while 4: + while 5: + while 6: + while 8: + while 9: + while 10: + while 11: + while 12: + while 13: + while 14: + while 15: + while 16: + while 17: + while 18: + while 19: + while 20: + while 21: + while 22: + break +""" + self._check_error(source, "too many statically nested blocks") + + @support.cpython_only + def test_error_on_parser_stack_overflow(self): + source = "-" * 100000 + "4" + for mode in ["exec", "eval", "single"]: + with self.subTest(mode=mode): + with self.assertRaises(MemoryError): + compile(source, "", mode) + def test_main(): support.run_unittest(SyntaxTestCase) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 1fd5247a91bb51..35da72c432b0af 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -379,7 +379,7 @@ def g456(): self.assertTrue(frame is sys._getframe()) # Verify that the captured thread frame is blocked in g456, called - # from f123. This is a litte tricky, since various bits of + # from f123. This is a little tricky, since various bits of # threading.py are also in the thread's call stack. frame = d.pop(thread_id) stack = traceback.extract_stack(frame) @@ -446,7 +446,7 @@ def g456(): self.assertEqual((None, None, None), d.pop(main_id)) # Verify that the captured thread frame is blocked in g456, called - # from f123. This is a litte tricky, since various bits of + # from f123. This is a little tricky, since various bits of # threading.py are also in the thread's call stack. exc_type, exc_value, exc_tb = d.pop(thread_id) stack = traceback.extract_stack(exc_tb.tb_frame) @@ -1069,6 +1069,20 @@ def __del__(self): self.assertIn("del is broken", report) self.assertTrue(report.endswith("\n")) + def test_original_unraisablehook_exception_qualname(self): + class A: + class B: + class X(Exception): + pass + + with test.support.captured_stderr() as stderr, \ + test.support.swap_attr(sys, 'unraisablehook', + sys.__unraisablehook__): + expected = self.write_unraisable_exc( + A.B.X(), "msg", "obj"); + report = stderr.getvalue() + testName = 'test_original_unraisablehook_exception_qualname' + self.assertIn(f"{testName}..A.B.X", report) def test_original_unraisablehook_wrong_type(self): exc = ValueError(42) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 40dd92ca8e23ac..4f13bbd6bfda2f 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -894,6 +894,29 @@ def func(): (4, 'line'), (4, 'return')]) + def test_nested_ifs_with_and(self): + + def func(): + if A: + if B: + if C: + if D: + return False + else: + return False + elif E and F: + return True + + A = B = True + C = False + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'return')]) + def test_nested_try_if(self): def func(): @@ -976,6 +999,145 @@ class A: (3, 'return'), (1, 'return')]) + def test_try_in_try(self): + def func(): + try: + try: + pass + except Exception as ex: + pass + except Exception: + pass + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'return')]) + + def test_if_in_if_in_if(self): + def func(a=0, p=1, z=1): + if p: + if a: + if z: + pass + else: + pass + else: + pass + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (2, 'return')]) + + def test_early_exit_with(self): + + class C: + def __enter__(self): + return self + def __exit__(*args): + pass + + def func_break(): + for i in (1,2): + with C(): + break + pass + + def func_return(): + with C(): + return + + self.run_and_compare(func_break, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (-5, 'call'), + (-4, 'line'), + (-4, 'return'), + (3, 'line'), + (2, 'line'), + (-3, 'call'), + (-2, 'line'), + (-2, 'return'), + (4, 'line'), + (4, 'return')]) + + self.run_and_compare(func_return, + [(0, 'call'), + (1, 'line'), + (-11, 'call'), + (-10, 'line'), + (-10, 'return'), + (2, 'line'), + (1, 'line'), + (-9, 'call'), + (-8, 'line'), + (-8, 'return'), + (1, 'return')]) + + def test_flow_converges_on_same_line(self): + + def foo(x): + if x: + try: + 1/(x - 1) + except ZeroDivisionError: + pass + return x + + def func(): + for i in range(2): + foo(i) + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (-8, 'call'), + (-7, 'line'), + (-2, 'line'), + (-2, 'return'), + (1, 'line'), + (2, 'line'), + (-8, 'call'), + (-7, 'line'), + (-6, 'line'), + (-5, 'line'), + (-5, 'exception'), + (-4, 'line'), + (-3, 'line'), + (-2, 'line'), + (-2, 'return'), + (1, 'line'), + (1, 'return')]) + + def test_no_tracing_of_named_except_cleanup(self): + + def func(): + x = 0 + try: + 1/x + except ZeroDivisionError as error: + if x: + raise + return "done" + + self.run_and_compare(func, + [(0, 'call'), + (1, 'line'), + (2, 'line'), + (3, 'line'), + (3, 'exception'), + (4, 'line'), + (5, 'line'), + (7, 'line'), + (7, 'return')]) + + class SkipLineEventsTraceTestCase(TraceTestCase): """Repeat the trace tests, but with per-line events skipped""" @@ -1647,6 +1809,7 @@ async def test_no_jump_forwards_into_async_for_block(output): output.append(1) async for i in asynciter([1, 2]): output.append(3) + pass @jump_test(3, 2, [2, 2], (ValueError, 'into')) def test_no_jump_backwards_into_for_block(output): diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index b8b9add36d7665..9408657c918863 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -296,7 +296,17 @@ def test_user_similar(self): base = base.replace(sys.base_prefix, sys.prefix) if HAS_USER_BASE: user_path = get_path(name, 'posix_user') - self.assertEqual(user_path, global_path.replace(base, user, 1)) + expected = global_path.replace(base, user, 1) + # bpo-44860: platlib of posix_user doesn't use sys.platlibdir, + # whereas posix_prefix does. + if name == 'platlib': + # Replace "/lib64/python3.11/site-packages" suffix + # with "/lib/python3.11/site-packages". + py_version_short = sysconfig.get_python_version() + suffix = f'python{py_version_short}/site-packages' + expected = expected.replace(f'/{sys.platlibdir}/{suffix}', + f'/lib/{suffix}') + self.assertEqual(user_path, expected) def test_main(self): # just making sure _main() runs and returns things in the stdout diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 817e6f17997121..e4b5c52bf1eaf4 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -19,6 +19,10 @@ import gzip except ImportError: gzip = None +try: + import zlib +except ImportError: + zlib = None try: import bz2 except ImportError: @@ -687,6 +691,16 @@ def test_parallel_iteration(self): self.assertEqual(m1.offset, m2.offset) self.assertEqual(m1.get_info(), m2.get_info()) + @unittest.skipIf(zlib is None, "requires zlib") + def test_zlib_error_does_not_leak(self): + # bpo-39039: tarfile.open allowed zlib exceptions to bubble up when + # parsing certain types of invalid data + with unittest.mock.patch("tarfile.TarInfo.fromtarfile") as mock: + mock.side_effect = zlib.error + with self.assertRaises(tarfile.ReadError): + tarfile.open(self.tarname) + + class MiscReadTest(MiscReadTestBase, unittest.TestCase): test_fail_comp = None @@ -1706,15 +1720,30 @@ def test_create_taropen_pathlike_name(self): class GzipCreateTest(GzipTest, CreateTest): - pass + + def test_create_with_compresslevel(self): + with tarfile.open(tmpname, self.mode, compresslevel=1) as tobj: + tobj.add(self.file_path) + with tarfile.open(tmpname, 'r:gz', compresslevel=1) as tobj: + pass class Bz2CreateTest(Bz2Test, CreateTest): - pass + + def test_create_with_compresslevel(self): + with tarfile.open(tmpname, self.mode, compresslevel=1) as tobj: + tobj.add(self.file_path) + with tarfile.open(tmpname, 'r:bz2', compresslevel=1) as tobj: + pass class LzmaCreateTest(LzmaTest, CreateTest): - pass + + # Unlike gz and bz2, xz uses the preset keyword instead of compresslevel. + # It does not allow for preset to be specified when reading. + def test_create_with_preset(self): + with tarfile.open(tmpname, self.mode, preset=1) as tobj: + tobj.add(self.file_path) class CreateWithXModeTest(CreateTest): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index cd3aacf6f8844c..30f043172478fb 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -43,8 +43,14 @@ def get_tk_patchlevel(): class TkinterTest(unittest.TestCase): def testFlattenLen(self): - # flatten() + # Object without length. self.assertRaises(TypeError, _tkinter._flatten, True) + # Object with length, but not sequence. + self.assertRaises(TypeError, _tkinter._flatten, {}) + # Sequence or set, but not tuple or list. + # (issue44608: there were leaks in the following cases) + self.assertRaises(TypeError, _tkinter._flatten, 'string') + self.assertRaises(TypeError, _tkinter._flatten, {'set'}) class TclTest(unittest.TestCase): @@ -738,9 +744,9 @@ def check(value): @support.cpython_only def test_new_tcl_obj(self): - self.assertRaises(TypeError, _tkinter.Tcl_Obj) - self.assertRaises(TypeError, _tkinter.TkttType) - self.assertRaises(TypeError, _tkinter.TkappType) + support.check_disallow_instantiation(self, _tkinter.Tcl_Obj) + support.check_disallow_instantiation(self, _tkinter.TkttType) + support.check_disallow_instantiation(self, _tkinter.TkappType) class BigmemTclTest(unittest.TestCase): @@ -798,8 +804,5 @@ def setUpModule(): print('patchlevel =', tcl.call('info', 'patchlevel')) -def test_main(): - support.run_unittest(TclTest, TkinterTest, BigmemTclTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 3a3f6a999ce0af..2b0ec46a103276 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -62,6 +62,25 @@ def test_infer_return_type_multiples_and_none(self): def test_infer_return_type_pathlib(self): self.assertIs(str, tempfile._infer_return_type(pathlib.Path('/'))) + def test_infer_return_type_pathlike(self): + class Path: + def __init__(self, path): + self.path = path + + def __fspath__(self): + return self.path + + self.assertIs(str, tempfile._infer_return_type(Path('/'))) + self.assertIs(bytes, tempfile._infer_return_type(Path(b'/'))) + self.assertIs(str, tempfile._infer_return_type('', Path(''))) + self.assertIs(bytes, tempfile._infer_return_type(b'', Path(b''))) + self.assertIs(bytes, tempfile._infer_return_type(None, Path(b''))) + self.assertIs(str, tempfile._infer_return_type(None, Path(''))) + + with self.assertRaises(TypeError): + tempfile._infer_return_type('', Path(b'')) + with self.assertRaises(TypeError): + tempfile._infer_return_type(b'', Path('')) # Common functionality. @@ -430,6 +449,7 @@ def test_choose_directory(self): self.do_create(dir=dir).write(b"blat") self.do_create(dir=pathlib.Path(dir)).write(b"blat") finally: + support.gc_collect() # For PyPy or other GCs. os.rmdir(dir) def test_file_mode(self): @@ -880,6 +900,8 @@ def test_many(self): extant = list(range(TEST_FILES)) for i in extant: extant[i] = self.do_create(pre="aa") + del extant + support.gc_collect() # For PyPy or other GCs. ## def test_warning(self): ## # mktemp issues a warning when used @@ -1432,7 +1454,7 @@ def test_explict_cleanup_ignore_errors(self): self.assertEqual( temp_path.exists(), sys.platform.startswith("win"), - f"TemporaryDirectory {temp_path!s} existance state unexpected") + f"TemporaryDirectory {temp_path!s} existence state unexpected") temp_dir.cleanup() self.assertFalse( temp_path.exists(), @@ -1491,7 +1513,7 @@ def test_del_on_collection_ignore_errors(self): self.assertEqual( temp_path.exists(), sys.platform.startswith("win"), - f"TemporaryDirectory {temp_path!s} existance state unexpected") + f"TemporaryDirectory {temp_path!s} existence state unexpected") def test_del_on_shutdown(self): # A TemporaryDirectory may be cleaned up during shutdown @@ -1556,7 +1578,7 @@ def test_del_on_shutdown_ignore_errors(self): self.assertEqual( temp_path.exists(), sys.platform.startswith("win"), - f"TemporaryDirectory {temp_path!s} existance state unexpected") + f"TemporaryDirectory {temp_path!s} existence state unexpected") err = err.decode('utf-8', 'backslashreplace') self.assertNotIn("Exception", err) self.assertNotIn("Error", err) diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 62b57fa3388376..4ae8a833b990d7 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -132,6 +132,7 @@ def task(): del task while not done: time.sleep(POLL_SLEEP) + support.gc_collect() # For PyPy or other GCs. self.assertEqual(thread._count(), orig) def test_unraisable_exception(self): diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 546773e3329afa..c54806e5946b68 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -4,7 +4,7 @@ import test.support from test.support import threading_helper -from test.support import verbose, cpython_only +from test.support import verbose, cpython_only, os_helper from test.support.import_helper import import_module from test.support.script_helper import assert_python_ok, assert_python_failure @@ -19,6 +19,7 @@ import subprocess import signal import textwrap +import traceback from unittest import mock from test import lock_tests @@ -31,6 +32,9 @@ # on platforms known to behave badly. platforms_to_skip = ('netbsd5', 'hp-ux11') +# Is Python built with Py_DEBUG macro defined? +Py_DEBUG = hasattr(sys, 'gettotalrefcount') + def restore_default_excepthook(testcase): testcase.addCleanup(setattr, threading, 'excepthook', threading.excepthook) @@ -123,8 +127,7 @@ def func(): pass def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) lock = threading.Lock() - tp = type(lock) - self.assertRaises(TypeError, tp) + test.support.check_disallow_instantiation(self, type(lock)) # Create a bunch of threads, let each do some work, wait until all are # done. @@ -907,6 +910,56 @@ def __call__(self): thread.join() self.assertTrue(target.ran) + def test_leak_without_join(self): + # bpo-37788: Test that a thread which is not joined explicitly + # does not leak. Test written for reference leak checks. + def noop(): pass + with threading_helper.wait_threads_exit(): + threading.Thread(target=noop).start() + # Thread.join() is not called + + @unittest.skipUnless(Py_DEBUG, 'need debug build (Py_DEBUG)') + def test_debug_deprecation(self): + # bpo-44584: The PYTHONTHREADDEBUG environment variable is deprecated + rc, out, err = assert_python_ok("-Wdefault", "-c", "pass", + PYTHONTHREADDEBUG="1") + msg = (b'DeprecationWarning: The threading debug ' + b'(PYTHONTHREADDEBUG environment variable) ' + b'is deprecated and will be removed in Python 3.12') + self.assertIn(msg, err) + + def test_import_from_another_thread(self): + # bpo-1596321: If the threading module is first import from a thread + # different than the main thread, threading._shutdown() must handle + # this case without logging an error at Python exit. + code = textwrap.dedent(''' + import _thread + import sys + + event = _thread.allocate_lock() + event.acquire() + + def import_threading(): + import threading + event.release() + + if 'threading' in sys.modules: + raise Exception('threading is already imported') + + _thread.start_new_thread(import_threading, ()) + + # wait until the threading module is imported + event.acquire() + event.release() + + if 'threading' not in sys.modules: + raise Exception('threading is not imported') + + # don't wait until the thread completes + ''') + rc, out, err = assert_python_ok("-c", code) + self.assertEqual(out, b'') + self.assertEqual(err, b'') class ThreadJoinOnShutdown(BaseTestCase): @@ -1338,6 +1391,22 @@ def run(self): # explicitly break the reference cycle to not leak a dangling thread thread.exc = None + def test_multithread_modify_file_noerror(self): + # See issue25872 + def modify_file(): + with open(os_helper.TESTFN, 'w', encoding='utf-8') as fp: + fp.write(' ') + traceback.format_stack() + + self.addCleanup(os_helper.unlink, os_helper.TESTFN) + threads = [ + threading.Thread(target=modify_file) + for i in range(100) + ] + for t in threads: + t.start() + t.join() + class ThreadRunFail(threading.Thread): def run(self): @@ -1581,6 +1650,31 @@ def test_interrupt_main_invalid_signal(self): self.assertRaises(ValueError, _thread.interrupt_main, signal.NSIG) self.assertRaises(ValueError, _thread.interrupt_main, 1000000) + @threading_helper.reap_threads + def test_can_interrupt_tight_loops(self): + cont = [True] + started = [False] + interrupted = [False] + + def worker(started, cont, interrupted): + iterations = 100_000_000 + started[0] = True + while cont[0]: + if iterations: + iterations -= 1 + else: + return + pass + interrupted[0] = True + + t = threading.Thread(target=worker,args=(started, cont, interrupted)) + t.start() + while not started[0]: + pass + cont[0] = False + t.join() + self.assertTrue(interrupted[0]) + class AtexitTests(unittest.TestCase): diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py index 9862094eaccd81..13facb513367a4 100644 --- a/Lib/test/test_threading_local.py +++ b/Lib/test/test_threading_local.py @@ -37,7 +37,7 @@ def _local_refs(self, n): t.join() del t - gc.collect() + support.gc_collect() # For PyPy or other GCs. self.assertEqual(len(weaklist), n) # XXX _threading_local keeps the local of the last stopped thread alive. @@ -46,7 +46,7 @@ def _local_refs(self, n): # Assignment to the same thread local frees it sometimes (!) local.someothervar = None - gc.collect() + support.gc_collect() # For PyPy or other GCs. deadlist = [weak for weak in weaklist if weak() is None] self.assertIn(len(deadlist), (n-1, n), (n, len(deadlist))) @@ -89,7 +89,7 @@ def f(): # 2) GC the cycle (triggers threadmodule.c::local_clear # before local_dealloc) del cycle - gc.collect() + support.gc_collect() # For PyPy or other GCs. e1.set() e2.wait() @@ -190,7 +190,7 @@ class X: x.local.x = x wr = weakref.ref(x) del x - gc.collect() + support.gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py index 15e8078e936623..bac82b8a445113 100644 --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -4,7 +4,6 @@ import signal import os import sys -from test import support from test.support import threading_helper import _thread as thread import time @@ -231,7 +230,7 @@ def send_signals(): signal.signal(signal.SIGUSR1, old_handler) -def test_main(): +def setUpModule(): global signal_blackboard signal_blackboard = { signal.SIGUSR1 : {'tripped': 0, 'tripped_by': 0 }, @@ -239,10 +238,8 @@ def test_main(): signal.SIGALRM : {'tripped': 0, 'tripped_by': 0 } } oldsigs = registerSignals(handle_signals, handle_signals, handle_signals) - try: - support.run_unittest(ThreadSignals) - finally: - registerSignals(*oldsigs) + unittest.addModuleCleanup(registerSignals, *oldsigs) + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 325829864851c3..d89078f08f611c 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -113,12 +113,13 @@ def test_pthread_getcpuclockid(self): clk_id = time.pthread_getcpuclockid(threading.get_ident()) self.assertTrue(type(clk_id) is int) # when in 32-bit mode AIX only returns the predefined constant - if not platform.system() == "AIX": - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - elif (sys.maxsize.bit_length() > 32): - self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) - else: + if platform.system() == "AIX" and (sys.maxsize.bit_length() <= 32): + self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + # Solaris returns CLOCK_THREAD_CPUTIME_ID when current thread is given + elif sys.platform.startswith("sunos"): self.assertEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) + else: + self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID) t1 = time.clock_gettime(clk_id) t2 = time.clock_gettime(clk_id) self.assertLessEqual(t1, t2) @@ -436,8 +437,8 @@ def test_mktime(self): @unittest.skipUnless(platform.libc_ver()[0] != 'glibc', "disabled because of a bug in glibc. Issue #13309") def test_mktime_error(self): - # It may not be possible to reliably make mktime return error - # on all platfom. This will make sure that no other exception + # It may not be possible to reliably make mktime return an error + # on all platforms. This will make sure that no other exception # than OverflowError is raised for an extreme value. tt = time.gmtime(self.t) tzname = time.strftime('%Z', tt) @@ -1062,7 +1063,7 @@ def test_clock_functions(self): clock_names = [ "CLOCK_MONOTONIC", "clock_gettime", "clock_gettime_ns", "clock_settime", "clock_settime_ns", "clock_getres"] - + if mac_ver >= (10, 12): for name in clock_names: self.assertTrue(hasattr(time, name), f"time.{name} is not available") diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index 823d5c3e1767e4..70a0175d77104c 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -290,13 +290,9 @@ def testRecvfromTimeout(self): self._sock_operation(1, 1.5, 'recvfrom', 1024) -def test_main(): +def setUpModule(): support.requires('network') - support.run_unittest( - CreationTestCase, - TCPTimeoutTestCase, - UDPTimeoutTestCase, - ) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_tix.py b/Lib/test/test_tix.py index e6d759e7bd3b61..8a60c7c8e1fbd5 100644 --- a/Lib/test/test_tix.py +++ b/Lib/test/test_tix.py @@ -1,7 +1,7 @@ +import sys import unittest from test import support from test.support import import_helper -import sys # Skip this test if the _tkinter module wasn't built. _tkinter = import_helper.import_module('_tkinter') @@ -9,7 +9,9 @@ # Skip test if tk cannot be initialized. support.requires('gui') -from tkinter import tix, TclError +# Suppress the deprecation warning +tix = import_helper.import_module('tkinter.tix', deprecated=True) +from tkinter import TclError class TestTix(unittest.TestCase): diff --git a/Lib/test/test_tk.py b/Lib/test/test_tk.py index 59842a5e25e366..69cc2322cd9aa8 100644 --- a/Lib/test/test_tk.py +++ b/Lib/test/test_tk.py @@ -6,11 +6,9 @@ # Skip test if tk cannot be initialized. support.requires('gui') -from tkinter.test import runtktests +def load_tests(loader, tests, pattern): + return loader.discover('tkinter.test.test_tkinter') -def test_main(): - support.run_unittest( - *runtktests.get_tests(text=False, packages=['test_tkinter'])) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 681f2c72f9c378..4bce1ca9c76f7c 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1458,6 +1458,16 @@ def test_pathological_trailing_whitespace(self): # See http://bugs.python.org/issue16152 self.assertExactTypeEqual('@ ', token.AT) + def test_comment_at_the_end_of_the_source_without_newline(self): + # See http://bugs.python.org/issue44667 + source = 'b = 1\n\n#test' + expected_tokens = [token.NAME, token.EQUAL, token.NUMBER, token.NEWLINE, token.NL, token.COMMENT] + + tokens = list(tokenize(BytesIO(source.encode('utf-8')).readline)) + self.assertEqual(tok_name[tokens[0].exact_type], tok_name[ENCODING]) + for i in range(6): + self.assertEqual(tok_name[tokens[i + 1].exact_type], tok_name[expected_tokens[i]]) + self.assertEqual(tok_name[tokens[-1].exact_type], tok_name[token.ENDMARKER]) class UntokenizeTest(TestCase): diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py index bfc1f287fff6e1..c5a230e95c2b7e 100644 --- a/Lib/test/test_tools/test_md5sum.py +++ b/Lib/test/test_tools/test_md5sum.py @@ -1,5 +1,6 @@ """Tests for the md5sum script in the Tools directory.""" +import sys import os import unittest from test.support import os_helper @@ -10,13 +11,13 @@ skip_if_missing() -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('md5', openssl=True) class MD5SumTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.script = os.path.join(scriptsdir, 'md5sum.py') - os.mkdir(os_helper.TESTFN) - cls.fodder = os.path.join(os_helper.TESTFN, 'md5sum.fodder') + os.mkdir(os_helper.TESTFN_ASCII) + cls.fodder = os.path.join(os_helper.TESTFN_ASCII, 'md5sum.fodder') with open(cls.fodder, 'wb') as f: f.write(b'md5sum\r\ntest file\r\n') cls.fodder_md5 = b'd38dae2eb1ab346a292ef6850f9e1a0d' @@ -24,7 +25,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - os_helper.rmtree(os_helper.TESTFN) + os_helper.rmtree(os_helper.TESTFN_ASCII) def test_noargs(self): rc, out, err = assert_python_ok(self.script) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 5bd969d62493a4..18cd4aba24af26 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -4,6 +4,7 @@ from io import StringIO import linecache import sys +import inspect import unittest import re from test import support @@ -38,6 +39,9 @@ def syntax_error_with_caret(self): def syntax_error_with_caret_2(self): compile("1 +\n", "?", "exec") + def syntax_error_with_caret_range(self): + compile("f(x, y for y in range(30), z)", "?", "exec") + def syntax_error_bad_indentation(self): compile("def spam():\n print(1)\n print(2)", "?", "exec") @@ -47,6 +51,9 @@ def syntax_error_with_caret_non_ascii(self): def syntax_error_bad_indentation2(self): compile(" print(2)", "?", "exec") + def tokenizer_error_with_caret_range(self): + compile("blech ( ", "?", "exec") + def test_caret(self): err = self.get_exception_format(self.syntax_error_with_caret, SyntaxError) @@ -54,18 +61,35 @@ def test_caret(self): self.assertTrue(err[1].strip() == "return x!") self.assertIn("^", err[2]) # third line has caret self.assertEqual(err[1].find("!"), err[2].find("^")) # in the right place + self.assertEqual(err[2].count("^"), 1) err = self.get_exception_format(self.syntax_error_with_caret_2, SyntaxError) self.assertIn("^", err[2]) # third line has caret self.assertEqual(err[2].count('\n'), 1) # and no additional newline self.assertEqual(err[1].find("+") + 1, err[2].find("^")) # in the right place + self.assertEqual(err[2].count("^"), 1) err = self.get_exception_format(self.syntax_error_with_caret_non_ascii, SyntaxError) self.assertIn("^", err[2]) # third line has caret self.assertEqual(err[2].count('\n'), 1) # and no additional newline self.assertEqual(err[1].find("+") + 1, err[2].find("^")) # in the right place + self.assertEqual(err[2].count("^"), 1) + + err = self.get_exception_format(self.syntax_error_with_caret_range, + SyntaxError) + self.assertIn("^", err[2]) # third line has caret + self.assertEqual(err[2].count('\n'), 1) # and no additional newline + self.assertEqual(err[1].find("y"), err[2].find("^")) # in the right place + self.assertEqual(err[2].count("^"), len("y for y in range(30)")) + + err = self.get_exception_format(self.tokenizer_error_with_caret_range, + SyntaxError) + self.assertIn("^", err[2]) # third line has caret + self.assertEqual(err[2].count('\n'), 1) # and no additional newline + self.assertEqual(err[1].find("("), err[2].find("^")) # in the right place + self.assertEqual(err[2].count("^"), 1) def test_nocaret(self): exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) @@ -255,6 +279,21 @@ def test_exception_is_None(self): self.assertEqual( traceback.format_exception_only(None, None), [NONE_EXC_STRING]) + def test_signatures(self): + self.assertEqual( + str(inspect.signature(traceback.print_exception)), + ('(exc, /, value=, tb=, ' + 'limit=None, file=None, chain=True)')) + + self.assertEqual( + str(inspect.signature(traceback.format_exception)), + ('(exc, /, value=, tb=, limit=None, ' + 'chain=True)')) + + self.assertEqual( + str(inspect.signature(traceback.format_exception_only)), + '(exc, /, value=)') + class TracebackFormatTests(unittest.TestCase): @@ -746,6 +785,17 @@ def test_message_none(self): err = self.get_report(Exception('')) self.assertIn('Exception\n', err) + def test_exception_modulename_not_unicode(self): + class X(Exception): + def __str__(self): + return "I am X" + + X.__module__ = 42 + + err = self.get_report(X()) + exp = f'.{X.__qualname__}: I am X\n' + self.assertEqual(exp, err) + def test_syntax_error_various_offsets(self): for offset in range(-5, 10): for add in [0, 2]: @@ -765,6 +815,19 @@ def test_syntax_error_various_offsets(self): exp = "\n".join(expected) self.assertEqual(exp, err) + def test_format_exception_only_qualname(self): + class A: + class B: + class X(Exception): + def __str__(self): + return "I am X" + pass + err = self.get_report(A.B.X()) + str_value = 'I am X' + str_name = '.'.join([A.B.X.__module__, A.B.X.__qualname__]) + exp = "%s: %s\n" % (str_name, str_value) + self.assertEqual(exp, err) + class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # @@ -985,6 +1048,10 @@ def test_lazy_lines(self): '"""Test cases for traceback module"""', f.line) + def test_no_line(self): + f = traceback.FrameSummary("f", None, "dummy") + self.assertEqual(f.line, None) + def test_explicit_line(self): f = traceback.FrameSummary("f", 1, "dummy", line="line") self.assertEqual("line", f.line) diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index 556656747bbcbe..82be98dfd8f5ac 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -1082,15 +1082,5 @@ def test_stop_untrack(self): self.untrack() -def test_main(): - support.run_unittest( - TestTraceback, - TestTracemallocEnabled, - TestSnapshot, - TestFilters, - TestCommandLine, - TestCAPI, - ) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_ttk_guionly.py b/Lib/test/test_ttk_guionly.py index abb26433652f17..8f59839d066e68 100644 --- a/Lib/test/test_ttk_guionly.py +++ b/Lib/test/test_ttk_guionly.py @@ -11,25 +11,26 @@ import tkinter from _tkinter import TclError from tkinter import ttk -from tkinter.test import runtktests - -root = None -try: - root = tkinter.Tk() - button = ttk.Button(root) - button.destroy() - del button -except TclError as msg: - # assuming ttk is not available - raise unittest.SkipTest("ttk not available: %s" % msg) -finally: - if root is not None: - root.destroy() - del root - -def test_main(): - support.run_unittest( - *runtktests.get_tests(text=False, packages=['test_ttk'])) + + +def setUpModule(): + root = None + try: + root = tkinter.Tk() + button = ttk.Button(root) + button.destroy() + del button + except TclError as msg: + # assuming ttk is not available + raise unittest.SkipTest("ttk not available: %s" % msg) + finally: + if root is not None: + root.destroy() + del root + +def load_tests(loader, tests, pattern): + return loader.discover('tkinter.test.test_ttk') + if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_ttk_textonly.py b/Lib/test/test_ttk_textonly.py index 013b0e9ee21da4..96dc179a69ecac 100644 --- a/Lib/test/test_ttk_textonly.py +++ b/Lib/test/test_ttk_textonly.py @@ -1,15 +1,463 @@ -from test import support from test.support import import_helper - # Skip this test if _tkinter does not exist. import_helper.import_module('_tkinter') -from tkinter.test import runtktests +import unittest +from tkinter import ttk + + +class MockTkApp: + + def splitlist(self, arg): + if isinstance(arg, tuple): + return arg + return arg.split(':') + + def wantobjects(self): + return True + + +class MockTclObj(object): + typename = 'test' + + def __init__(self, val): + self.val = val + + def __str__(self): + return str(self.val) + + +class MockStateSpec(object): + typename = 'StateSpec' + + def __init__(self, *args): + self.val = args + + def __str__(self): + return ' '.join(self.val) + + +class InternalFunctionsTest(unittest.TestCase): + + def test_format_optdict(self): + def check_against(fmt_opts, result): + for i in range(0, len(fmt_opts), 2): + self.assertEqual(result.pop(fmt_opts[i]), fmt_opts[i + 1]) + if result: + self.fail("result still got elements: %s" % result) + + # passing an empty dict should return an empty object (tuple here) + self.assertFalse(ttk._format_optdict({})) + + # check list formatting + check_against( + ttk._format_optdict({'fg': 'blue', 'padding': [1, 2, 3, 4]}), + {'-fg': 'blue', '-padding': '1 2 3 4'}) + + # check tuple formatting (same as list) + check_against( + ttk._format_optdict({'test': (1, 2, '', 0)}), + {'-test': '1 2 {} 0'}) + + # check untouched values + check_against( + ttk._format_optdict({'test': {'left': 'as is'}}), + {'-test': {'left': 'as is'}}) + + # check script formatting + check_against( + ttk._format_optdict( + {'test': [1, -1, '', '2m', 0], 'test2': 3, + 'test3': '', 'test4': 'abc def', + 'test5': '"abc"', 'test6': '{}', + 'test7': '} -spam {'}, script=True), + {'-test': '{1 -1 {} 2m 0}', '-test2': '3', + '-test3': '{}', '-test4': '{abc def}', + '-test5': '{"abc"}', '-test6': r'\{\}', + '-test7': r'\}\ -spam\ \{'}) + + opts = {'αβγ': True, 'á': False} + orig_opts = opts.copy() + # check if giving unicode keys is fine + check_against(ttk._format_optdict(opts), {'-αβγ': True, '-á': False}) + # opts should remain unchanged + self.assertEqual(opts, orig_opts) + + # passing values with spaces inside a tuple/list + check_against( + ttk._format_optdict( + {'option': ('one two', 'three')}), + {'-option': '{one two} three'}) + check_against( + ttk._format_optdict( + {'option': ('one\ttwo', 'three')}), + {'-option': '{one\ttwo} three'}) + + # passing empty strings inside a tuple/list + check_against( + ttk._format_optdict( + {'option': ('', 'one')}), + {'-option': '{} one'}) + + # passing values with braces inside a tuple/list + check_against( + ttk._format_optdict( + {'option': ('one} {two', 'three')}), + {'-option': r'one\}\ \{two three'}) + + # passing quoted strings inside a tuple/list + check_against( + ttk._format_optdict( + {'option': ('"one"', 'two')}), + {'-option': '{"one"} two'}) + check_against( + ttk._format_optdict( + {'option': ('{one}', 'two')}), + {'-option': r'\{one\} two'}) + + # ignore an option + amount_opts = len(ttk._format_optdict(opts, ignore=('á'))) / 2 + self.assertEqual(amount_opts, len(opts) - 1) + + # ignore non-existing options + amount_opts = len(ttk._format_optdict(opts, ignore=('á', 'b'))) / 2 + self.assertEqual(amount_opts, len(opts) - 1) + + # ignore every option + self.assertFalse(ttk._format_optdict(opts, ignore=list(opts.keys()))) + + + def test_format_mapdict(self): + opts = {'a': [('b', 'c', 'val'), ('d', 'otherval'), ('', 'single')]} + result = ttk._format_mapdict(opts) + self.assertEqual(len(result), len(list(opts.keys())) * 2) + self.assertEqual(result, ('-a', '{b c} val d otherval {} single')) + self.assertEqual(ttk._format_mapdict(opts, script=True), + ('-a', '{{b c} val d otherval {} single}')) + + self.assertEqual(ttk._format_mapdict({2: []}), ('-2', '')) + + opts = {'üñíćódè': [('á', 'vãl')]} + result = ttk._format_mapdict(opts) + self.assertEqual(result, ('-üñíćódè', 'á vãl')) + + self.assertEqual(ttk._format_mapdict({'opt': [('value',)]}), + ('-opt', '{} value')) + + # empty states + valid = {'opt': [('', '', 'hi')]} + self.assertEqual(ttk._format_mapdict(valid), ('-opt', '{ } hi')) + + # when passing multiple states, they all must be strings + invalid = {'opt': [(1, 2, 'valid val')]} + self.assertRaises(TypeError, ttk._format_mapdict, invalid) + invalid = {'opt': [([1], '2', 'valid val')]} + self.assertRaises(TypeError, ttk._format_mapdict, invalid) + # but when passing a single state, it can be anything + valid = {'opt': [[1, 'value']]} + self.assertEqual(ttk._format_mapdict(valid), ('-opt', '1 value')) + # special attention to single states which evaluate to False + for stateval in (None, 0, False, '', set()): # just some samples + valid = {'opt': [(stateval, 'value')]} + self.assertEqual(ttk._format_mapdict(valid), + ('-opt', '{} value')) + + # values must be iterable + opts = {'a': None} + self.assertRaises(TypeError, ttk._format_mapdict, opts) + + + def test_format_elemcreate(self): + self.assertTrue(ttk._format_elemcreate(None), (None, ())) + + ## Testing type = image + # image type expects at least an image name, so this should raise + # IndexError since it tries to access the index 0 of an empty tuple + self.assertRaises(IndexError, ttk._format_elemcreate, 'image') + + # don't format returned values as a tcl script + # minimum acceptable for image type + self.assertEqual(ttk._format_elemcreate('image', False, 'test'), + ("test ", ())) + # specifying a state spec + self.assertEqual(ttk._format_elemcreate('image', False, 'test', + ('', 'a')), ("test {} a", ())) + # state spec with multiple states + self.assertEqual(ttk._format_elemcreate('image', False, 'test', + ('a', 'b', 'c')), ("test {a b} c", ())) + # state spec and options + self.assertEqual(ttk._format_elemcreate('image', False, 'test', + ('a', 'b'), a='x'), ("test a b", ("-a", "x"))) + # format returned values as a tcl script + # state spec with multiple states and an option with a multivalue + self.assertEqual(ttk._format_elemcreate('image', True, 'test', + ('a', 'b', 'c', 'd'), x=[2, 3]), ("{test {a b c} d}", "-x {2 3}")) + + ## Testing type = vsapi + # vsapi type expects at least a class name and a part_id, so this + # should raise a ValueError since it tries to get two elements from + # an empty tuple + self.assertRaises(ValueError, ttk._format_elemcreate, 'vsapi') + + # don't format returned values as a tcl script + # minimum acceptable for vsapi + self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b'), + ("a b ", ())) + # now with a state spec with multiple states + self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', + ('a', 'b', 'c')), ("a b {a b} c", ())) + # state spec and option + self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', + ('a', 'b'), opt='x'), ("a b a b", ("-opt", "x"))) + # format returned values as a tcl script + # state spec with a multivalue and an option + self.assertEqual(ttk._format_elemcreate('vsapi', True, 'a', 'b', + ('a', 'b', [1, 2]), opt='x'), ("{a b {a b} {1 2}}", "-opt x")) + + # Testing type = from + # from type expects at least a type name + self.assertRaises(IndexError, ttk._format_elemcreate, 'from') + + self.assertEqual(ttk._format_elemcreate('from', False, 'a'), + ('a', ())) + self.assertEqual(ttk._format_elemcreate('from', False, 'a', 'b'), + ('a', ('b', ))) + self.assertEqual(ttk._format_elemcreate('from', True, 'a', 'b'), + ('{a}', 'b')) + + + def test_format_layoutlist(self): + def sample(indent=0, indent_size=2): + return ttk._format_layoutlist( + [('a', {'other': [1, 2, 3], 'children': + [('b', {'children': + [('c', {'children': + [('d', {'nice': 'opt'})], 'something': (1, 2) + })] + })] + })], indent=indent, indent_size=indent_size)[0] + + def sample_expected(indent=0, indent_size=2): + spaces = lambda amount=0: ' ' * (amount + indent) + return ( + "%sa -other {1 2 3} -children {\n" + "%sb -children {\n" + "%sc -something {1 2} -children {\n" + "%sd -nice opt\n" + "%s}\n" + "%s}\n" + "%s}" % (spaces(), spaces(indent_size), + spaces(2 * indent_size), spaces(3 * indent_size), + spaces(2 * indent_size), spaces(indent_size), spaces())) + + # empty layout + self.assertEqual(ttk._format_layoutlist([])[0], '') + + # _format_layoutlist always expects the second item (in every item) + # to act like a dict (except when the value evaluates to False). + self.assertRaises(AttributeError, + ttk._format_layoutlist, [('a', 'b')]) + + smallest = ttk._format_layoutlist([('a', None)], indent=0) + self.assertEqual(smallest, + ttk._format_layoutlist([('a', '')], indent=0)) + self.assertEqual(smallest[0], 'a') + + # testing indentation levels + self.assertEqual(sample(), sample_expected()) + for i in range(4): + self.assertEqual(sample(i), sample_expected(i)) + self.assertEqual(sample(i, i), sample_expected(i, i)) + + # invalid layout format, different kind of exceptions will be + # raised by internal functions + + # plain wrong format + self.assertRaises(ValueError, ttk._format_layoutlist, + ['bad', 'format']) + # will try to use iteritems in the 'bad' string + self.assertRaises(AttributeError, ttk._format_layoutlist, + [('name', 'bad')]) + # bad children formatting + self.assertRaises(ValueError, ttk._format_layoutlist, + [('name', {'children': {'a': None}})]) + + + def test_script_from_settings(self): + # empty options + self.assertFalse(ttk._script_from_settings({'name': + {'configure': None, 'map': None, 'element create': None}})) + + # empty layout + self.assertEqual( + ttk._script_from_settings({'name': {'layout': None}}), + "ttk::style layout name {\nnull\n}") + + configdict = {'αβγ': True, 'á': False} + self.assertTrue( + ttk._script_from_settings({'name': {'configure': configdict}})) + + mapdict = {'üñíćódè': [('á', 'vãl')]} + self.assertTrue( + ttk._script_from_settings({'name': {'map': mapdict}})) + + # invalid image element + self.assertRaises(IndexError, + ttk._script_from_settings, {'name': {'element create': ['image']}}) + + # minimal valid image + self.assertTrue(ttk._script_from_settings({'name': + {'element create': ['image', 'name']}})) + + image = {'thing': {'element create': + ['image', 'name', ('state1', 'state2', 'val')]}} + self.assertEqual(ttk._script_from_settings(image), + "ttk::style element create thing image {name {state1 state2} val} ") + + image['thing']['element create'].append({'opt': 30}) + self.assertEqual(ttk._script_from_settings(image), + "ttk::style element create thing image {name {state1 state2} val} " + "-opt 30") + + image['thing']['element create'][-1]['opt'] = [MockTclObj(3), + MockTclObj('2m')] + self.assertEqual(ttk._script_from_settings(image), + "ttk::style element create thing image {name {state1 state2} val} " + "-opt {3 2m}") + + + def test_tclobj_to_py(self): + self.assertEqual( + ttk._tclobj_to_py((MockStateSpec('a', 'b'), 'val')), + [('a', 'b', 'val')]) + self.assertEqual( + ttk._tclobj_to_py([MockTclObj('1'), 2, MockTclObj('3m')]), + [1, 2, '3m']) + + + def test_list_from_statespec(self): + def test_it(sspec, value, res_value, states): + self.assertEqual(ttk._list_from_statespec( + (sspec, value)), [states + (res_value, )]) + + states_even = tuple('state%d' % i for i in range(6)) + statespec = MockStateSpec(*states_even) + test_it(statespec, 'val', 'val', states_even) + test_it(statespec, MockTclObj('val'), 'val', states_even) + + states_odd = tuple('state%d' % i for i in range(5)) + statespec = MockStateSpec(*states_odd) + test_it(statespec, 'val', 'val', states_odd) + + test_it(('a', 'b', 'c'), MockTclObj('val'), 'val', ('a', 'b', 'c')) + + + def test_list_from_layouttuple(self): + tk = MockTkApp() + + # empty layout tuple + self.assertFalse(ttk._list_from_layouttuple(tk, ())) + + # shortest layout tuple + self.assertEqual(ttk._list_from_layouttuple(tk, ('name', )), + [('name', {})]) + + # not so interesting ltuple + sample_ltuple = ('name', '-option', 'value') + self.assertEqual(ttk._list_from_layouttuple(tk, sample_ltuple), + [('name', {'option': 'value'})]) + + # empty children + self.assertEqual(ttk._list_from_layouttuple(tk, + ('something', '-children', ())), + [('something', {'children': []})] + ) + + # more interesting ltuple + ltuple = ( + 'name', '-option', 'niceone', '-children', ( + ('otherone', '-children', ( + ('child', )), '-otheropt', 'othervalue' + ) + ) + ) + self.assertEqual(ttk._list_from_layouttuple(tk, ltuple), + [('name', {'option': 'niceone', 'children': + [('otherone', {'otheropt': 'othervalue', 'children': + [('child', {})] + })] + })] + ) + + # bad tuples + self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, + ('name', 'no_minus')) + self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, + ('name', 'no_minus', 'value')) + self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, + ('something', '-children')) # no children + + + def test_val_or_dict(self): + def func(res, opt=None, val=None): + if opt is None: + return res + if val is None: + return "test val" + return (opt, val) + + tk = MockTkApp() + tk.call = func + + self.assertEqual(ttk._val_or_dict(tk, {}, '-test:3'), + {'test': '3'}) + self.assertEqual(ttk._val_or_dict(tk, {}, ('-test', 3)), + {'test': 3}) + + self.assertEqual(ttk._val_or_dict(tk, {'test': None}, 'x:y'), + 'test val') + + self.assertEqual(ttk._val_or_dict(tk, {'test': 3}, 'x:y'), + {'test': 3}) + + + def test_convert_stringval(self): + tests = ( + (0, 0), ('09', 9), ('a', 'a'), ('áÚ', 'áÚ'), ([], '[]'), + (None, 'None') + ) + for orig, expected in tests: + self.assertEqual(ttk._convert_stringval(orig), expected) + + +class TclObjsToPyTest(unittest.TestCase): + + def test_unicode(self): + adict = {'opt': 'välúè'} + self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'}) + + adict['opt'] = MockTclObj(adict['opt']) + self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'}) + + def test_multivalues(self): + adict = {'opt': [1, 2, 3, 4]} + self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 2, 3, 4]}) + + adict['opt'] = [1, 'xm', 3] + self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 'xm', 3]}) + + adict['opt'] = (MockStateSpec('a', 'b'), 'válũè') + self.assertEqual(ttk.tclobjs_to_py(adict), + {'opt': [('a', 'b', 'válũè')]}) + + self.assertEqual(ttk.tclobjs_to_py({'x': ['y z']}), + {'x': ['y z']}) + + def test_nosplit(self): + self.assertEqual(ttk.tclobjs_to_py({'text': 'some text'}), + {'text': 'some text'}) -def test_main(): - support.run_unittest( - *runtktests.get_tests(gui=False, packages=['test_ttk'])) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py index 86d65075144753..8d6d3a7bd806ca 100644 --- a/Lib/test/test_turtle.py +++ b/Lib/test/test_turtle.py @@ -235,17 +235,9 @@ def test_vector_negative(self): self.assertVectorsAlmostEqual(-vec, expected) def test_distance(self): - vec = Vec2D(6, 8) - expected = 10 - self.assertEqual(abs(vec), expected) - - vec = Vec2D(0, 0) - expected = 0 - self.assertEqual(abs(vec), expected) - - vec = Vec2D(2.5, 6) - expected = 6.5 - self.assertEqual(abs(vec), expected) + self.assertEqual(abs(Vec2D(6, 8)), 10) + self.assertEqual(abs(Vec2D(0, 0)), 0) + self.assertAlmostEqual(abs(Vec2D(2.5, 6)), 6.5) def test_rotate(self): diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py index f6c99bda3aa6f6..87f46c2ce8ce61 100644 --- a/Lib/test/test_type_annotations.py +++ b/Lib/test/test_type_annotations.py @@ -71,7 +71,7 @@ def __annotations__(self, value): @__annotations__.deleter def __annotations__(self): - if hasattr(self, 'my_annotations') and self.my_annotations == None: + if getattr(self, 'my_annotations', False) is None: raise AttributeError('__annotations__') self.my_annotations = None diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 25ebec5fa55093..3dfda5cb956636 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,8 +1,10 @@ # Python test set -- part 6, built-in types -from test.support import run_with_locale +from test.support import run_with_locale, cpython_only import collections.abc from collections import namedtuple +import copy +import gc import inspect import pickle import locale @@ -12,11 +14,19 @@ import weakref import typing + +T = typing.TypeVar("T") + class Example: pass class Forward: ... +def clear_typing_caches(): + for f in typing._cleanups: + f() + + class TypesTests(unittest.TestCase): def test_truth_values(self): @@ -605,12 +615,26 @@ def test_method_descriptor_types(self): self.assertIsInstance(int.from_bytes, types.BuiltinMethodType) self.assertIsInstance(int.__new__, types.BuiltinMethodType) + def test_ellipsis_type(self): + self.assertIsInstance(Ellipsis, types.EllipsisType) + + def test_notimplemented_type(self): + self.assertIsInstance(NotImplemented, types.NotImplementedType) + + def test_none_type(self): + self.assertIsInstance(None, types.NoneType) + + +class UnionTests(unittest.TestCase): + def test_or_types_operator(self): self.assertEqual(int | str, typing.Union[int, str]) self.assertNotEqual(int | list, typing.Union[int, str]) self.assertEqual(str | int, typing.Union[int, str]) self.assertEqual(int | None, typing.Union[int, None]) self.assertEqual(None | int, typing.Union[int, None]) + self.assertEqual(int | type(None), int | None) + self.assertEqual(type(None) | int, None | int) self.assertEqual(int | str | list, typing.Union[int, str, list]) self.assertEqual(int | (str | list), typing.Union[int, str, list]) self.assertEqual(str | (int | list), typing.Union[int, str, list]) @@ -620,7 +644,7 @@ def test_or_types_operator(self): self.assertEqual(None | typing.List[int], typing.Union[None, typing.List[int]]) self.assertEqual(str | float | int | complex | int, (int | str) | (float | complex)) self.assertEqual(typing.Union[str, int, typing.List[int]], str | int | typing.List[int]) - self.assertEqual(int | int, int) + self.assertIs(int | int, int) self.assertEqual( BaseException | bool | @@ -648,22 +672,162 @@ def test_or_types_operator(self): 3 | int with self.assertRaises(TypeError): Example() | int + x = int | str + self.assertEqual(x, int | str) + self.assertEqual(x, str | int) + self.assertNotEqual(x, {}) # should not raise exception with self.assertRaises(TypeError): - (int | str) < typing.Union[str, int] + x < x with self.assertRaises(TypeError): - (int | str) < (int | bool) + x <= x + y = typing.Union[str, int] with self.assertRaises(TypeError): - (int | str) <= (int | str) + x < y + y = int | bool with self.assertRaises(TypeError): - # Check that we don't crash if typing.Union does not have a tuple in __args__ - x = typing.Union[str, int] - x.__args__ = [str, int] - (int | str ) == x + x < y + # Check that we don't crash if typing.Union does not have a tuple in __args__ + y = typing.Union[str, int] + y.__args__ = [str, int] + self.assertEqual(x, y) + + def test_hash(self): + self.assertEqual(hash(int | str), hash(str | int)) + self.assertEqual(hash(int | str), hash(typing.Union[int, str])) + + def test_instancecheck(self): + x = int | str + self.assertIsInstance(1, x) + self.assertIsInstance(True, x) + self.assertIsInstance('a', x) + self.assertNotIsInstance(None, x) + self.assertTrue(issubclass(int, x)) + self.assertTrue(issubclass(bool, x)) + self.assertTrue(issubclass(str, x)) + self.assertFalse(issubclass(type(None), x)) + x = int | None + self.assertIsInstance(None, x) + self.assertTrue(issubclass(type(None), x)) + x = int | collections.abc.Mapping + self.assertIsInstance({}, x) + self.assertTrue(issubclass(dict, x)) + + def test_bad_instancecheck(self): + class BadMeta(type): + def __instancecheck__(cls, inst): + 1/0 + x = int | BadMeta('A', (), {}) + self.assertTrue(isinstance(1, x)) + self.assertRaises(ZeroDivisionError, isinstance, [], x) + + def test_bad_subclasscheck(self): + class BadMeta(type): + def __subclasscheck__(cls, sub): + 1/0 + x = int | BadMeta('A', (), {}) + self.assertTrue(issubclass(int, x)) + self.assertRaises(ZeroDivisionError, issubclass, list, x) def test_or_type_operator_with_TypeVar(self): TV = typing.TypeVar('T') assert TV | str == typing.Union[TV, str] assert str | TV == typing.Union[str, TV] + self.assertIs((int | TV)[int], int) + self.assertIs((TV | int)[int], int) + + def test_union_args(self): + def check(arg, expected): + clear_typing_caches() + self.assertEqual(arg.__args__, expected) + + check(int | str, (int, str)) + check((int | str) | list, (int, str, list)) + check(int | (str | list), (int, str, list)) + check((int | str) | int, (int, str)) + check(int | (str | int), (int, str)) + check((int | str) | (str | int), (int, str)) + check(typing.Union[int, str] | list, (int, str, list)) + check(int | typing.Union[str, list], (int, str, list)) + check((int | str) | (list | int), (int, str, list)) + check((int | str) | typing.Union[list, int], (int, str, list)) + check(typing.Union[int, str] | (list | int), (int, str, list)) + check((str | int) | (int | list), (str, int, list)) + check((str | int) | typing.Union[int, list], (str, int, list)) + check(typing.Union[str, int] | (int | list), (str, int, list)) + check(int | type(None), (int, type(None))) + check(type(None) | int, (type(None), int)) + + args = (int, list[int], typing.List[int], + typing.Tuple[int, int], typing.Callable[[int], int], + typing.Hashable, typing.TypeVar('T')) + for x in args: + with self.subTest(x): + check(x | None, (x, type(None))) + check(None | x, (type(None), x)) + + def test_union_parameter_chaining(self): + T = typing.TypeVar("T") + S = typing.TypeVar("S") + + self.assertEqual((float | list[T])[int], float | list[int]) + self.assertEqual(list[int | list[T]].__parameters__, (T,)) + self.assertEqual(list[int | list[T]][str], list[int | list[str]]) + self.assertEqual((list[T] | list[S]).__parameters__, (T, S)) + self.assertEqual((list[T] | list[S])[int, T], list[int] | list[T]) + self.assertEqual((list[T] | list[S])[int, int], list[int]) + + def test_union_parameter_substitution(self): + def eq(actual, expected, typed=True): + self.assertEqual(actual, expected) + if typed: + self.assertIs(type(actual), type(expected)) + + T = typing.TypeVar('T') + S = typing.TypeVar('S') + NT = typing.NewType('NT', str) + x = int | T | bytes + + eq(x[str], int | str | bytes, typed=False) + eq(x[list[int]], int | list[int] | bytes, typed=False) + eq(x[typing.List], int | typing.List | bytes) + eq(x[typing.List[int]], int | typing.List[int] | bytes) + eq(x[typing.Hashable], int | typing.Hashable | bytes) + eq(x[collections.abc.Hashable], + int | collections.abc.Hashable | bytes, typed=False) + eq(x[typing.Callable[[int], str]], + int | typing.Callable[[int], str] | bytes) + eq(x[collections.abc.Callable[[int], str]], + int | collections.abc.Callable[[int], str] | bytes, typed=False) + eq(x[typing.Tuple[int, str]], int | typing.Tuple[int, str] | bytes) + eq(x[typing.Literal['none']], int | typing.Literal['none'] | bytes) + eq(x[str | list], int | str | list | bytes, typed=False) + eq(x[typing.Union[str, list]], typing.Union[int, str, list, bytes]) + eq(x[str | int], int | str | bytes, typed=False) + eq(x[typing.Union[str, int]], typing.Union[int, str, bytes]) + eq(x[NT], int | NT | bytes) + eq(x[S], int | S | bytes) + + def test_union_pickle(self): + orig = list[T] | int + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(orig, proto) + loaded = pickle.loads(s) + self.assertEqual(loaded, orig) + self.assertEqual(loaded.__args__, orig.__args__) + self.assertEqual(loaded.__parameters__, orig.__parameters__) + + def test_union_copy(self): + orig = list[T] | int + for copied in (copy.copy(orig), copy.deepcopy(orig)): + self.assertEqual(copied, orig) + self.assertEqual(copied.__args__, orig.__args__) + self.assertEqual(copied.__parameters__, orig.__parameters__) + + def test_union_parameter_substitution_errors(self): + T = typing.TypeVar("T") + x = int | T + with self.assertRaises(TypeError): + x[42] def test_or_type_operator_with_forward(self): T = typing.TypeVar('T') @@ -710,7 +874,11 @@ def test_or_type_operator_with_SpecialForm(self): assert typing.Union[int, bool] | str == typing.Union[int, bool, str] def test_or_type_repr(self): + assert repr(int | str) == "int | str" + assert repr((int | str) | list) == "int | str | list" + assert repr(int | (str | list)) == "int | str | list" assert repr(int | None) == "int | None" + assert repr(int | type(None)) == "int | None" assert repr(int | typing.GenericAlias(list, int)) == "int | list[int]" def test_or_type_operator_with_genericalias(self): @@ -743,18 +911,40 @@ def __eq__(self, other): for type_ in union_ga: with self.subTest(f"check isinstance/issubclass is invalid for {type_}"): with self.assertRaises(TypeError): - isinstance(list, type_) + isinstance(1, type_) with self.assertRaises(TypeError): - issubclass(list, type_) - - def test_ellipsis_type(self): - self.assertIsInstance(Ellipsis, types.EllipsisType) - - def test_notimplemented_type(self): - self.assertIsInstance(NotImplemented, types.NotImplementedType) + issubclass(int, type_) - def test_none_type(self): - self.assertIsInstance(None, types.NoneType) + def test_or_type_operator_with_bad_module(self): + class BadMeta(type): + __qualname__ = 'TypeVar' + @property + def __module__(self): + 1 / 0 + TypeVar = BadMeta('TypeVar', (), {}) + _SpecialForm = BadMeta('_SpecialForm', (), {}) + # Crashes in Issue44483 + with self.assertRaises((TypeError, ZeroDivisionError)): + str | TypeVar() + with self.assertRaises((TypeError, ZeroDivisionError)): + str | _SpecialForm() + + @cpython_only + def test_or_type_operator_reference_cycle(self): + if not hasattr(sys, 'gettotalrefcount'): + self.skipTest('Cannot get total reference count.') + gc.collect() + before = sys.gettotalrefcount() + for _ in range(30): + T = typing.TypeVar('T') + U = int | list[T] + T.blah = U + del T + del U + gc.collect() + leeway = 15 + self.assertLessEqual(sys.gettotalrefcount() - before, leeway, + msg='Check for union reference leak.') class MappingProxyTests(unittest.TestCase): @@ -1046,6 +1236,17 @@ def __mro_entries__(self, bases): self.assertEqual(D.__orig_bases__, (c,)) self.assertEqual(D.__mro__, (D, A, object)) + def test_new_class_with_mro_entry_genericalias(self): + L1 = types.new_class('L1', (typing.List[int],), {}) + self.assertEqual(L1.__bases__, (list, typing.Generic)) + self.assertEqual(L1.__orig_bases__, (typing.List[int],)) + self.assertEqual(L1.__mro__, (L1, list, typing.Generic, object)) + + L2 = types.new_class('L2', (list[int],), {}) + self.assertEqual(L2.__bases__, (list,)) + self.assertEqual(L2.__orig_bases__, (list[int],)) + self.assertEqual(L2.__mro__, (L2, list, object)) + def test_new_class_with_mro_entry_none(self): class A: pass class B: pass @@ -1161,6 +1362,11 @@ def __mro_entries__(self, bases): for bases in [x, y, z, t]: self.assertIs(types.resolve_bases(bases), bases) + def test_resolve_bases_with_mro_entry(self): + self.assertEqual(types.resolve_bases((typing.List[int],)), + (list, typing.Generic)) + self.assertEqual(types.resolve_bases((list[int],)), (list,)) + def test_metaclass_derivation(self): # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls @@ -1334,6 +1540,24 @@ class N(type, metaclass=M): N(5) self.assertEqual(str(cm.exception), expected_message) + def test_metaclass_new_error(self): + # bpo-44232: The C function type_new() must properly report the + # exception when a metaclass constructor raises an exception and the + # winner class is not the metaclass. + class ModelBase(type): + def __new__(cls, name, bases, attrs): + super_new = super().__new__ + new_class = super_new(cls, name, bases, {}) + if name != "Model": + raise RuntimeWarning(f"{name=}") + return new_class + + class Model(metaclass=ModelBase): + pass + + with self.assertRaises(RuntimeWarning): + type("SouthPonies", (Model,), {}) + class SimpleNamespaceTests(unittest.TestCase): diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 47dc0b9358d7de..f943aed73614cd 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -33,6 +33,7 @@ import types from test import mod_generics_cache +from test import _typed_dict_helper class BaseTestCase(TestCase): @@ -314,6 +315,8 @@ def test_repr(self): self.assertEqual(repr(u), 'typing.Union[typing.List[int], int]') u = Union[list[int], dict[str, float]] self.assertEqual(repr(u), 'typing.Union[list[int], dict[str, float]]') + u = Union[int | float] + self.assertEqual(repr(u), 'typing.Union[int, float]') def test_cannot_subclass(self): with self.assertRaises(TypeError): @@ -397,8 +400,8 @@ def test_basics(self): issubclass(tuple, Tuple[int, str]) class TP(tuple): ... - self.assertTrue(issubclass(tuple, Tuple)) - self.assertTrue(issubclass(TP, Tuple)) + self.assertIsSubclass(tuple, Tuple) + self.assertIsSubclass(TP, Tuple) def test_equality(self): self.assertEqual(Tuple[int], Tuple[int]) @@ -409,7 +412,7 @@ def test_equality(self): def test_tuple_subclass(self): class MyTuple(tuple): pass - self.assertTrue(issubclass(MyTuple, Tuple)) + self.assertIsSubclass(MyTuple, Tuple) def test_tuple_instance_type_error(self): with self.assertRaises(TypeError): @@ -430,23 +433,28 @@ def test_errors(self): issubclass(42, Tuple[int]) -class CallableTests(BaseTestCase): +class BaseCallableTests: def test_self_subclass(self): + Callable = self.Callable with self.assertRaises(TypeError): - self.assertTrue(issubclass(type(lambda x: x), Callable[[int], int])) - self.assertTrue(issubclass(type(lambda x: x), Callable)) + issubclass(types.FunctionType, Callable[[int], int]) + self.assertIsSubclass(types.FunctionType, Callable) def test_eq_hash(self): - self.assertEqual(Callable[[int], int], Callable[[int], int]) - self.assertEqual(len({Callable[[int], int], Callable[[int], int]}), 1) - self.assertNotEqual(Callable[[int], int], Callable[[int], str]) - self.assertNotEqual(Callable[[int], int], Callable[[str], int]) - self.assertNotEqual(Callable[[int], int], Callable[[int, int], int]) - self.assertNotEqual(Callable[[int], int], Callable[[], int]) - self.assertNotEqual(Callable[[int], int], Callable) + Callable = self.Callable + C = Callable[[int], int] + self.assertEqual(C, Callable[[int], int]) + self.assertEqual(len({C, Callable[[int], int]}), 1) + self.assertNotEqual(C, Callable[[int], str]) + self.assertNotEqual(C, Callable[[str], int]) + self.assertNotEqual(C, Callable[[int, int], int]) + self.assertNotEqual(C, Callable[[], int]) + self.assertNotEqual(C, Callable[..., int]) + self.assertNotEqual(C, Callable) def test_cannot_instantiate(self): + Callable = self.Callable with self.assertRaises(TypeError): Callable() with self.assertRaises(TypeError): @@ -458,16 +466,19 @@ def test_cannot_instantiate(self): type(c)() def test_callable_wrong_forms(self): + Callable = self.Callable with self.assertRaises(TypeError): Callable[int] def test_callable_instance_works(self): + Callable = self.Callable def f(): pass self.assertIsInstance(f, Callable) self.assertNotIsInstance(None, Callable) def test_callable_instance_type_error(self): + Callable = self.Callable def f(): pass with self.assertRaises(TypeError): @@ -480,17 +491,19 @@ def f(): self.assertNotIsInstance(None, Callable[[], Any]) def test_repr(self): + Callable = self.Callable + fullname = f'{Callable.__module__}.Callable' ct0 = Callable[[], bool] - self.assertEqual(repr(ct0), 'typing.Callable[[], bool]') + self.assertEqual(repr(ct0), f'{fullname}[[], bool]') ct2 = Callable[[str, float], int] - self.assertEqual(repr(ct2), 'typing.Callable[[str, float], int]') + self.assertEqual(repr(ct2), f'{fullname}[[str, float], int]') ctv = Callable[..., str] - self.assertEqual(repr(ctv), 'typing.Callable[..., str]') + self.assertEqual(repr(ctv), f'{fullname}[..., str]') ct3 = Callable[[str, float], list[int]] - self.assertEqual(repr(ct3), 'typing.Callable[[str, float], list[int]]') + self.assertEqual(repr(ct3), f'{fullname}[[str, float], list[int]]') def test_callable_with_ellipsis(self): - + Callable = self.Callable def foo(a: Callable[..., T]): pass @@ -498,10 +511,136 @@ def foo(a: Callable[..., T]): {'a': Callable[..., T]}) def test_ellipsis_in_generic(self): + Callable = self.Callable # Shouldn't crash; see https://github.com/python/typing/issues/259 typing.List[Callable[..., str]] + def test_basic(self): + Callable = self.Callable + alias = Callable[[int, str], float] + if Callable is collections.abc.Callable: + self.assertIsInstance(alias, types.GenericAlias) + self.assertIs(alias.__origin__, collections.abc.Callable) + self.assertEqual(alias.__args__, (int, str, float)) + self.assertEqual(alias.__parameters__, ()) + + def test_weakref(self): + Callable = self.Callable + alias = Callable[[int, str], float] + self.assertEqual(weakref.ref(alias)(), alias) + + def test_pickle(self): + Callable = self.Callable + alias = Callable[[int, str], float] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(alias, proto) + loaded = pickle.loads(s) + self.assertEqual(alias.__origin__, loaded.__origin__) + self.assertEqual(alias.__args__, loaded.__args__) + self.assertEqual(alias.__parameters__, loaded.__parameters__) + + def test_var_substitution(self): + Callable = self.Callable + fullname = f"{Callable.__module__}.Callable" + C1 = Callable[[int, T], T] + C2 = Callable[[KT, T], VT] + C3 = Callable[..., T] + self.assertEqual(C1[str], Callable[[int, str], str]) + self.assertEqual(C2[int, float, str], Callable[[int, float], str]) + self.assertEqual(C3[int], Callable[..., int]) + + # multi chaining + C4 = C2[int, VT, str] + self.assertEqual(repr(C4), f"{fullname}[[int, ~VT], str]") + self.assertEqual(repr(C4[dict]), f"{fullname}[[int, dict], str]") + self.assertEqual(C4[dict], Callable[[int, dict], str]) + + # substitute a nested GenericAlias (both typing and the builtin + # version) + C5 = Callable[[typing.List[T], tuple[KT, T], VT], int] + self.assertEqual(C5[int, str, float], + Callable[[typing.List[int], tuple[str, int], float], int]) + + def test_type_erasure(self): + Callable = self.Callable + class C1(Callable): + def __call__(self): + return None + a = C1[[int], T] + self.assertIs(a().__class__, C1) + self.assertEqual(a().__orig_class__, C1[[int], T]) + + def test_paramspec(self): + Callable = self.Callable + fullname = f"{Callable.__module__}.Callable" + P = ParamSpec('P') + P2 = ParamSpec('P2') + C1 = Callable[P, T] + # substitution + self.assertEqual(C1[[int], str], Callable[[int], str]) + self.assertEqual(C1[[int, str], str], Callable[[int, str], str]) + self.assertEqual(C1[[], str], Callable[[], str]) + self.assertEqual(C1[..., str], Callable[..., str]) + self.assertEqual(C1[P2, str], Callable[P2, str]) + self.assertEqual(C1[Concatenate[int, P2], str], + Callable[Concatenate[int, P2], str]) + self.assertEqual(repr(C1), f"{fullname}[~P, ~T]") + self.assertEqual(repr(C1[[int, str], str]), f"{fullname}[[int, str], str]") + with self.assertRaises(TypeError): + C1[int, str] + + C2 = Callable[P, int] + self.assertEqual(C2[[int]], Callable[[int], int]) + self.assertEqual(C2[[int, str]], Callable[[int, str], int]) + self.assertEqual(C2[[]], Callable[[], int]) + self.assertEqual(C2[...], Callable[..., int]) + self.assertEqual(C2[P2], Callable[P2, int]) + self.assertEqual(C2[Concatenate[int, P2]], + Callable[Concatenate[int, P2], int]) + # special case in PEP 612 where + # X[int, str, float] == X[[int, str, float]] + self.assertEqual(C2[int], Callable[[int], int]) + self.assertEqual(C2[int, str], Callable[[int, str], int]) + self.assertEqual(repr(C2), f"{fullname}[~P, int]") + self.assertEqual(repr(C2[int, str]), f"{fullname}[[int, str], int]") + + def test_concatenate(self): + Callable = self.Callable + fullname = f"{Callable.__module__}.Callable" + P = ParamSpec('P') + C1 = Callable[typing.Concatenate[int, P], int] + self.assertEqual(repr(C1), + f"{fullname}[typing.Concatenate[int, ~P], int]") + + def test_errors(self): + Callable = self.Callable + alias = Callable[[int, str], float] + with self.assertRaisesRegex(TypeError, "is not a generic class"): + alias[int] + P = ParamSpec('P') + C1 = Callable[P, T] + with self.assertRaisesRegex(TypeError, "many arguments for"): + C1[int, str, str] + with self.assertRaisesRegex(TypeError, "few arguments for"): + C1[int] + +class TypingCallableTests(BaseCallableTests, BaseTestCase): + Callable = typing.Callable + + def test_consistency(self): + # bpo-42195 + # Testing collections.abc.Callable's consistency with typing.Callable + c1 = typing.Callable[[int, str], dict] + c2 = collections.abc.Callable[[int, str], dict] + self.assertEqual(c1.__args__, c2.__args__) + self.assertEqual(hash(c1.__args__), hash(c2.__args__)) + + +class CollectionsCallableTests(BaseCallableTests, BaseTestCase): + Callable = collections.abc.Callable + + class LiteralTests(BaseTestCase): def test_basics(self): # All of these are allowed. @@ -569,6 +708,8 @@ def test_equal(self): self.assertNotEqual(Literal[True], Literal[1]) self.assertNotEqual(Literal[1], Literal[2]) self.assertNotEqual(Literal[1, True], Literal[1]) + self.assertNotEqual(Literal[1, True], Literal[1, 1]) + self.assertNotEqual(Literal[1, 2], Literal[True, 2]) self.assertEqual(Literal[1], Literal[1]) self.assertEqual(Literal[1, 2], Literal[2, 1]) self.assertEqual(Literal[1, 2, 3], Literal[1, 2, 3, 3]) @@ -752,6 +893,9 @@ class P(Protocol): pass class C(P): pass self.assertIsInstance(C(), C) + with self.assertRaises(TypeError): + C(42) + T = TypeVar('T') class PG(Protocol[T]): pass @@ -766,6 +910,8 @@ class PG(Protocol[T]): pass class CG(PG[T]): pass self.assertIsInstance(CG[int](), CG) + with self.assertRaises(TypeError): + CG[int](42) def test_cannot_instantiate_abstract(self): @runtime_checkable @@ -1193,6 +1339,37 @@ def __init__(self): self.assertEqual(C[int]().test, 'OK') + class B: + def __init__(self): + self.test = 'OK' + + class D1(B, P[T]): + pass + + self.assertEqual(D1[int]().test, 'OK') + + class D2(P[T], B): + pass + + self.assertEqual(D2[int]().test, 'OK') + + def test_new_called(self): + T = TypeVar('T') + + class P(Protocol[T]): pass + + class C(P[T]): + def __new__(cls, *args): + self = super().__new__(cls, *args) + self.test = 'OK' + return self + + self.assertEqual(C[int]().test, 'OK') + with self.assertRaises(TypeError): + C[int](42) + with self.assertRaises(TypeError): + C[int](a=42) + def test_protocols_bad_subscripts(self): T = TypeVar('T') S = TypeVar('S') @@ -1422,6 +1599,24 @@ class CustomProtocol(TestCase, Protocol): class CustomContextManager(typing.ContextManager, Protocol): pass + def test_non_runtime_protocol_isinstance_check(self): + class P(Protocol): + x: int + + with self.assertRaisesRegex(TypeError, "@runtime_checkable"): + isinstance(1, P) + + def test_super_call_init(self): + class P(Protocol): + x: int + + class Foo(P): + def __init__(self): + super().__init__() + + Foo() # Previously triggered RecursionError + + class GenericTests(BaseTestCase): def test_basics(self): @@ -1440,6 +1635,8 @@ def test_basics(self): with self.assertRaises(TypeError): issubclass(SM1, SimpleMapping) self.assertIsInstance(SM1(), SimpleMapping) + T = TypeVar("T") + self.assertEqual(List[list[T] | float].__parameters__, (T,)) def test_generic_errors(self): T = TypeVar('T') @@ -1776,6 +1973,7 @@ def test_extended_generic_rules_repr(self): def test_generic_forward_ref(self): def foobar(x: List[List['CC']]): ... def foobar2(x: list[list[ForwardRef('CC')]]): ... + def foobar3(x: list[ForwardRef('CC | int')] | int): ... class CC: ... self.assertEqual( get_type_hints(foobar, globals(), locals()), @@ -1785,6 +1983,10 @@ class CC: ... get_type_hints(foobar2, globals(), locals()), {'x': list[list[CC]]} ) + self.assertEqual( + get_type_hints(foobar3, globals(), locals()), + {'x': list[CC | int] | int} + ) T = TypeVar('T') AT = Tuple[T, ...] @@ -2228,6 +2430,22 @@ def __new__(cls, arg): self.assertEqual(c.from_b, 'b') self.assertEqual(c.from_c, 'c') + def test_subclass_special_form(self): + for obj in ( + ClassVar[int], + Final[int], + Union[int, float], + Optional[int], + Literal[1, 2], + Concatenate[int, ParamSpec("P")], + TypeGuard[int], + ): + with self.subTest(msg=obj): + with self.assertRaisesRegex( + TypeError, f'^{re.escape(f"Cannot subclass {obj!r}")}$' + ): + class Foo(obj): + pass class ClassVarTests(BaseTestCase): @@ -2268,13 +2486,6 @@ def test_no_isinstance(self): with self.assertRaises(TypeError): issubclass(int, ClassVar) - def test_bad_module(self): - # bpo-41515 - class BadModule: - pass - BadModule.__module__ = 'bad' # Something not in sys.modules - self.assertEqual(get_type_hints(BadModule), {}) - class FinalTests(BaseTestCase): def test_basics(self): @@ -2465,6 +2676,12 @@ def foo(a: Union['T']): self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Union[T]}) + def foo(a: tuple[ForwardRef('T')] | int): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), + {'a': tuple[T] | int}) + def test_tuple_forward(self): def foo(a: Tuple['T']): @@ -2754,7 +2971,7 @@ async def __aexit__(self, etype, eval, tb): # Definitions needed for features introduced in Python 3.6 -from test import ann_module, ann_module2, ann_module3 +from test import ann_module, ann_module2, ann_module3, ann_module5, ann_module6 from typing import AsyncContextManager class A: @@ -2802,6 +3019,9 @@ class Point2D(TypedDict): x: int y: int +class Bar(_typed_dict_helper.Foo, total=False): + b: int + class LabelPoint2D(Point2D, Label): ... class Options(TypedDict, total=False): @@ -2846,7 +3066,7 @@ def test_get_type_hints_from_various_objects(self): gth(None) def test_get_type_hints_modules(self): - ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str} + ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str, 'u': int | float} self.assertEqual(gth(ann_module), ann_module_type_hints) self.assertEqual(gth(ann_module2), {}) self.assertEqual(gth(ann_module3), {}) @@ -2884,6 +3104,12 @@ def test_get_type_hints_classes(self): 'my_inner_a2': mod_generics_cache.B.A, 'my_outer_a': mod_generics_cache.A}) + def test_get_type_hints_classes_no_implicit_optional(self): + class WithNoneDefault: + field: int = None # most type-checkers won't be happy with it + + self.assertEqual(gth(WithNoneDefault), {'field': int}) + def test_respect_no_type_check(self): @no_type_check class NoTpCheck: @@ -2989,6 +3215,16 @@ def barfoo3(x: BA2): ... get_type_hints(barfoo3, globals(), locals(), include_extras=True)["x"], BA2 ) + BA3 = typing.Annotated[int | float, "const"] + def barfoo4(x: BA3): ... + self.assertEqual( + get_type_hints(barfoo4, globals(), locals()), + {"x": int | float} + ) + self.assertEqual( + get_type_hints(barfoo4, globals(), locals(), include_extras=True), + {"x": typing.Annotated[int | float, "const"]} + ) def test_get_type_hints_annotated_refs(self): @@ -3024,6 +3260,24 @@ class Foo: # This previously raised an error under PEP 563. self.assertEqual(get_type_hints(Foo), {'x': str}) + def test_get_type_hints_bad_module(self): + # bpo-41515 + class BadModule: + pass + BadModule.__module__ = 'bad' # Something not in sys.modules + self.assertNotIn('bad', sys.modules) + self.assertEqual(get_type_hints(BadModule), {}) + + def test_get_type_hints_annotated_bad_module(self): + # See https://bugs.python.org/issue44468 + class BadBase: + foo: tuple + class BadType(BadBase): + bar: list + BadType.__module__ = BadBase.__module__ = 'bad' + self.assertNotIn('bad', sys.modules) + self.assertEqual(get_type_hints(BadType), {'foo': tuple, 'bar': list}) + class GetUtilitiesTestCase(TestCase): def test_get_origin(self): @@ -3046,7 +3300,7 @@ class C(Generic[T]): pass self.assertIs(get_origin(Callable), collections.abc.Callable) self.assertIs(get_origin(list[int]), list) self.assertIs(get_origin(list), None) - self.assertIs(get_origin(list | str), types.Union) + self.assertIs(get_origin(list | str), types.UnionType) self.assertIs(get_origin(P.args), P) self.assertIs(get_origin(P.kwargs), P) @@ -3087,6 +3341,22 @@ class C(Generic[T]): pass (Concatenate[int, P], int)) self.assertEqual(get_args(list | str), (list, str)) + def test_forward_ref_and_final(self): + # https://bugs.python.org/issue45166 + hints = get_type_hints(ann_module5) + self.assertEqual(hints, {'name': Final[str]}) + + hints = get_type_hints(ann_module5.MyClass) + self.assertEqual(hints, {'value': Final}) + + def test_top_level_class_var(self): + # https://bugs.python.org/issue45166 + with self.assertRaisesRegex( + TypeError, + r'typing.ClassVar\[int\] is not valid as type argument', + ): + get_type_hints(ann_module6) + class CollectionsAbcTests(BaseTestCase): @@ -3635,23 +3905,81 @@ def foo(a: A) -> Optional[BaseException]: class NewTypeTests(BaseTestCase): + @classmethod + def setUpClass(cls): + global UserId + UserId = NewType('UserId', int) + cls.UserName = NewType(cls.__qualname__ + '.UserName', str) + + @classmethod + def tearDownClass(cls): + global UserId + del UserId + del cls.UserName + + def tearDown(self): + self.clear_caches() def test_basic(self): - UserId = NewType('UserId', int) - UserName = NewType('UserName', str) self.assertIsInstance(UserId(5), int) - self.assertIsInstance(UserName('Joe'), str) + self.assertIsInstance(self.UserName('Joe'), str) self.assertEqual(UserId(5) + 1, 6) def test_errors(self): - UserId = NewType('UserId', int) - UserName = NewType('UserName', str) with self.assertRaises(TypeError): issubclass(UserId, int) with self.assertRaises(TypeError): - class D(UserName): + class D(UserId): pass + def test_or(self): + for cls in (int, self.UserName): + with self.subTest(cls=cls): + self.assertEqual(UserId | cls, Union[UserId, cls]) + self.assertEqual(cls | UserId, Union[cls, UserId]) + + self.assertEqual(get_args(UserId | cls), (UserId, cls)) + self.assertEqual(get_args(cls | UserId), (cls, UserId)) + + def test_special_attrs(self): + self.assertEqual(UserId.__name__, 'UserId') + self.assertEqual(UserId.__qualname__, 'UserId') + self.assertEqual(UserId.__module__, __name__) + self.assertEqual(UserId.__supertype__, int) + + UserName = self.UserName + self.assertEqual(UserName.__name__, 'UserName') + self.assertEqual(UserName.__qualname__, + self.__class__.__qualname__ + '.UserName') + self.assertEqual(UserName.__module__, __name__) + self.assertEqual(UserName.__supertype__, str) + + def test_repr(self): + self.assertEqual(repr(UserId), f'{__name__}.UserId') + self.assertEqual(repr(self.UserName), + f'{__name__}.{self.__class__.__qualname__}.UserName') + + def test_pickle(self): + UserAge = NewType('UserAge', float) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + pickled = pickle.dumps(UserId, proto) + loaded = pickle.loads(pickled) + self.assertIs(loaded, UserId) + + pickled = pickle.dumps(self.UserName, proto) + loaded = pickle.loads(pickled) + self.assertIs(loaded, self.UserName) + + with self.assertRaises(pickle.PicklingError): + pickle.dumps(UserAge, proto) + + def test_missing__name__(self): + code = ("import typing\n" + "NT = typing.NewType('NT', int)\n" + ) + exec(code, {}) + class NamedTupleTests(BaseTestCase): class NestedEmployee(NamedTuple): @@ -3761,6 +4089,19 @@ def test_namedtuple_special_keyword_names(self): self.assertEqual(a.typename, 'foo') self.assertEqual(a.fields, [('bar', tuple)]) + def test_empty_namedtuple(self): + NT = NamedTuple('NT') + + class CNT(NamedTuple): + pass # empty body + + for struct in [NT, CNT]: + with self.subTest(struct=struct): + self.assertEqual(struct._fields, ()) + self.assertEqual(struct._field_defaults, {}) + self.assertEqual(struct.__annotations__, {}) + self.assertIsInstance(struct(), struct) + def test_namedtuple_errors(self): with self.assertRaises(TypeError): NamedTuple.__new__() @@ -3960,6 +4301,12 @@ def test_is_typeddict(self): # classes, not instances assert is_typeddict(Point2D()) is False + def test_get_type_hints(self): + self.assertEqual( + get_type_hints(Bar), + {'a': typing.Optional[int], 'b': int} + ) + class IOTests(BaseTestCase): @@ -4228,6 +4575,11 @@ def test_annotated_in_other_types(self): X = List[Annotated[T, 5]] self.assertEqual(X[int], List[Annotated[int, 5]]) + def test_annotated_mro(self): + class X(Annotated[int, (1, 10)]): ... + self.assertEqual(X.__mro__, (X, int, object), + "Annotated should be transparent.") + class TypeAliasTests(BaseTestCase): def test_canonical_usage_with_variable_annotation(self): @@ -4314,6 +4666,10 @@ class X(Generic[T, P]): G1 = X[int, P_2] self.assertEqual(G1.__args__, (int, P_2)) self.assertEqual(G1.__parameters__, (P_2,)) + with self.assertRaisesRegex(TypeError, "few arguments for"): + X[int] + with self.assertRaisesRegex(TypeError, "many arguments for"): + X[int, P_2, str] G2 = X[int, Concatenate[int, P_2]] self.assertEqual(G2.__args__, (int, Concatenate[int, P_2])) @@ -4344,12 +4700,58 @@ class Z(Generic[P]): self.assertEqual(G5.__parameters__, G6.__parameters__) self.assertEqual(G5, G6) - def test_var_substitution(self): + G7 = Z[int] + self.assertEqual(G7.__args__, ((int,),)) + self.assertEqual(G7.__parameters__, ()) + + with self.assertRaisesRegex(TypeError, "many arguments for"): + Z[[int, str], bool] + with self.assertRaisesRegex(TypeError, "many arguments for"): + Z[P_2, bool] + + def test_multiple_paramspecs_in_user_generics(self): + P = ParamSpec("P") + P2 = ParamSpec("P2") + + class X(Generic[P, P2]): + f: Callable[P, int] + g: Callable[P2, str] + + G1 = X[[int, str], [bytes]] + G2 = X[[int], [str, bytes]] + self.assertNotEqual(G1, G2) + self.assertEqual(G1.__args__, ((int, str), (bytes,))) + self.assertEqual(G2.__args__, ((int,), (str, bytes))) + + def test_no_paramspec_in__parameters__(self): + # ParamSpec should not be found in __parameters__ + # of generics. Usages outside Callable, Concatenate + # and Generic are invalid. + T = TypeVar("T") + P = ParamSpec("P") + self.assertNotIn(P, List[P].__parameters__) + self.assertIn(T, Tuple[T, P].__parameters__) + + # Test for consistency with builtin generics. + self.assertNotIn(P, list[P].__parameters__) + self.assertIn(T, tuple[T, P].__parameters__) + + self.assertNotIn(P, (list[P] | int).__parameters__) + self.assertIn(T, (tuple[T, P] | int).__parameters__) + + def test_paramspec_in_nested_generics(self): + # Although ParamSpec should not be found in __parameters__ of most + # generics, they probably should be found when nested in + # a valid location. T = TypeVar("T") P = ParamSpec("P") C1 = Callable[P, T] - self.assertEqual(C1[int, str], Callable[[int], str]) - self.assertEqual(C1[[int, str, dict], float], Callable[[int, str, dict], float]) + G1 = List[C1] + G2 = list[C1] + G3 = list[C1] | int + self.assertEqual(G1.__parameters__, (P, T)) + self.assertEqual(G2.__parameters__, (P, T)) + self.assertEqual(G3.__parameters__, (P, T)) class ConcatenateTests(BaseTestCase): @@ -4417,6 +4819,198 @@ def test_no_isinstance(self): issubclass(int, TypeGuard) +SpecialAttrsP = typing.ParamSpec('SpecialAttrsP') +SpecialAttrsT = typing.TypeVar('SpecialAttrsT', int, float, complex) + + +class SpecialAttrsTests(BaseTestCase): + + def test_special_attrs(self): + cls_to_check = { + # ABC classes + typing.AbstractSet: 'AbstractSet', + typing.AsyncContextManager: 'AsyncContextManager', + typing.AsyncGenerator: 'AsyncGenerator', + typing.AsyncIterable: 'AsyncIterable', + typing.AsyncIterator: 'AsyncIterator', + typing.Awaitable: 'Awaitable', + typing.ByteString: 'ByteString', + typing.Callable: 'Callable', + typing.ChainMap: 'ChainMap', + typing.Collection: 'Collection', + typing.Container: 'Container', + typing.ContextManager: 'ContextManager', + typing.Coroutine: 'Coroutine', + typing.Counter: 'Counter', + typing.DefaultDict: 'DefaultDict', + typing.Deque: 'Deque', + typing.Dict: 'Dict', + typing.FrozenSet: 'FrozenSet', + typing.Generator: 'Generator', + typing.Hashable: 'Hashable', + typing.ItemsView: 'ItemsView', + typing.Iterable: 'Iterable', + typing.Iterator: 'Iterator', + typing.KeysView: 'KeysView', + typing.List: 'List', + typing.Mapping: 'Mapping', + typing.MappingView: 'MappingView', + typing.MutableMapping: 'MutableMapping', + typing.MutableSequence: 'MutableSequence', + typing.MutableSet: 'MutableSet', + typing.OrderedDict: 'OrderedDict', + typing.Reversible: 'Reversible', + typing.Sequence: 'Sequence', + typing.Set: 'Set', + typing.Sized: 'Sized', + typing.Tuple: 'Tuple', + typing.Type: 'Type', + typing.ValuesView: 'ValuesView', + # Subscribed ABC classes + typing.AbstractSet[Any]: 'AbstractSet', + typing.AsyncContextManager[Any]: 'AsyncContextManager', + typing.AsyncGenerator[Any, Any]: 'AsyncGenerator', + typing.AsyncIterable[Any]: 'AsyncIterable', + typing.AsyncIterator[Any]: 'AsyncIterator', + typing.Awaitable[Any]: 'Awaitable', + typing.Callable[[], Any]: 'Callable', + typing.Callable[..., Any]: 'Callable', + typing.ChainMap[Any, Any]: 'ChainMap', + typing.Collection[Any]: 'Collection', + typing.Container[Any]: 'Container', + typing.ContextManager[Any]: 'ContextManager', + typing.Coroutine[Any, Any, Any]: 'Coroutine', + typing.Counter[Any]: 'Counter', + typing.DefaultDict[Any, Any]: 'DefaultDict', + typing.Deque[Any]: 'Deque', + typing.Dict[Any, Any]: 'Dict', + typing.FrozenSet[Any]: 'FrozenSet', + typing.Generator[Any, Any, Any]: 'Generator', + typing.ItemsView[Any, Any]: 'ItemsView', + typing.Iterable[Any]: 'Iterable', + typing.Iterator[Any]: 'Iterator', + typing.KeysView[Any]: 'KeysView', + typing.List[Any]: 'List', + typing.Mapping[Any, Any]: 'Mapping', + typing.MappingView[Any]: 'MappingView', + typing.MutableMapping[Any, Any]: 'MutableMapping', + typing.MutableSequence[Any]: 'MutableSequence', + typing.MutableSet[Any]: 'MutableSet', + typing.OrderedDict[Any, Any]: 'OrderedDict', + typing.Reversible[Any]: 'Reversible', + typing.Sequence[Any]: 'Sequence', + typing.Set[Any]: 'Set', + typing.Tuple[Any]: 'Tuple', + typing.Tuple[Any, ...]: 'Tuple', + typing.Type[Any]: 'Type', + typing.ValuesView[Any]: 'ValuesView', + # Special Forms + typing.Annotated: 'Annotated', + typing.Any: 'Any', + typing.ClassVar: 'ClassVar', + typing.Concatenate: 'Concatenate', + typing.Final: 'Final', + typing.ForwardRef: 'ForwardRef', + typing.Literal: 'Literal', + typing.NewType: 'NewType', + typing.NoReturn: 'NoReturn', + typing.Optional: 'Optional', + typing.TypeAlias: 'TypeAlias', + typing.TypeGuard: 'TypeGuard', + typing.TypeVar: 'TypeVar', + typing.Union: 'Union', + # Subscribed special forms + typing.Annotated[Any, "Annotation"]: 'Annotated', + typing.ClassVar[Any]: 'ClassVar', + typing.Concatenate[Any, SpecialAttrsP]: 'Concatenate', + typing.Final[Any]: 'Final', + typing.Literal[Any]: 'Literal', + typing.Literal[1, 2]: 'Literal', + typing.Literal[True, 2]: 'Literal', + typing.Optional[Any]: 'Optional', + typing.TypeGuard[Any]: 'TypeGuard', + typing.Union[Any]: 'Any', + typing.Union[int, float]: 'Union', + # Incompatible special forms (tested in test_special_attrs2) + # - typing.ForwardRef('set[Any]') + # - typing.NewType('TypeName', Any) + # - typing.ParamSpec('SpecialAttrsP') + # - typing.TypeVar('T') + } + + for cls, name in cls_to_check.items(): + with self.subTest(cls=cls): + self.assertEqual(cls.__name__, name, str(cls)) + self.assertEqual(cls.__qualname__, name, str(cls)) + self.assertEqual(cls.__module__, 'typing', str(cls)) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(cls, proto) + loaded = pickle.loads(s) + self.assertIs(cls, loaded) + + TypeName = typing.NewType('SpecialAttrsTests.TypeName', Any) + + def test_special_attrs2(self): + # Forward refs provide a different introspection API. __name__ and + # __qualname__ make little sense for forward refs as they can store + # complex typing expressions. + fr = typing.ForwardRef('set[Any]') + self.assertFalse(hasattr(fr, '__name__')) + self.assertFalse(hasattr(fr, '__qualname__')) + self.assertEqual(fr.__module__, 'typing') + # Forward refs are currently unpicklable. + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.assertRaises(TypeError) as exc: + pickle.dumps(fr, proto) + + self.assertEqual(SpecialAttrsTests.TypeName.__name__, 'TypeName') + self.assertEqual( + SpecialAttrsTests.TypeName.__qualname__, + 'SpecialAttrsTests.TypeName', + ) + self.assertEqual( + SpecialAttrsTests.TypeName.__module__, + 'test.test_typing', + ) + # NewTypes are picklable assuming correct qualname information. + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(SpecialAttrsTests.TypeName, proto) + loaded = pickle.loads(s) + self.assertIs(SpecialAttrsTests.TypeName, loaded) + + # Type variables don't support non-global instantiation per PEP 484 + # restriction that "The argument to TypeVar() must be a string equal + # to the variable name to which it is assigned". Thus, providing + # __qualname__ is unnecessary. + self.assertEqual(SpecialAttrsT.__name__, 'SpecialAttrsT') + self.assertFalse(hasattr(SpecialAttrsT, '__qualname__')) + self.assertEqual(SpecialAttrsT.__module__, 'test.test_typing') + # Module-level type variables are picklable. + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(SpecialAttrsT, proto) + loaded = pickle.loads(s) + self.assertIs(SpecialAttrsT, loaded) + + self.assertEqual(SpecialAttrsP.__name__, 'SpecialAttrsP') + self.assertFalse(hasattr(SpecialAttrsP, '__qualname__')) + self.assertEqual(SpecialAttrsP.__module__, 'test.test_typing') + # Module-level ParamSpecs are picklable. + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + s = pickle.dumps(SpecialAttrsP, proto) + loaded = pickle.loads(s) + self.assertIs(SpecialAttrsP, loaded) + + def test_genericalias_dir(self): + class Foo(Generic[T]): + def bar(self): + pass + baz = 3 + # The class attributes of the original class should be visible even + # in dir() of the GenericAlias. See bpo-45755. + self.assertIn('bar', dir(Foo[int])) + self.assertIn('baz', dir(Foo[int])) + + class AllTests(BaseTestCase): """Tests for __all__.""" diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index 0e6cbb61b2298b..dd1428710d568c 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -508,6 +508,28 @@ def test_replace_id(self): text = 'abc def' self.assertIs(text.replace(pattern, pattern), text) + def test_repeat_id_preserving(self): + a = '123abc1@' + b = '456zyx-+' + self.assertEqual(id(a), id(a)) + self.assertNotEqual(id(a), id(b)) + self.assertNotEqual(id(a), id(a * -4)) + self.assertNotEqual(id(a), id(a * 0)) + self.assertEqual(id(a), id(a * 1)) + self.assertEqual(id(a), id(1 * a)) + self.assertNotEqual(id(a), id(a * 2)) + + class SubStr(str): + pass + + s = SubStr('qwerty()') + self.assertEqual(id(s), id(s)) + self.assertNotEqual(id(s), id(s * -4)) + self.assertNotEqual(id(s), id(s * 0)) + self.assertNotEqual(id(s), id(s * 1)) + self.assertNotEqual(id(s), id(1 * s)) + self.assertNotEqual(id(s), id(s * 2)) + def test_bytes_comparison(self): with warnings_helper.check_warnings(): warnings.simplefilter('ignore', BytesWarning) @@ -1231,8 +1253,11 @@ def __repr__(self): 0, 1, 2, 3, 4, 5, 6, 7) # string format spec errors - self.assertRaises(ValueError, "{0:-s}".format, '') - self.assertRaises(ValueError, format, "", "-") + sign_msg = "Sign not allowed in string format specifier" + self.assertRaisesRegex(ValueError, sign_msg, "{0:-s}".format, '') + self.assertRaisesRegex(ValueError, sign_msg, format, "", "-") + space_msg = "Space not allowed in string format specifier" + self.assertRaisesRegex(ValueError, space_msg, "{: }".format, '') self.assertRaises(ValueError, "{0:=s}".format, '') # Alternate formatting is not supported @@ -1463,23 +1488,22 @@ class Float(float, enum.Enum): PI = 3.1415926 class Int(enum.IntEnum): IDES = 15 - class Str(enum.StrEnum): - # StrEnum uses the value and not the name for %s etc. + class Str(str, enum.Enum): ABC = 'abc' # Testing Unicode formatting strings... self.assertEqual("%s, %s" % (Str.ABC, Str.ABC), - 'abc, abc') + 'Str.ABC, Str.ABC') self.assertEqual("%s, %s, %d, %i, %u, %f, %5.2f" % (Str.ABC, Str.ABC, Int.IDES, Int.IDES, Int.IDES, Float.PI, Float.PI), - 'abc, abc, 15, 15, 15, 3.141593, 3.14') + 'Str.ABC, Str.ABC, 15, 15, 15, 3.141593, 3.14') # formatting jobs delegated from the string implementation: self.assertEqual('...%(foo)s...' % {'foo':Str.ABC}, - '...abc...') + '...Str.ABC...') self.assertEqual('...%(foo)s...' % {'foo':Int.IDES}, - '...IDES...') + '...Int.IDES...') self.assertEqual('...%(foo)i...' % {'foo':Int.IDES}, '...15...') self.assertEqual('...%(foo)d...' % {'foo':Int.IDES}, diff --git a/Lib/test/test_unicode_file.py b/Lib/test/test_unicode_file.py index e3979491879838..80c22c6cdd1dad 100644 --- a/Lib/test/test_unicode_file.py +++ b/Lib/test/test_unicode_file.py @@ -6,7 +6,6 @@ import unicodedata import unittest -from test.support import run_unittest from test.support.os_helper import (rmtree, change_cwd, TESTFN_UNICODE, TESTFN_UNENCODABLE, create_empty_file) @@ -136,8 +135,6 @@ def test_directories(self): self._do_directory(TESTFN_UNENCODABLE+ext, TESTFN_UNENCODABLE+ext) -def test_main(): - run_unittest(__name__) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_unicode_file_functions.py b/Lib/test/test_unicode_file_functions.py index 7ef11aac9f8ef6..54916dec4eafa3 100644 --- a/Lib/test/test_unicode_file_functions.py +++ b/Lib/test/test_unicode_file_functions.py @@ -5,7 +5,6 @@ import unittest import warnings from unicodedata import normalize -from test import support from test.support import os_helper @@ -185,15 +184,5 @@ class UnicodeNFKDFileTests(UnicodeFileTests): normal_form = 'NFKD' -def test_main(): - support.run_unittest( - UnicodeFileTests, - UnicodeNFCFileTests, - UnicodeNFDFileTests, - UnicodeNFKCFileTests, - UnicodeNFKDFileTests, - ) - - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index c6bbe3f5ff2b33..213b3cf2529986 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -12,7 +12,7 @@ import unicodedata import unittest from test.support import (open_urlresource, requires_resource, script_helper, - cpython_only) + cpython_only, check_disallow_instantiation) class UnicodeMethodsTest(unittest.TestCase): @@ -229,7 +229,7 @@ class UnicodeMiscTest(UnicodeDatabaseTest): @cpython_only def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) - self.assertRaises(TypeError, unicodedata.UCD) + check_disallow_instantiation(self, unicodedata.UCD) def test_failed_import_during_compiling(self): # Issue 4367 diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index bfc3ded6f128da..1079c7df2e51c2 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -3,14 +3,14 @@ from test import support -def test_main(): - # used by regrtest - support.run_unittest(unittest.test.suite()) - support.reap_children() - def load_tests(*_): # used by unittest return unittest.test.suite() + +def tearDownModule(): + support.reap_children() + + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 9f67b49f3a6b2b..33e1149bfd360f 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -408,7 +408,7 @@ def test_type_ignore(self): class CosmeticTestCase(ASTTestCase): - """Test if there are cosmetic issues caused by unnecesary additions""" + """Test if there are cosmetic issues caused by unnecessary additions""" def test_simple_expressions_parens(self): self.check_src_roundtrip("(a := b)") diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index ebb43c30b4d505..0b2d07ce61d5c7 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -317,7 +317,7 @@ def test_basic_auth_httperror(self): self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url) -@hashlib_helper.requires_hashdigest("md5") +@hashlib_helper.requires_hashdigest("md5", openssl=True) class ProxyAuthTests(unittest.TestCase): URL = "http://localhost" @@ -661,17 +661,10 @@ def test_line_iteration(self): self.assertEqual(index + 1, len(lines)) -threads_key = None - def setUpModule(): - # Store the threading_setup in a key and ensure that it is cleaned up - # in the tearDown - global threads_key - threads_key = threading_helper.threading_setup() - -def tearDownModule(): - if threads_key: - threading_helper.threading_cleanup(*threads_key) + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index 4750ad9600cc3e..aa41811560c789 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -67,7 +67,7 @@ def __exit__(self, type_=None, value=None, traceback=None): raise ResourceDenied("an optional resource is not available") # Context managers that raise ResourceDenied when various issues -# with the Internet connection manifest themselves as exceptions. +# with the internet connection manifest themselves as exceptions. # XXX deprecate these and use transient_internet() instead time_out = TransientResource(OSError, errno=errno.ETIMEDOUT) socket_peer_reset = TransientResource(OSError, errno=errno.ECONNRESET) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 67341fecef94cd..31943f357f49f3 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -614,32 +614,40 @@ def test_urlsplit_attributes(self): def test_urlsplit_remove_unsafe_bytes(self): # Remove ASCII tabs and newlines from input - url = "http://www.python.org/java\nscript:\talert('msg\r\n')/#frag" + url = "http\t://www.python\n.org\t/java\nscript:\talert('msg\r\n')/?query\n=\tsomething#frag\nment" p = urllib.parse.urlsplit(url) self.assertEqual(p.scheme, "http") self.assertEqual(p.netloc, "www.python.org") self.assertEqual(p.path, "/javascript:alert('msg')/") - self.assertEqual(p.query, "") - self.assertEqual(p.fragment, "frag") + self.assertEqual(p.query, "query=something") + self.assertEqual(p.fragment, "fragment") self.assertEqual(p.username, None) self.assertEqual(p.password, None) self.assertEqual(p.hostname, "www.python.org") self.assertEqual(p.port, None) - self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/#frag") + self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") # Remove ASCII tabs and newlines from input as bytes. - url = b"http://www.python.org/java\nscript:\talert('msg\r\n')/#frag" + url = b"http\t://www.python\n.org\t/java\nscript:\talert('msg\r\n')/?query\n=\tsomething#frag\nment" p = urllib.parse.urlsplit(url) self.assertEqual(p.scheme, b"http") self.assertEqual(p.netloc, b"www.python.org") self.assertEqual(p.path, b"/javascript:alert('msg')/") - self.assertEqual(p.query, b"") - self.assertEqual(p.fragment, b"frag") + self.assertEqual(p.query, b"query=something") + self.assertEqual(p.fragment, b"fragment") self.assertEqual(p.username, None) self.assertEqual(p.password, None) self.assertEqual(p.hostname, b"www.python.org") self.assertEqual(p.port, None) - self.assertEqual(p.geturl(), b"http://www.python.org/javascript:alert('msg')/#frag") + self.assertEqual(p.geturl(), b"http://www.python.org/javascript:alert('msg')/?query=something#fragment") + + # with scheme as cache-key + url = "http://www.python.org/java\nscript:\talert('msg\r\n')/?query\n=\tsomething#frag\nment" + scheme = "ht\ntp" + for _ in range(2): + p = urllib.parse.urlsplit(url, scheme=scheme) + self.assertEqual(p.scheme, "http") + self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") def test_attributes_bad_port(self): """Check handling of invalid ports.""" diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 3f56192c70e846..d6a8333427a4a2 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -4,7 +4,6 @@ import builtins import contextlib import copy -import enum import io import os import pickle @@ -32,13 +31,6 @@ def get_command_stdout(command, args): class BaseTestUUID: uuid = None - def test_safe_uuid_enum(self): - class CheckedSafeUUID(enum.Enum): - safe = 0 - unsafe = -1 - unknown = None - enum._test_simple_enum(CheckedSafeUUID, py_uuid.SafeUUID) - def test_UUID(self): equal = self.assertEqual ascending = [] diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 098ba17af59758..94d626598bac38 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -150,14 +150,20 @@ def test_prompt(self): def test_upgrade_dependencies(self): builder = venv.EnvBuilder() bin_path = 'Scripts' if sys.platform == 'win32' else 'bin' - python_exe = 'python.exe' if sys.platform == 'win32' else 'python' + python_exe = os.path.split(sys.executable)[1] with tempfile.TemporaryDirectory() as fake_env_dir: + expect_exe = os.path.normcase( + os.path.join(fake_env_dir, bin_path, python_exe) + ) + if sys.platform == 'win32': + expect_exe = os.path.normcase(os.path.realpath(expect_exe)) def pip_cmd_checker(cmd): + cmd[0] = os.path.normcase(cmd[0]) self.assertEqual( cmd, [ - os.path.join(fake_env_dir, bin_path, python_exe), + expect_exe, '-m', 'pip', 'install', diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 56a42f055d0b54..096833d1ebb355 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -12,6 +12,7 @@ from test import support from test.support import script_helper, ALWAYS_EQ +from test.support import gc_collect # Used in ReferencesTestCase.test_ref_created_during_del() . ref_from_del = None @@ -135,6 +136,7 @@ def test_multiple_callbacks(self): ref1 = weakref.ref(o, self.callback) ref2 = weakref.ref(o, self.callback) del o + gc_collect() # For PyPy or other GCs. self.assertIsNone(ref1(), "expected reference to be invalidated") self.assertIsNone(ref2(), "expected reference to be invalidated") self.assertEqual(self.cbcalled, 2, @@ -168,13 +170,16 @@ def test_proxy_ref(self): ref1 = weakref.proxy(o, self.callback) ref2 = weakref.proxy(o, self.callback) del o + gc_collect() # For PyPy or other GCs. def check(proxy): proxy.bar self.assertRaises(ReferenceError, check, ref1) self.assertRaises(ReferenceError, check, ref2) - self.assertRaises(ReferenceError, bool, weakref.proxy(C())) + ref3 = weakref.proxy(C()) + gc_collect() # For PyPy or other GCs. + self.assertRaises(ReferenceError, bool, ref3) self.assertEqual(self.cbcalled, 2) def check_basic_ref(self, factory): @@ -191,6 +196,7 @@ def check_basic_callback(self, factory): o = factory() ref = weakref.ref(o, self.callback) del o + gc_collect() # For PyPy or other GCs. self.assertEqual(self.cbcalled, 1, "callback did not properly set 'cbcalled'") self.assertIsNone(ref(), @@ -215,6 +221,7 @@ def test_ref_reuse(self): self.assertEqual(weakref.getweakrefcount(o), 2, "wrong weak ref count for object") del proxy + gc_collect() # For PyPy or other GCs. self.assertEqual(weakref.getweakrefcount(o), 1, "wrong weak ref count for object after deleting proxy") @@ -411,6 +418,36 @@ def __iter__(self): # can be killed in the middle of the call "blech" in p + def test_proxy_next(self): + arr = [4, 5, 6] + def iterator_func(): + yield from arr + it = iterator_func() + + class IteratesWeakly: + def __iter__(self): + return weakref.proxy(it) + + weak_it = IteratesWeakly() + + # Calls proxy.__next__ + self.assertEqual(list(weak_it), [4, 5, 6]) + + def test_proxy_bad_next(self): + # bpo-44720: PyIter_Next() shouldn't be called if the reference + # isn't an iterator. + + not_an_iterator = lambda: 0 + + class A: + def __iter__(self): + return weakref.proxy(not_an_iterator) + a = A() + + msg = "Weakref proxy referenced a non-iterator" + with self.assertRaisesRegex(TypeError, msg): + list(a) + def test_proxy_reversed(self): class MyObj: def __len__(self): @@ -422,14 +459,20 @@ def __reversed__(self): self.assertEqual("".join(reversed(weakref.proxy(obj))), "cba") def test_proxy_hash(self): - cool_hash = 299_792_458 - class MyObj: def __hash__(self): - return cool_hash + return 42 + + obj = MyObj() + with self.assertRaises(TypeError): + hash(weakref.proxy(obj)) + + class MyObj: + __hash__ = None obj = MyObj() - self.assertEqual(hash(weakref.proxy(obj)), cool_hash) + with self.assertRaises(TypeError): + hash(weakref.proxy(obj)) def test_getweakrefcount(self): o = C() @@ -444,6 +487,7 @@ def test_getweakrefcount(self): "got wrong number of weak reference objects") del ref1, ref2, proxy1, proxy2 + gc_collect() # For PyPy or other GCs. self.assertEqual(weakref.getweakrefcount(o), 0, "weak reference objects not unlinked from" " referent when discarded.") @@ -457,6 +501,7 @@ def test_getweakrefs(self): ref1 = weakref.ref(o, self.callback) ref2 = weakref.ref(o, self.callback) del ref1 + gc_collect() # For PyPy or other GCs. self.assertEqual(weakref.getweakrefs(o), [ref2], "list of refs does not match") @@ -464,10 +509,12 @@ def test_getweakrefs(self): ref1 = weakref.ref(o, self.callback) ref2 = weakref.ref(o, self.callback) del ref2 + gc_collect() # For PyPy or other GCs. self.assertEqual(weakref.getweakrefs(o), [ref1], "list of refs does not match") del ref1 + gc_collect() # For PyPy or other GCs. self.assertEqual(weakref.getweakrefs(o), [], "list of refs not cleared") @@ -953,6 +1000,7 @@ def __call__(self): self.assertTrue(mr.called) self.assertEqual(mr.value, 24) del o + gc_collect() # For PyPy or other GCs. self.assertIsNone(mr()) self.assertTrue(mr.called) @@ -1255,15 +1303,18 @@ def test_weak_values(self): del items1, items2 self.assertEqual(len(dict), self.COUNT) del objects[0] + gc_collect() # For PyPy or other GCs. self.assertEqual(len(dict), self.COUNT - 1, "deleting object did not cause dictionary update") del objects, o + gc_collect() # For PyPy or other GCs. self.assertEqual(len(dict), 0, "deleting the values did not clear the dictionary") # regression on SF bug #447152: dict = weakref.WeakValueDictionary() self.assertRaises(KeyError, dict.__getitem__, 1) dict[2] = C() + gc_collect() # For PyPy or other GCs. self.assertRaises(KeyError, dict.__getitem__, 2) def test_weak_keys(self): @@ -1284,9 +1335,11 @@ def test_weak_keys(self): del items1, items2 self.assertEqual(len(dict), self.COUNT) del objects[0] + gc_collect() # For PyPy or other GCs. self.assertEqual(len(dict), (self.COUNT - 1), "deleting object did not cause dictionary update") del objects, o + gc_collect() # For PyPy or other GCs. self.assertEqual(len(dict), 0, "deleting the keys did not clear the dictionary") o = Object(42) @@ -1419,7 +1472,7 @@ def check_weak_del_and_len_while_iterating(self, dict, testcontext): o = Object(123456) with testcontext(): n = len(dict) - # Since underlaying dict is ordered, first item is popped + # Since underlying dict is ordered, first item is popped dict.pop(next(dict.keys())) self.assertEqual(len(dict), n - 1) dict[o] = o @@ -1785,6 +1838,7 @@ def __eq__(self, other): for o in objs: count += 1 del d[o] + gc_collect() # For PyPy or other GCs. self.assertEqual(len(d), 0) self.assertEqual(count, 2) @@ -2093,6 +2147,7 @@ def test_atexit(self): libreftest = """ Doctest for examples in the library reference: weakref.rst +>>> from test.support import gc_collect >>> import weakref >>> class Dict(dict): ... pass @@ -2112,6 +2167,7 @@ def test_atexit(self): >>> o is o2 True >>> del o, o2 +>>> gc_collect() # For PyPy or other GCs. >>> print(r()) None @@ -2164,6 +2220,7 @@ def test_atexit(self): >>> id2obj(a_id) is a True >>> del a +>>> gc_collect() # For PyPy or other GCs. >>> try: ... id2obj(a_id) ... except KeyError: diff --git a/Lib/test/test_weakset.py b/Lib/test/test_weakset.py index 49a9b5c3c658a8..9b31d5fce3472f 100644 --- a/Lib/test/test_weakset.py +++ b/Lib/test/test_weakset.py @@ -5,6 +5,7 @@ from collections.abc import Set, MutableSet import gc import contextlib +from test import support class Foo: @@ -48,6 +49,7 @@ def test_len(self): self.assertEqual(len(self.s), len(self.d)) self.assertEqual(len(self.fs), 1) del self.obj + support.gc_collect() # For PyPy or other GCs. self.assertEqual(len(self.fs), 0) def test_contains(self): @@ -57,6 +59,7 @@ def test_contains(self): self.assertNotIn(1, self.s) self.assertIn(self.obj, self.fs) del self.obj + support.gc_collect() # For PyPy or other GCs. self.assertNotIn(ustr('F'), self.fs) def test_union(self): @@ -215,6 +218,7 @@ def test_add(self): self.assertEqual(self.s, dup) self.assertRaises(TypeError, self.s.add, []) self.fs.add(Foo()) + support.gc_collect() # For PyPy or other GCs. self.assertTrue(len(self.fs) == 1) self.fs.add(self.obj) self.assertTrue(len(self.fs) == 1) @@ -406,6 +410,7 @@ def test_len_cycles(self): n1 = len(s) del it gc.collect() + gc.collect() # For PyPy or other GCs. n2 = len(s) # one item may be kept alive inside the iterator self.assertIn(n1, (0, 1)) diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index 1807e47c66c387..70a85552cc03b0 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -92,9 +92,11 @@ def test_open_name(self): f.close() f.close() - f = open('C:/con', 'rb', buffering=0) - self.assertIsInstance(f, ConIO) - f.close() + # bpo-45354: Windows 11 changed MS-DOS device name handling + if sys.getwindowsversion()[:3] < (10, 0, 22000): + f = open('C:/con', 'rb', buffering=0) + self.assertIsInstance(f, ConIO) + f.close() @unittest.skipIf(sys.getwindowsversion()[:2] <= (6, 1), "test does not work on Windows 7 and earlier") @@ -114,7 +116,8 @@ def test_conout_path(self): conout_path = os.path.join(temp_path, 'CONOUT$') with open(conout_path, 'wb', buffering=0) as f: - if sys.getwindowsversion()[:2] > (6, 1): + # bpo-45354: Windows 11 changed MS-DOS device name handling + if (6, 1) < sys.getwindowsversion()[:3] < (10, 0, 22000): self.assertIsInstance(f, ConIO) else: self.assertNotIsInstance(f, ConIO) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 487abcd8d9531a..8157c2da6efaa6 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -3,7 +3,6 @@ import os, sys, errno import unittest -from test import support from test.support import import_helper import threading from platform import machine, win32_edition @@ -46,7 +45,7 @@ ("Raw Data", b"binary\x00data", REG_BINARY), ("Big String", "x"*(2**14-1), REG_SZ), ("Big Binary", b"x"*(2**14), REG_BINARY), - # Two and three kanjis, meaning: "Japan" and "Japanese") + # Two and three kanjis, meaning: "Japan" and "Japanese". ("Japanese 日本", "日本語", REG_SZ), ] @@ -490,12 +489,9 @@ def test_exception_numbers(self): with self.assertRaises(FileNotFoundError) as ctx: QueryValue(HKEY_CLASSES_ROOT, 'some_value_that_does_not_exist') -def test_main(): - support.run_unittest(LocalWinregTests, RemoteWinregTests, - Win64WinregTests) if __name__ == "__main__": if not REMOTE_NAME: print("Remote registry calls can be tested using", "'test_winreg.py --remote \\\\machine_name'") - test_main() + unittest.main() diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py index 93ca6b99a92c9c..42094f467731d4 100644 --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -580,7 +580,7 @@ def testEnviron(self): # Test handler.environ as a dict expected = {} setup_testing_defaults(expected) - # Handler inherits os_environ variables which are not overriden + # Handler inherits os_environ variables which are not overridden # by SimpleHandler.add_cgi_vars() (SimpleHandler.base_env) for key, value in os_environ.items(): if key not in expected: diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 553529a3001702..285559a872a65f 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -26,7 +26,7 @@ from test import support from test.support import os_helper from test.support import warnings_helper -from test.support import findfile, gc_collect, swap_attr +from test.support import findfile, gc_collect, swap_attr, swap_item from test.support.import_helper import import_fresh_module from test.support.os_helper import TESTFN @@ -167,12 +167,11 @@ def setUpClass(cls): cls.modules = {pyET, ET} def pickleRoundTrip(self, obj, name, dumper, loader, proto): - save_m = sys.modules[name] try: - sys.modules[name] = dumper - temp = pickle.dumps(obj, proto) - sys.modules[name] = loader - result = pickle.loads(temp) + with swap_item(sys.modules, name, dumper): + temp = pickle.dumps(obj, proto) + with swap_item(sys.modules, name, loader): + result = pickle.loads(temp) except pickle.PicklingError as pe: # pyET must be second, because pyET may be (equal to) ET. human = dict([(ET, "cET"), (pyET, "pyET")]) @@ -180,8 +179,6 @@ def pickleRoundTrip(self, obj, name, dumper, loader, proto): % (obj, human.get(dumper, dumper), human.get(loader, loader))) from pe - finally: - sys.modules[name] = save_m return result def assertEqualElements(self, alice, bob): @@ -2480,6 +2477,7 @@ def wref_cb(w): wref = weakref.ref(e, wref_cb) self.assertEqual(wref().tag, 'e') del e + gc_collect() # For PyPy or other GCs. self.assertEqual(flag, True) self.assertEqual(wref(), None) @@ -3333,7 +3331,7 @@ class MyElement(ET.Element): self._check_element_factory_class(MyElement) def test_element_factory_pure_python_subclass(self): - # Mimick SimpleTAL's behaviour (issue #16089): both versions of + # Mimic SimpleTAL's behaviour (issue #16089): both versions of # TreeBuilder should be able to cope with a subclass of the # pure Python Element class. base = ET._Element_Py diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e68613bb910dd4..bec8208571902e 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -169,6 +169,18 @@ def test_xmlpullparser_leaks(self): del parser support.gc_collect() + def test_dict_disappearing_during_get_item(self): + # test fix for seg fault reported in issue 27946 + class X: + def __hash__(self): + e.attrib = {} # this frees e->extra->attrib + [{i: i} for i in range(1000)] # exhaust the dict keys cache + return 13 + + e = cET.Element("elem", {1: 2}) + r = e.get(X()) + self.assertIsNone(r) + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index a9f67466071bc6..1f06f5fdf483e9 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -561,7 +561,7 @@ def test_comparison(self): class BinaryTestCase(unittest.TestCase): - # XXX What should str(Binary(b"\xff")) return? I'm chosing "\xff" + # XXX What should str(Binary(b"\xff")) return? I'm choosing "\xff" # for now (i.e. interpreting the binary data as Latin-1-encoded # text). But this feels very unsatisfactory. Perhaps we should # only define repr(), and return r"Binary(b'\xff')" instead? @@ -1504,16 +1504,10 @@ def test_xmlrpcserver_has_use_builtin_types_flag(self): self.assertTrue(server.use_builtin_types) -@threading_helper.reap_threads -def test_main(): - support.run_unittest(XMLRPCTestCase, HelperTestCase, DateTimeTestCase, - BinaryTestCase, FaultTestCase, UseBuiltinTypesTestCase, - SimpleServerTestCase, SimpleServerEncodingTestCase, - KeepaliveServerTestCase1, KeepaliveServerTestCase2, - GzipServerTestCase, GzipUtilTestCase, HeadersServerTestCase, - MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase, - CGIHandlerTestCase, SimpleXMLRPCDispatcherTestCase) +def setUpModule(): + thread_info = threading_helper.threading_setup() + unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_xmlrpc_net.py b/Lib/test/test_xmlrpc_net.py index f3652b86f75102..51167b28bc5a1e 100644 --- a/Lib/test/test_xmlrpc_net.py +++ b/Lib/test/test_xmlrpc_net.py @@ -5,6 +5,9 @@ import xmlrpc.client as xmlrpclib +support.requires("network") + + @unittest.skip('XXX: buildbot.python.org/all/xmlrpc/ is gone') class PythonBuildersTest(unittest.TestCase): @@ -24,9 +27,5 @@ def test_python_builders(self): self.assertTrue([x for x in builders if "3.x" in x], builders) -def test_main(): - support.requires("network") - support.run_unittest(PythonBuildersTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index dfc4a060ec6cc9..19d3a880f4cd7b 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -37,14 +37,9 @@ def get_file(): def make_pyc(co, mtime, size): data = marshal.dumps(co) - if type(mtime) is type(0.0): - # Mac mtimes need a bit of special casing - if mtime < 0x7fffffff: - mtime = int(mtime) - else: - mtime = int(-0x100000000 + int(mtime)) pyc = (importlib.util.MAGIC_NUMBER + - struct.pack("") - def test_eventtype_enum(self): - class CheckedEventType(enum.StrEnum): - KeyPress = '2' - Key = KeyPress - KeyRelease = '3' - ButtonPress = '4' - Button = ButtonPress - ButtonRelease = '5' - Motion = '6' - Enter = '7' - Leave = '8' - FocusIn = '9' - FocusOut = '10' - Keymap = '11' # undocumented - Expose = '12' - GraphicsExpose = '13' # undocumented - NoExpose = '14' # undocumented - Visibility = '15' - Create = '16' - Destroy = '17' - Unmap = '18' - Map = '19' - MapRequest = '20' - Reparent = '21' - Configure = '22' - ConfigureRequest = '23' - Gravity = '24' - ResizeRequest = '25' - Circulate = '26' - CirculateRequest = '27' - Property = '28' - SelectionClear = '29' # undocumented - SelectionRequest = '30' # undocumented - Selection = '31' # undocumented - Colormap = '32' - ClientMessage = '33' # undocumented - Mapping = '34' # undocumented - VirtualEvent = '35' # undocumented - Activate = '36' - Deactivate = '37' - MouseWheel = '38' - enum._test_simple_enum(CheckedEventType, tkinter.EventType) - def test_getboolean(self): for v in 'true', 'yes', 'on', '1', 't', 'y', 1, True: self.assertIs(self.root.getboolean(v), True) @@ -383,7 +353,5 @@ def test_mainloop(self): self.assertRaises(RuntimeError, tkinter.mainloop) -tests_gui = (MiscTest, DefaultRootTest) - if __name__ == "__main__": - support.run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_tkinter/test_simpledialog.py b/Lib/tkinter/test/test_tkinter/test_simpledialog.py index b64b854c4db7ef..18cd2712b0c5ed 100644 --- a/Lib/tkinter/test/test_tkinter/test_simpledialog.py +++ b/Lib/tkinter/test/test_tkinter/test_simpledialog.py @@ -1,6 +1,6 @@ import unittest import tkinter -from test.support import requires, run_unittest, swap_attr +from test.support import requires, swap_attr from tkinter.test.support import AbstractDefaultRootTest from tkinter.simpledialog import Dialog, askinteger @@ -31,7 +31,5 @@ def mock_wait_window(w): self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number") -tests_gui = (DefaultRootTest,) - if __name__ == "__main__": - run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_tkinter/test_text.py b/Lib/tkinter/test/test_tkinter/test_text.py index 13b7c56a3978d9..482f150df559fc 100644 --- a/Lib/tkinter/test/test_tkinter/test_text.py +++ b/Lib/tkinter/test/test_tkinter/test_text.py @@ -1,6 +1,6 @@ import unittest import tkinter -from test.support import requires, run_unittest +from test.support import requires from tkinter.test.support import AbstractTkTest requires('gui') @@ -41,7 +41,5 @@ def test_search(self): self.assertEqual(text.search('test', '1.0', 'end'), '1.3') -tests_gui = (TextTest, ) - if __name__ == "__main__": - run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py index 6aebe8d16d556b..427e168454362c 100644 --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -1,4 +1,6 @@ import unittest +from test import support + import gc import tkinter from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, @@ -46,6 +48,7 @@ def test___del__(self): v = Variable(self.root, "sample string", "varname") self.assertTrue(self.info_exists("varname")) del v + support.gc_collect() # For PyPy or other GCs. self.assertFalse(self.info_exists("varname")) def test_dont_unset_not_existing(self): @@ -53,9 +56,11 @@ def test_dont_unset_not_existing(self): v1 = Variable(self.root, name="name") v2 = Variable(self.root, name="name") del v1 + support.gc_collect() # For PyPy or other GCs. self.assertFalse(self.info_exists("name")) # shouldn't raise exception del v2 + support.gc_collect() # For PyPy or other GCs. self.assertFalse(self.info_exists("name")) def test_equality(self): @@ -333,10 +338,5 @@ def test_variable(self): self.assertRaises(RuntimeError, Variable) -tests_gui = (TestVariable, TestStringVar, TestIntVar, - TestDoubleVar, TestBooleanVar, DefaultRootTest) - - if __name__ == "__main__": - from test.support import run_unittest - run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py index 39334de8cf41c3..cc227e579679b7 100644 --- a/Lib/tkinter/test/test_tkinter/test_widgets.py +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py @@ -1241,8 +1241,11 @@ def test_configure_title(self): def test_configure_type(self): widget = self.create() - self.checkEnumParam(widget, 'type', - 'normal', 'tearoff', 'menubar') + self.checkEnumParam( + widget, 'type', + 'normal', 'tearoff', 'menubar', + errmsg='bad type "{}": must be normal, tearoff, or menubar', + ) def test_entryconfigure(self): m1 = self.create() diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index 1a70e0befe6234..1220c4831c52f4 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -2,7 +2,7 @@ import unittest import tkinter from tkinter import ttk -from test.support import requires, run_unittest +from test.support import requires, gc_collect from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest requires('gui') @@ -18,6 +18,7 @@ def test_widget_destroy(self): x = ttk.LabeledScale(self.root) var = x._variable._name x.destroy() + gc_collect() # For PyPy or other GCs. self.assertRaises(tkinter.TclError, x.tk.globalgetvar, var) # manually created variable @@ -30,6 +31,7 @@ def test_widget_destroy(self): else: self.assertEqual(float(x.tk.globalgetvar(name)), myvar.get()) del myvar + gc_collect() # For PyPy or other GCs. self.assertRaises(tkinter.TclError, x.tk.globalgetvar, name) # checking that the tracing callback is properly removed @@ -171,6 +173,7 @@ def test_variable_change(self): def test_resize(self): x = ttk.LabeledScale(self.root) x.pack(expand=True, fill='both') + gc_collect() # For PyPy or other GCs. x.update() width, height = x.master.winfo_width(), x.master.winfo_height() @@ -206,6 +209,7 @@ def test_widget_destroy(self): optmenu.destroy() self.assertEqual(optmenu.tk.globalgetvar(name), var.get()) del var + gc_collect() # For PyPy or other GCs. self.assertRaises(tkinter.TclError, optmenu.tk.globalgetvar, name) @@ -251,6 +255,7 @@ def test_menu(self): # check that variable is updated correctly optmenu.pack() + gc_collect() # For PyPy or other GCs. optmenu['menu'].invoke(0) self.assertEqual(optmenu._variable.get(), items[0]) @@ -296,6 +301,22 @@ def test_unique_radiobuttons(self): optmenu.destroy() optmenu2.destroy() + def test_trace_variable(self): + # prior to bpo45160, tracing a variable would cause the callback to be made twice + success = [] + items = ('a', 'b', 'c') + textvar = tkinter.StringVar(self.root) + def cb_test(*args): + success.append(textvar.get()) + optmenu = ttk.OptionMenu(self.root, textvar, "a", *items) + optmenu.pack() + cb_name = textvar.trace_add("write", cb_test) + optmenu['menu'].invoke(1) + self.assertEqual(success, ['b']) + self.assertEqual(textvar.get(), 'b') + textvar.trace_remove("write", cb_name) + optmenu.destroy() + class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): @@ -303,7 +324,5 @@ def test_labeledscale(self): self._test_widget(ttk.LabeledScale) -tests_gui = (LabeledScaleTest, OptionMenuTest, DefaultRootTest) - if __name__ == "__main__": - run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_ttk/test_functions.py b/Lib/tkinter/test/test_ttk/test_functions.py deleted file mode 100644 index 5c23d6fecf8b42..00000000000000 --- a/Lib/tkinter/test/test_ttk/test_functions.py +++ /dev/null @@ -1,460 +0,0 @@ -# -*- encoding: utf-8 -*- -import unittest -from tkinter import ttk - -class MockTkApp: - - def splitlist(self, arg): - if isinstance(arg, tuple): - return arg - return arg.split(':') - - def wantobjects(self): - return True - - -class MockTclObj(object): - typename = 'test' - - def __init__(self, val): - self.val = val - - def __str__(self): - return str(self.val) - - -class MockStateSpec(object): - typename = 'StateSpec' - - def __init__(self, *args): - self.val = args - - def __str__(self): - return ' '.join(self.val) - - -class InternalFunctionsTest(unittest.TestCase): - - def test_format_optdict(self): - def check_against(fmt_opts, result): - for i in range(0, len(fmt_opts), 2): - self.assertEqual(result.pop(fmt_opts[i]), fmt_opts[i + 1]) - if result: - self.fail("result still got elements: %s" % result) - - # passing an empty dict should return an empty object (tuple here) - self.assertFalse(ttk._format_optdict({})) - - # check list formatting - check_against( - ttk._format_optdict({'fg': 'blue', 'padding': [1, 2, 3, 4]}), - {'-fg': 'blue', '-padding': '1 2 3 4'}) - - # check tuple formatting (same as list) - check_against( - ttk._format_optdict({'test': (1, 2, '', 0)}), - {'-test': '1 2 {} 0'}) - - # check untouched values - check_against( - ttk._format_optdict({'test': {'left': 'as is'}}), - {'-test': {'left': 'as is'}}) - - # check script formatting - check_against( - ttk._format_optdict( - {'test': [1, -1, '', '2m', 0], 'test2': 3, - 'test3': '', 'test4': 'abc def', - 'test5': '"abc"', 'test6': '{}', - 'test7': '} -spam {'}, script=True), - {'-test': '{1 -1 {} 2m 0}', '-test2': '3', - '-test3': '{}', '-test4': '{abc def}', - '-test5': '{"abc"}', '-test6': r'\{\}', - '-test7': r'\}\ -spam\ \{'}) - - opts = {'αβγ': True, 'á': False} - orig_opts = opts.copy() - # check if giving unicode keys is fine - check_against(ttk._format_optdict(opts), {'-αβγ': True, '-á': False}) - # opts should remain unchanged - self.assertEqual(opts, orig_opts) - - # passing values with spaces inside a tuple/list - check_against( - ttk._format_optdict( - {'option': ('one two', 'three')}), - {'-option': '{one two} three'}) - check_against( - ttk._format_optdict( - {'option': ('one\ttwo', 'three')}), - {'-option': '{one\ttwo} three'}) - - # passing empty strings inside a tuple/list - check_against( - ttk._format_optdict( - {'option': ('', 'one')}), - {'-option': '{} one'}) - - # passing values with braces inside a tuple/list - check_against( - ttk._format_optdict( - {'option': ('one} {two', 'three')}), - {'-option': r'one\}\ \{two three'}) - - # passing quoted strings inside a tuple/list - check_against( - ttk._format_optdict( - {'option': ('"one"', 'two')}), - {'-option': '{"one"} two'}) - check_against( - ttk._format_optdict( - {'option': ('{one}', 'two')}), - {'-option': r'\{one\} two'}) - - # ignore an option - amount_opts = len(ttk._format_optdict(opts, ignore=('á'))) / 2 - self.assertEqual(amount_opts, len(opts) - 1) - - # ignore non-existing options - amount_opts = len(ttk._format_optdict(opts, ignore=('á', 'b'))) / 2 - self.assertEqual(amount_opts, len(opts) - 1) - - # ignore every option - self.assertFalse(ttk._format_optdict(opts, ignore=list(opts.keys()))) - - - def test_format_mapdict(self): - opts = {'a': [('b', 'c', 'val'), ('d', 'otherval'), ('', 'single')]} - result = ttk._format_mapdict(opts) - self.assertEqual(len(result), len(list(opts.keys())) * 2) - self.assertEqual(result, ('-a', '{b c} val d otherval {} single')) - self.assertEqual(ttk._format_mapdict(opts, script=True), - ('-a', '{{b c} val d otherval {} single}')) - - self.assertEqual(ttk._format_mapdict({2: []}), ('-2', '')) - - opts = {'üñíćódè': [('á', 'vãl')]} - result = ttk._format_mapdict(opts) - self.assertEqual(result, ('-üñíćódè', 'á vãl')) - - self.assertEqual(ttk._format_mapdict({'opt': [('value',)]}), - ('-opt', '{} value')) - - # empty states - valid = {'opt': [('', '', 'hi')]} - self.assertEqual(ttk._format_mapdict(valid), ('-opt', '{ } hi')) - - # when passing multiple states, they all must be strings - invalid = {'opt': [(1, 2, 'valid val')]} - self.assertRaises(TypeError, ttk._format_mapdict, invalid) - invalid = {'opt': [([1], '2', 'valid val')]} - self.assertRaises(TypeError, ttk._format_mapdict, invalid) - # but when passing a single state, it can be anything - valid = {'opt': [[1, 'value']]} - self.assertEqual(ttk._format_mapdict(valid), ('-opt', '1 value')) - # special attention to single states which evaluate to False - for stateval in (None, 0, False, '', set()): # just some samples - valid = {'opt': [(stateval, 'value')]} - self.assertEqual(ttk._format_mapdict(valid), - ('-opt', '{} value')) - - # values must be iterable - opts = {'a': None} - self.assertRaises(TypeError, ttk._format_mapdict, opts) - - - def test_format_elemcreate(self): - self.assertTrue(ttk._format_elemcreate(None), (None, ())) - - ## Testing type = image - # image type expects at least an image name, so this should raise - # IndexError since it tries to access the index 0 of an empty tuple - self.assertRaises(IndexError, ttk._format_elemcreate, 'image') - - # don't format returned values as a tcl script - # minimum acceptable for image type - self.assertEqual(ttk._format_elemcreate('image', False, 'test'), - ("test ", ())) - # specifying a state spec - self.assertEqual(ttk._format_elemcreate('image', False, 'test', - ('', 'a')), ("test {} a", ())) - # state spec with multiple states - self.assertEqual(ttk._format_elemcreate('image', False, 'test', - ('a', 'b', 'c')), ("test {a b} c", ())) - # state spec and options - self.assertEqual(ttk._format_elemcreate('image', False, 'test', - ('a', 'b'), a='x'), ("test a b", ("-a", "x"))) - # format returned values as a tcl script - # state spec with multiple states and an option with a multivalue - self.assertEqual(ttk._format_elemcreate('image', True, 'test', - ('a', 'b', 'c', 'd'), x=[2, 3]), ("{test {a b c} d}", "-x {2 3}")) - - ## Testing type = vsapi - # vsapi type expects at least a class name and a part_id, so this - # should raise a ValueError since it tries to get two elements from - # an empty tuple - self.assertRaises(ValueError, ttk._format_elemcreate, 'vsapi') - - # don't format returned values as a tcl script - # minimum acceptable for vsapi - self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b'), - ("a b ", ())) - # now with a state spec with multiple states - self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', - ('a', 'b', 'c')), ("a b {a b} c", ())) - # state spec and option - self.assertEqual(ttk._format_elemcreate('vsapi', False, 'a', 'b', - ('a', 'b'), opt='x'), ("a b a b", ("-opt", "x"))) - # format returned values as a tcl script - # state spec with a multivalue and an option - self.assertEqual(ttk._format_elemcreate('vsapi', True, 'a', 'b', - ('a', 'b', [1, 2]), opt='x'), ("{a b {a b} {1 2}}", "-opt x")) - - # Testing type = from - # from type expects at least a type name - self.assertRaises(IndexError, ttk._format_elemcreate, 'from') - - self.assertEqual(ttk._format_elemcreate('from', False, 'a'), - ('a', ())) - self.assertEqual(ttk._format_elemcreate('from', False, 'a', 'b'), - ('a', ('b', ))) - self.assertEqual(ttk._format_elemcreate('from', True, 'a', 'b'), - ('{a}', 'b')) - - - def test_format_layoutlist(self): - def sample(indent=0, indent_size=2): - return ttk._format_layoutlist( - [('a', {'other': [1, 2, 3], 'children': - [('b', {'children': - [('c', {'children': - [('d', {'nice': 'opt'})], 'something': (1, 2) - })] - })] - })], indent=indent, indent_size=indent_size)[0] - - def sample_expected(indent=0, indent_size=2): - spaces = lambda amount=0: ' ' * (amount + indent) - return ( - "%sa -other {1 2 3} -children {\n" - "%sb -children {\n" - "%sc -something {1 2} -children {\n" - "%sd -nice opt\n" - "%s}\n" - "%s}\n" - "%s}" % (spaces(), spaces(indent_size), - spaces(2 * indent_size), spaces(3 * indent_size), - spaces(2 * indent_size), spaces(indent_size), spaces())) - - # empty layout - self.assertEqual(ttk._format_layoutlist([])[0], '') - - # _format_layoutlist always expects the second item (in every item) - # to act like a dict (except when the value evaluates to False). - self.assertRaises(AttributeError, - ttk._format_layoutlist, [('a', 'b')]) - - smallest = ttk._format_layoutlist([('a', None)], indent=0) - self.assertEqual(smallest, - ttk._format_layoutlist([('a', '')], indent=0)) - self.assertEqual(smallest[0], 'a') - - # testing indentation levels - self.assertEqual(sample(), sample_expected()) - for i in range(4): - self.assertEqual(sample(i), sample_expected(i)) - self.assertEqual(sample(i, i), sample_expected(i, i)) - - # invalid layout format, different kind of exceptions will be - # raised by internal functions - - # plain wrong format - self.assertRaises(ValueError, ttk._format_layoutlist, - ['bad', 'format']) - # will try to use iteritems in the 'bad' string - self.assertRaises(AttributeError, ttk._format_layoutlist, - [('name', 'bad')]) - # bad children formatting - self.assertRaises(ValueError, ttk._format_layoutlist, - [('name', {'children': {'a': None}})]) - - - def test_script_from_settings(self): - # empty options - self.assertFalse(ttk._script_from_settings({'name': - {'configure': None, 'map': None, 'element create': None}})) - - # empty layout - self.assertEqual( - ttk._script_from_settings({'name': {'layout': None}}), - "ttk::style layout name {\nnull\n}") - - configdict = {'αβγ': True, 'á': False} - self.assertTrue( - ttk._script_from_settings({'name': {'configure': configdict}})) - - mapdict = {'üñíćódè': [('á', 'vãl')]} - self.assertTrue( - ttk._script_from_settings({'name': {'map': mapdict}})) - - # invalid image element - self.assertRaises(IndexError, - ttk._script_from_settings, {'name': {'element create': ['image']}}) - - # minimal valid image - self.assertTrue(ttk._script_from_settings({'name': - {'element create': ['image', 'name']}})) - - image = {'thing': {'element create': - ['image', 'name', ('state1', 'state2', 'val')]}} - self.assertEqual(ttk._script_from_settings(image), - "ttk::style element create thing image {name {state1 state2} val} ") - - image['thing']['element create'].append({'opt': 30}) - self.assertEqual(ttk._script_from_settings(image), - "ttk::style element create thing image {name {state1 state2} val} " - "-opt 30") - - image['thing']['element create'][-1]['opt'] = [MockTclObj(3), - MockTclObj('2m')] - self.assertEqual(ttk._script_from_settings(image), - "ttk::style element create thing image {name {state1 state2} val} " - "-opt {3 2m}") - - - def test_tclobj_to_py(self): - self.assertEqual( - ttk._tclobj_to_py((MockStateSpec('a', 'b'), 'val')), - [('a', 'b', 'val')]) - self.assertEqual( - ttk._tclobj_to_py([MockTclObj('1'), 2, MockTclObj('3m')]), - [1, 2, '3m']) - - - def test_list_from_statespec(self): - def test_it(sspec, value, res_value, states): - self.assertEqual(ttk._list_from_statespec( - (sspec, value)), [states + (res_value, )]) - - states_even = tuple('state%d' % i for i in range(6)) - statespec = MockStateSpec(*states_even) - test_it(statespec, 'val', 'val', states_even) - test_it(statespec, MockTclObj('val'), 'val', states_even) - - states_odd = tuple('state%d' % i for i in range(5)) - statespec = MockStateSpec(*states_odd) - test_it(statespec, 'val', 'val', states_odd) - - test_it(('a', 'b', 'c'), MockTclObj('val'), 'val', ('a', 'b', 'c')) - - - def test_list_from_layouttuple(self): - tk = MockTkApp() - - # empty layout tuple - self.assertFalse(ttk._list_from_layouttuple(tk, ())) - - # shortest layout tuple - self.assertEqual(ttk._list_from_layouttuple(tk, ('name', )), - [('name', {})]) - - # not so interesting ltuple - sample_ltuple = ('name', '-option', 'value') - self.assertEqual(ttk._list_from_layouttuple(tk, sample_ltuple), - [('name', {'option': 'value'})]) - - # empty children - self.assertEqual(ttk._list_from_layouttuple(tk, - ('something', '-children', ())), - [('something', {'children': []})] - ) - - # more interesting ltuple - ltuple = ( - 'name', '-option', 'niceone', '-children', ( - ('otherone', '-children', ( - ('child', )), '-otheropt', 'othervalue' - ) - ) - ) - self.assertEqual(ttk._list_from_layouttuple(tk, ltuple), - [('name', {'option': 'niceone', 'children': - [('otherone', {'otheropt': 'othervalue', 'children': - [('child', {})] - })] - })] - ) - - # bad tuples - self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, - ('name', 'no_minus')) - self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, - ('name', 'no_minus', 'value')) - self.assertRaises(ValueError, ttk._list_from_layouttuple, tk, - ('something', '-children')) # no children - - - def test_val_or_dict(self): - def func(res, opt=None, val=None): - if opt is None: - return res - if val is None: - return "test val" - return (opt, val) - - tk = MockTkApp() - tk.call = func - - self.assertEqual(ttk._val_or_dict(tk, {}, '-test:3'), - {'test': '3'}) - self.assertEqual(ttk._val_or_dict(tk, {}, ('-test', 3)), - {'test': 3}) - - self.assertEqual(ttk._val_or_dict(tk, {'test': None}, 'x:y'), - 'test val') - - self.assertEqual(ttk._val_or_dict(tk, {'test': 3}, 'x:y'), - {'test': 3}) - - - def test_convert_stringval(self): - tests = ( - (0, 0), ('09', 9), ('a', 'a'), ('áÚ', 'áÚ'), ([], '[]'), - (None, 'None') - ) - for orig, expected in tests: - self.assertEqual(ttk._convert_stringval(orig), expected) - - -class TclObjsToPyTest(unittest.TestCase): - - def test_unicode(self): - adict = {'opt': 'välúè'} - self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'}) - - adict['opt'] = MockTclObj(adict['opt']) - self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': 'välúè'}) - - def test_multivalues(self): - adict = {'opt': [1, 2, 3, 4]} - self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 2, 3, 4]}) - - adict['opt'] = [1, 'xm', 3] - self.assertEqual(ttk.tclobjs_to_py(adict), {'opt': [1, 'xm', 3]}) - - adict['opt'] = (MockStateSpec('a', 'b'), 'válũè') - self.assertEqual(ttk.tclobjs_to_py(adict), - {'opt': [('a', 'b', 'válũè')]}) - - self.assertEqual(ttk.tclobjs_to_py({'x': ['y z']}), - {'x': ['y z']}) - - def test_nosplit(self): - self.assertEqual(ttk.tclobjs_to_py({'text': 'some text'}), - {'text': 'some text'}) - -tests_nogui = (InternalFunctionsTest, TclObjsToPyTest) - -if __name__ == "__main__": - from test.support import run_unittest - run_unittest(*tests_nogui) diff --git a/Lib/tkinter/test/test_ttk/test_style.py b/Lib/tkinter/test/test_ttk/test_style.py index 38d70d7a89077d..a33c24ac55beef 100644 --- a/Lib/tkinter/test/test_ttk/test_style.py +++ b/Lib/tkinter/test/test_ttk/test_style.py @@ -3,7 +3,7 @@ import tkinter from tkinter import ttk from test import support -from test.support import requires, run_unittest +from test.support import requires from tkinter.test.support import AbstractTkTest requires('gui') @@ -175,7 +175,5 @@ def test_map_custom_copy(self): self.assertEqual(style.map(newname, key), value) -tests_gui = (StyleTest, ) - if __name__ == "__main__": - run_unittest(*tests_gui) + unittest.main() diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 1fac83a004a6d0..1cb7e74c66ec74 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -1,10 +1,10 @@ import unittest import tkinter from tkinter import ttk, TclError -from test.support import requires +from test.support import requires, gc_collect import sys -from tkinter.test.test_ttk.test_functions import MockTclObj +from test.test_ttk_textonly import MockTclObj from tkinter.test.support import (AbstractTkTest, tcl_version, get_tk_patchlevel, simulate_mouse_click, AbstractDefaultRootTest) from tkinter.test.widget_tests import (add_standard_options, noconv, @@ -61,7 +61,6 @@ def setUp(self): self.widget = ttk.Button(self.root, width=0, text="Text") self.widget.pack() - def test_identify(self): self.widget.update() self.assertEqual(self.widget.identify( @@ -74,7 +73,6 @@ def test_identify(self): self.assertRaises(tkinter.TclError, self.widget.identify, 5, None) self.assertRaises(tkinter.TclError, self.widget.identify, 5, '') - def test_widget_state(self): # XXX not sure about the portability of all these tests self.assertEqual(self.widget.state(), ()) @@ -169,10 +167,13 @@ def checkImageParam(self, widget, name): errmsg='image "spam" doesn\'t exist') def test_configure_compound(self): + options = 'none text image center top bottom left right'.split() + errmsg = ( + 'bad compound "{}": must be' + f' {", ".join(options[:-1])}, or {options[-1]}' + ) widget = self.create() - self.checkEnumParam(widget, 'compound', - 'none', 'text', 'image', 'center', - 'top', 'bottom', 'left', 'right') + self.checkEnumParam(widget, 'compound', *options, errmsg=errmsg) def test_configure_state(self): widget = self.create() @@ -284,6 +285,7 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase): 'show', 'state', 'style', 'takefocus', 'textvariable', 'validate', 'validatecommand', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Entry.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -316,30 +318,23 @@ def test_configure_validatecommand(self): widget = self.create() self.checkCommandParam(widget, 'validatecommand') - def test_bbox(self): self.assertIsBoundingBox(self.entry.bbox(0)) self.assertRaises(tkinter.TclError, self.entry.bbox, 'noindex') self.assertRaises(tkinter.TclError, self.entry.bbox, None) - def test_identify(self): self.entry.pack() self.entry.update() # bpo-27313: macOS Cocoa widget differs from X, allow either - if sys.platform == 'darwin': - self.assertIn(self.entry.identify(5, 5), - ("textarea", "Combobox.button") ) - else: - self.assertEqual(self.entry.identify(5, 5), "textarea") + self.assertEqual(self.entry.identify(5, 5), self.IDENTIFY_AS) self.assertEqual(self.entry.identify(-1, -1), "") self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) self.assertRaises(tkinter.TclError, self.entry.identify, 5, None) self.assertRaises(tkinter.TclError, self.entry.identify, 5, '') - def test_validation_options(self): success = [] test_invalid = lambda: success.append(True) @@ -367,7 +362,6 @@ def test_validation_options(self): self.entry['validatecommand'] = True self.assertRaises(tkinter.TclError, self.entry.validate) - def test_validation(self): validation = [] def validate(to_insert): @@ -385,7 +379,6 @@ def validate(to_insert): self.assertEqual(validation, [False, True]) self.assertEqual(self.entry.get(), 'a') - def test_revalidation(self): def validate(content): for letter in content: @@ -421,6 +414,7 @@ class ComboboxTest(EntryTest, unittest.TestCase): 'validate', 'validatecommand', 'values', 'width', 'xscrollcommand', ) + IDENTIFY_AS = 'Combobox.button' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -436,7 +430,8 @@ def test_configure_height(self): def _show_drop_down_listbox(self): width = self.combo.winfo_width() x, y = width - 5, 5 - self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') + if sys.platform != 'darwin': # there's no down arrow on macOS + self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z') self.combo.event_generate('', x=x, y=y) self.combo.event_generate('', x=x, y=y) self.combo.update_idletasks() @@ -458,7 +453,6 @@ def test_virtual_event(self): self.assertTrue(success) - def test_configure_postcommand(self): success = [] @@ -474,7 +468,6 @@ def test_configure_postcommand(self): self._show_drop_down_listbox() self.assertEqual(len(success), 1) - def test_configure_values(self): def check_get_current(getval, currval): self.assertEqual(self.combo.get(), getval) @@ -589,7 +582,6 @@ def test_add(self): other_child.destroy() self.assertRaises(tkinter.TclError, self.paned.pane, 0) - def test_forget(self): self.assertRaises(tkinter.TclError, self.paned.forget, None) self.assertRaises(tkinter.TclError, self.paned.forget, 0) @@ -598,7 +590,6 @@ def test_forget(self): self.paned.forget(0) self.assertRaises(tkinter.TclError, self.paned.forget, 0) - def test_insert(self): self.assertRaises(tkinter.TclError, self.paned.insert, None, 0) self.assertRaises(tkinter.TclError, self.paned.insert, 0, None) @@ -633,7 +624,6 @@ def test_insert(self): self.assertEqual(self.paned.panes(), (str(child3), str(child2), str(child))) - def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0) @@ -650,7 +640,6 @@ def test_pane(self): self.assertRaises(tkinter.TclError, self.paned.pane, 0, badoption='somevalue') - def test_sashpos(self): self.assertRaises(tkinter.TclError, self.paned.sashpos, None) self.assertRaises(tkinter.TclError, self.paned.sashpos, '') @@ -798,7 +787,6 @@ def test_custom_event(self): self.assertFalse(failure) - def test_get(self): if self.wantobjects: conv = lambda x: x @@ -816,7 +804,6 @@ def test_get(self): self.assertRaises(tkinter.TclError, self.scale.get, '', 0) self.assertRaises(tkinter.TclError, self.scale.get, 0, '') - def test_set(self): if self.wantobjects: conv = lambda x: x @@ -839,6 +826,7 @@ def test_set(self): self.assertEqual(conv(self.scale.get()), var.get()) self.assertEqual(conv(self.scale.get()), max + 5) del var + gc_collect() # For PyPy or other GCs. # the same happens with the value option self.scale['value'] = max + 10 @@ -948,7 +936,6 @@ def test_tab_identifiers(self): else: self.fail("Tab with text 'a' not found") - def test_add_and_hidden(self): self.assertRaises(tkinter.TclError, self.nb.hide, -1) self.assertRaises(tkinter.TclError, self.nb.hide, 'hi') @@ -967,7 +954,7 @@ def test_add_and_hidden(self): tabs = self.nb.tabs() curr = self.nb.index('current') - # verify that the tab gets readded at its previous position + # verify that the tab gets re-added at its previous position child2_index = self.nb.index(self.child2) self.nb.hide(self.child2) self.nb.add(self.child2) @@ -977,7 +964,6 @@ def test_add_and_hidden(self): # but the tab next to it (not hidden) is the one selected now self.assertEqual(self.nb.index('current'), curr + 1) - def test_forget(self): self.assertRaises(tkinter.TclError, self.nb.forget, -1) self.assertRaises(tkinter.TclError, self.nb.forget, 'hi') @@ -993,7 +979,6 @@ def test_forget(self): self.assertEqual(self.nb.index(self.child1), 1) self.assertNotEqual(child1_index, self.nb.index(self.child1)) - def test_index(self): self.assertRaises(tkinter.TclError, self.nb.index, -1) self.assertRaises(tkinter.TclError, self.nb.index, None) @@ -1003,7 +988,6 @@ def test_index(self): self.assertEqual(self.nb.index(self.child2), 1) self.assertEqual(self.nb.index('end'), 2) - def test_insert(self): # moving tabs tabs = self.nb.tabs() @@ -1036,7 +1020,6 @@ def test_insert(self): self.assertRaises(tkinter.TclError, self.nb.insert, None, 0) self.assertRaises(tkinter.TclError, self.nb.insert, None, None) - def test_select(self): self.nb.pack() self.nb.update() @@ -1056,7 +1039,6 @@ def test_select(self): self.nb.update() self.assertTrue(tab_changed) - def test_tab(self): self.assertRaises(tkinter.TclError, self.nb.tab, -1) self.assertRaises(tkinter.TclError, self.nb.tab, 'notab') @@ -1070,7 +1052,6 @@ def test_tab(self): self.assertEqual(self.nb.tab(self.child1, text=None), 'abc') self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc') - def test_configure_tabs(self): self.assertEqual(len(self.nb.tabs()), 2) @@ -1079,14 +1060,14 @@ def test_configure_tabs(self): self.assertEqual(self.nb.tabs(), ()) - def test_traversal(self): self.nb.pack() self.nb.update() self.nb.select(0) - self.assertEqual(self.nb.identify(5, 5), 'focus') + focus_identify_as = 'focus' if sys.platform != 'darwin' else '' + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) self.nb.focus_force() self.nb.event_generate('') @@ -1099,15 +1080,24 @@ def test_traversal(self): self.assertEqual(self.nb.select(), str(self.child2)) self.nb.tab(self.child1, text='a', underline=0) + self.nb.tab(self.child2, text='e', underline=0) self.nb.enable_traversal() self.nb.focus_force() - self.assertEqual(self.nb.identify(5, 5), 'focus') + self.assertEqual(self.nb.identify(5, 5), focus_identify_as) simulate_mouse_click(self.nb, 5, 5) + # on macOS Emacs-style keyboard shortcuts are region-dependent; + # let's use the regular arrow keys instead if sys.platform == 'darwin': - self.nb.event_generate('') + begin = '' + end = '' else: - self.nb.event_generate('') + begin = '' + end = '' + self.nb.event_generate(begin) self.assertEqual(self.nb.select(), str(self.child1)) + self.nb.event_generate(end) + self.assertEqual(self.nb.select(), str(self.child2)) + @add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) class SpinboxTest(EntryTest, unittest.TestCase): @@ -1118,6 +1108,7 @@ class SpinboxTest(EntryTest, unittest.TestCase): 'takefocus', 'textvariable', 'to', 'validate', 'validatecommand', 'values', 'width', 'wrap', 'xscrollcommand', ) + IDENTIFY_AS = 'Spinbox.field' if sys.platform == 'darwin' else 'textarea' def setUp(self): super().setUp() @@ -1366,7 +1357,6 @@ def test_bbox(self): child1 = self.tv.insert(item_id, 'end') self.assertEqual(self.tv.bbox(child1), '') - def test_children(self): # no children yet, should get an empty tuple self.assertEqual(self.tv.get_children(), ()) @@ -1394,7 +1384,6 @@ def test_children(self): self.tv.set_children('') self.assertEqual(self.tv.get_children(), ()) - def test_column(self): # return a dict with all options/values self.assertIsInstance(self.tv.column('#0'), dict) @@ -1420,7 +1409,6 @@ def test_column(self): self.assertRaises(tkinter.TclError, self.tv.column, '#0', **kw) - def test_delete(self): self.assertRaises(tkinter.TclError, self.tv.delete, '#0') @@ -1444,7 +1432,6 @@ def test_delete(self): self.tv.delete(item1, item2) self.assertFalse(self.tv.get_children()) - def test_detach_reattach(self): item_id = self.tv.insert('', 'end') item2 = self.tv.insert(item_id, 'end') @@ -1486,7 +1473,6 @@ def test_detach_reattach(self): self.assertEqual(self.tv.get_children(), ()) self.assertEqual(self.tv.get_children(item_id), ()) - def test_exists(self): self.assertEqual(self.tv.exists('something'), False) self.assertEqual(self.tv.exists(''), True) @@ -1497,7 +1483,6 @@ def test_exists(self): # in the tcl interpreter since tk requires an item. self.assertRaises(tkinter.TclError, self.tv.exists, None) - def test_focus(self): # nothing is focused right now self.assertEqual(self.tv.focus(), '') @@ -1512,7 +1497,6 @@ def test_focus(self): # try focusing inexistent item self.assertRaises(tkinter.TclError, self.tv.focus, 'hi') - def test_heading(self): # check a dict is returned self.assertIsInstance(self.tv.heading('#0'), dict) @@ -1564,7 +1548,6 @@ def simulate_heading_click(x, y): #self.tv.heading('#0', command='I dont exist') #simulate_heading_click(5, 5) - def test_index(self): # item 'what' doesn't exist self.assertRaises(tkinter.TclError, self.tv.index, 'what') @@ -1595,7 +1578,6 @@ def test_index(self): self.tv.delete(item1) self.assertRaises(tkinter.TclError, self.tv.index, c2) - def test_insert_item(self): # parent 'none' doesn't exist self.assertRaises(tkinter.TclError, self.tv.insert, 'none', 'end') @@ -1672,7 +1654,6 @@ def test_insert_item(self): self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', False) self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', '') - def test_selection(self): self.assertRaises(TypeError, self.tv.selection, 'spam') # item 'none' doesn't exist @@ -1743,7 +1724,6 @@ def test_selection(self): self.tv.selection_toggle((c1, c3)) self.assertEqual(self.tv.selection(), (c3, item2)) - def test_set(self): self.tv['columns'] = ['A', 'B'] item = self.tv.insert('', 'end', values=['a', 'b']) @@ -1776,7 +1756,6 @@ def test_set(self): # inexistent item self.assertRaises(tkinter.TclError, self.tv.set, 'notme') - def test_tag_bind(self): events = [] item1 = self.tv.insert('', 'end', tags=['call']) @@ -1809,7 +1788,6 @@ def test_tag_bind(self): for evt in zip(events[::2], events[1::2]): self.assertEqual(evt, (1, 2)) - def test_tag_configure(self): # Just testing parameter passing for now self.assertRaises(TypeError, self.tv.tag_configure) diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py index 7d24075403649c..44ecae1a326831 100644 --- a/Lib/tkinter/tix.py +++ b/Lib/tkinter/tix.py @@ -21,13 +21,20 @@ # Compare the demo tixwidgets.py to the original Tcl program and you will # appreciate the advantages. # +# NOTE: This module is deprecated since Python 3.6. import os +import warnings import tkinter from tkinter import * from tkinter import _cnfmerge -import _tkinter # If this fails your Python may not be configured for Tk +warnings.warn( + 'The Tix Tk extension is unmaintained, and the tkinter.tix wrapper module' + ' is deprecated in favor of tkinter.ttk', + DeprecationWarning, + stacklevel=2, + ) # Some more constants (for consistency with Tkinter) WINDOW = 'window' diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index b854235a626793..acdd565ec48a92 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1643,7 +1643,10 @@ def set_menu(self, default=None, *values): menu.delete(0, 'end') for val in values: menu.add_radiobutton(label=val, - command=tkinter._setit(self._variable, val, self._callback), + command=( + None if self._callback is None + else lambda val=val: self._callback(val) + ), variable=self._variable) if default: diff --git a/Lib/tokenize.py b/Lib/tokenize.py index 42c1f10373de9b..7d7736fe985981 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -604,7 +604,7 @@ def _tokenize(readline, encoding): pos += 1 # Add an implicit NEWLINE if the input doesn't end in one - if last_line and last_line[-1] not in '\r\n': + if last_line and last_line[-1] not in '\r\n' and not last_line.strip().startswith("#"): yield TokenInfo(NEWLINE, '', (lnum - 1, len(last_line)), (lnum - 1, len(last_line) + 1), '') for indent in indents[1:]: # pop remaining indent levels yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '') diff --git a/Lib/traceback.py b/Lib/traceback.py index 8f908dd2e09444..d6a010f4157582 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -84,8 +84,11 @@ def extract_tb(tb, limit=None): "another exception occurred:\n\n") -_sentinel = object() +class _Sentinel: + def __repr__(self): + return "" +_sentinel = _Sentinel() def _parse_value_tb(exc, value, tb): if (value is _sentinel) != (tb is _sentinel): @@ -298,9 +301,10 @@ def __len__(self): @property def line(self): if self._line is None: - self._line = linecache.getline(self.filename, self.lineno).strip() - return self._line - + if self.lineno is None: + return None + self._line = linecache.getline(self.filename, self.lineno) + return self._line.strip() def walk_stack(f): """Walk a stack yielding the frame and line number for each frame. @@ -471,10 +475,14 @@ class TracebackException: occurred. - :attr:`lineno` For syntax errors - the linenumber where the error occurred. + - :attr:`end_lineno` For syntax errors - the end linenumber where the error + occurred. Can be `None` if not present. - :attr:`text` For syntax errors - the text where the error occurred. - :attr:`offset` For syntax errors - the offset into the text where the error occurred. + - :attr:`end_offset` For syntax errors - the offset into the text where the + error occurred. Can be `None` if not present. - :attr:`msg` For syntax errors - the compiler error message. """ @@ -503,8 +511,11 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, self.filename = exc_value.filename lno = exc_value.lineno self.lineno = str(lno) if lno is not None else None + end_lno = exc_value.end_lineno + self.end_lineno = str(end_lno) if end_lno is not None else None self.text = exc_value.text self.offset = exc_value.offset + self.end_offset = exc_value.end_offset self.msg = exc_value.msg if lookup_lines: self._load_lines() @@ -593,6 +604,8 @@ def format_exception_only(self): stype = self.exc_type.__qualname__ smod = self.exc_type.__module__ if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" stype = smod + '.' + stype if not issubclass(self.exc_type, SyntaxError): @@ -619,12 +632,20 @@ def _format_syntax_error(self, stype): ltext = rtext.lstrip(' \n\f') spaces = len(rtext) - len(ltext) yield ' {}\n'.format(ltext) - # Convert 1-based column offset to 0-based index into stripped text - caret = (self.offset or 0) - 1 - spaces - if caret >= 0: - # non-space whitespace (likes tabs) must be kept for alignment - caretspace = ((c if c.isspace() else ' ') for c in ltext[:caret]) - yield ' {}^\n'.format(''.join(caretspace)) + + if self.offset is not None: + offset = self.offset + end_offset = self.end_offset if self.end_offset not in {None, 0} else offset + if offset == end_offset or end_offset == -1: + end_offset = offset + 1 + + # Convert 1-based column offset to 0-based index into stripped text + colno = offset - 1 - spaces + end_colno = end_offset - 1 - spaces + if colno >= 0: + # non-space whitespace (likes tabs) must be kept for alignment + caretspace = ((c if c.isspace() else ' ') for c in ltext[:colno]) + yield ' {}{}'.format("".join(caretspace), ('^' * (end_colno - colno) + "\n")) msg = self.msg or "" yield "{}: {}{}\n".format(stype, msg, filename_suffix) diff --git a/Lib/turtle.py b/Lib/turtle.py index 7d94720f8131d6..f3b320b90caebc 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -38,7 +38,7 @@ ----- turtle.py This module is an extended reimplementation of turtle.py from the -Python standard distribution up to Python 2.5. (See: http://www.python.org) +Python standard distribution up to Python 2.5. (See: https://www.python.org) It tries to keep the merits of turtle.py and to be (nearly) 100% compatible with it. This means in the first place to enable the @@ -2877,7 +2877,8 @@ def tiltangle(self, angle=None): between the orientation of the turtleshape and the heading of the turtle (its direction of movement). - Deprecated since Python 3.1 + (Incorrectly marked as deprecated since Python 3.1, it is really + settiltangle that is deprecated.) Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") diff --git a/Lib/turtledemo/__main__.py b/Lib/turtledemo/__main__.py index 12be5098dad274..caea022da4a688 100755 --- a/Lib/turtledemo/__main__.py +++ b/Lib/turtledemo/__main__.py @@ -124,7 +124,6 @@ def getExampleEntries(): ) - class DemoWindow(object): def __init__(self, filename=None): @@ -171,15 +170,23 @@ def __init__(self, filename=None): self.output_lbl = Label(root, height= 1, text=" --- ", bg="#ddf", font=("Arial", 16, 'normal'), borderwidth=2, relief=RIDGE) - self.start_btn = Button(root, text=" START ", font=btnfont, - fg="white", disabledforeground = "#fed", - command=self.startDemo) - self.stop_btn = Button(root, text=" STOP ", font=btnfont, - fg="white", disabledforeground = "#fed", - command=self.stopIt) - self.clear_btn = Button(root, text=" CLEAR ", font=btnfont, - fg="white", disabledforeground="#fed", - command = self.clearCanvas) + if darwin: # Leave Mac button colors alone - #44254. + self.start_btn = Button(root, text=" START ", font=btnfont, + fg='#00cc22', command=self.startDemo) + self.stop_btn = Button(root, text=" STOP ", font=btnfont, + fg='#00cc22', command=self.stopIt) + self.clear_btn = Button(root, text=" CLEAR ", font=btnfont, + fg='#00cc22', command = self.clearCanvas) + else: + self.start_btn = Button(root, text=" START ", font=btnfont, + fg="white", disabledforeground = "#fed", + command=self.startDemo) + self.stop_btn = Button(root, text=" STOP ", font=btnfont, + fg="white", disabledforeground = "#fed", + command=self.stopIt) + self.clear_btn = Button(root, text=" CLEAR ", font=btnfont, + fg="white", disabledforeground="#fed", + command = self.clearCanvas) self.output_lbl.grid(row=1, column=0, sticky='news', padx=(0,5)) self.start_btn.grid(row=1, column=1, sticky='ew') self.stop_btn.grid(row=1, column=2, sticky='ew') @@ -267,12 +274,17 @@ def update_mousewheel(self, event): return self.increase_size() def configGUI(self, start, stop, clear, txt="", color="blue"): - self.start_btn.config(state=start, - bg="#d00" if start == NORMAL else "#fca") - self.stop_btn.config(state=stop, - bg="#d00" if stop == NORMAL else "#fca") - self.clear_btn.config(state=clear, - bg="#d00" if clear == NORMAL else "#fca") + if darwin: # Leave Mac button colors alone - #44254. + self.start_btn.config(state=start) + self.stop_btn.config(state=stop) + self.clear_btn.config(state=clear) + else: + self.start_btn.config(state=start, + bg="#d00" if start == NORMAL else "#fca") + self.stop_btn.config(state=stop, + bg="#d00" if stop == NORMAL else "#fca") + self.clear_btn.config(state=clear, + bg="#d00" if clear == NORMAL else "#fca") self.output_lbl.config(text=txt, fg=color) def makeLoadDemoMenu(self, master): diff --git a/Lib/types.py b/Lib/types.py index c509b242d5d8f3..62122a994866fe 100644 --- a/Lib/types.py +++ b/Lib/types.py @@ -82,7 +82,7 @@ def resolve_bases(bases): updated = False shift = 0 for i, base in enumerate(bases): - if isinstance(base, type): + if isinstance(base, type) and not isinstance(base, GenericAlias): continue if not hasattr(base, "__mro_entries__"): continue @@ -297,9 +297,8 @@ def wrapped(*args, **kwargs): return wrapped - GenericAlias = type(list[int]) -Union = type(int | str) +UnionType = type(int | str) EllipsisType = type(Ellipsis) NoneType = type(None) diff --git a/Lib/typing.py b/Lib/typing.py index ff964343c5336a..25225470afbac2 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -100,6 +100,13 @@ 'TypedDict', # Not really a type. 'Generator', + # Other concrete types. + 'BinaryIO', + 'IO', + 'Match', + 'Pattern', + 'TextIO', + # One-off things. 'AnyStr', 'cast', @@ -127,16 +134,16 @@ # legitimate imports of those modules. -def _type_convert(arg): +def _type_convert(arg, module=None): """For converting None to type(None), and strings to ForwardRef.""" if arg is None: return type(None) if isinstance(arg, str): - return ForwardRef(arg) + return ForwardRef(arg, module=module) return arg -def _type_check(arg, msg, is_argument=True): +def _type_check(arg, msg, is_argument=True, module=None, *, is_class=False): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -149,24 +156,31 @@ def _type_check(arg, msg, is_argument=True): We append the repr() of the actual value (truncated to 100 chars). """ invalid_generic_forms = (Generic, Protocol) - if is_argument: - invalid_generic_forms = invalid_generic_forms + (ClassVar, Final) + if not is_class: + invalid_generic_forms += (ClassVar,) + if is_argument: + invalid_generic_forms += (Final,) - arg = _type_convert(arg) + arg = _type_convert(arg, module=module) if (isinstance(arg, _GenericAlias) and arg.__origin__ in invalid_generic_forms): raise TypeError(f"{arg} is not valid as type argument") - if arg in (Any, NoReturn): + if arg in (Any, NoReturn, Final): return arg if isinstance(arg, _SpecialForm) or arg in (Generic, Protocol): raise TypeError(f"Plain {arg} is not valid as type argument") - if isinstance(arg, (type, TypeVar, ForwardRef, types.Union, ParamSpec)): + if isinstance(arg, (type, TypeVar, ForwardRef, types.UnionType, ParamSpec)): return arg if not callable(arg): raise TypeError(f"{msg} Got {arg!r:.100}.") return arg +def _is_param_expr(arg): + return arg is ... or isinstance(arg, + (tuple, list, ParamSpec, _ConcatenateGenericAlias)) + + def _type_repr(obj): """Return the repr() of an object, special-casing types (internal helper). @@ -188,17 +202,19 @@ def _type_repr(obj): return repr(obj) -def _collect_type_vars(types): - """Collect all type variable-like variables contained +def _collect_type_vars(types_, typevar_types=None): + """Collect all type variable contained in types in order of first appearance (lexicographic order). For example:: _collect_type_vars((T, List[S, T])) == (T, S) """ + if typevar_types is None: + typevar_types = TypeVar tvars = [] - for t in types: - if isinstance(t, _TypeVarLike) and t not in tvars: + for t in types_: + if isinstance(t, typevar_types) and t not in tvars: tvars.append(t) - if isinstance(t, (_GenericAlias, GenericAlias)): + if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)): tvars.extend([t for t in t.__parameters__ if t not in tvars]) return tuple(tvars) @@ -211,7 +227,7 @@ def _check_generic(cls, parameters, elen): raise TypeError(f"{cls} is not a generic class") alen = len(parameters) if alen != elen: - raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};" + raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};" f" actual {alen}, expected {elen}") def _prepare_paramspec_params(cls, params): @@ -219,9 +235,12 @@ def _prepare_paramspec_params(cls, params): variables (internal helper). """ # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. - if len(cls.__parameters__) == 1 and len(params) > 1: + if (len(cls.__parameters__) == 1 + and params and not _is_param_expr(params[0])): + assert isinstance(cls.__parameters__[0], ParamSpec) return (params,) else: + _check_generic(cls, params, len(cls.__parameters__)) _params = [] # Convert lists to tuples to help other libraries cache the results. for p, tvar in zip(params, cls.__parameters__): @@ -251,7 +270,7 @@ def _remove_dups_flatten(parameters): # Flatten out Union[Union[...], ...]. params = [] for p in parameters: - if isinstance(p, (_UnionGenericAlias, types.Union)): + if isinstance(p, (_UnionGenericAlias, types.UnionType)): params.extend(p.__args__) elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union: params.extend(p[1:]) @@ -305,12 +324,14 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()): """ if isinstance(t, ForwardRef): return t._evaluate(globalns, localns, recursive_guard) - if isinstance(t, (_GenericAlias, GenericAlias)): + if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)): ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__) if ev_args == t.__args__: return t if isinstance(t, GenericAlias): return GenericAlias(t.__origin__, ev_args) + if isinstance(t, types.UnionType): + return functools.reduce(operator.or_, ev_args) else: return t.copy_with(ev_args) return t @@ -346,6 +367,12 @@ def __init__(self, getitem): self._name = getitem.__name__ self.__doc__ = getitem.__doc__ + def __getattr__(self, item): + if item in {'__name__', '__qualname__'}: + return self._name + + raise AttributeError(item) + def __mro_entries__(self, bases): raise TypeError(f"Cannot subclass {self!r}") @@ -358,6 +385,12 @@ def __reduce__(self): def __call__(self, *args, **kwds): raise TypeError(f"Cannot instantiate {self!r}") + def __or__(self, other): + return Union[self, other] + + def __ror__(self, other): + return Union[other, self] + def __instancecheck__(self, obj): raise TypeError(f"{self} cannot be used with isinstance()") @@ -370,9 +403,10 @@ def __getitem__(self, parameters): class _LiteralSpecialForm(_SpecialForm, _root=True): - @_tp_cache(typed=True) def __getitem__(self, parameters): - return self._getitem(self, parameters) + if not isinstance(parameters, tuple): + parameters = (parameters,) + return self._getitem(self, *parameters) @_SpecialForm @@ -481,6 +515,8 @@ def Union(self, parameters): parameters = _remove_dups_flatten(parameters) if len(parameters) == 1: return parameters[0] + if len(parameters) == 2 and type(None) in parameters: + return _UnionGenericAlias(self, parameters, name="Optional") return _UnionGenericAlias(self, parameters) @_SpecialForm @@ -493,7 +529,8 @@ def Optional(self, parameters): return Union[arg, type(None)] @_LiteralSpecialForm -def Literal(self, parameters): +@_tp_cache(typed=True) +def Literal(self, *parameters): """Special typing form to define literal types (a.k.a. value types). This form can be used to indicate to type checkers that the corresponding @@ -516,9 +553,6 @@ def open_helper(file: str, mode: MODE) -> str: """ # There is no '_type_check' call because arguments to Literal[...] are # values, not types. - if not isinstance(parameters, tuple): - parameters = (parameters,) - parameters = _flatten_literal_params(parameters) try: @@ -621,9 +655,10 @@ class ForwardRef(_Final, _root=True): __slots__ = ('__forward_arg__', '__forward_code__', '__forward_evaluated__', '__forward_value__', - '__forward_is_argument__') + '__forward_is_argument__', '__forward_is_class__', + '__forward_module__') - def __init__(self, arg, is_argument=True): + def __init__(self, arg, is_argument=True, module=None, *, is_class=False): if not isinstance(arg, str): raise TypeError(f"Forward reference must be a string -- got {arg!r}") try: @@ -635,6 +670,8 @@ def __init__(self, arg, is_argument=True): self.__forward_evaluated__ = False self.__forward_value__ = None self.__forward_is_argument__ = is_argument + self.__forward_is_class__ = is_class + self.__forward_module__ = module def _evaluate(self, globalns, localns, recursive_guard): if self.__forward_arg__ in recursive_guard: @@ -646,10 +683,15 @@ def _evaluate(self, globalns, localns, recursive_guard): globalns = localns elif localns is None: localns = globalns - type_ =_type_check( + if self.__forward_module__ is not None: + globalns = getattr( + sys.modules.get(self.__forward_module__, None), '__dict__', globalns + ) + type_ = _type_check( eval(self.__forward_code__, globalns, localns), "Forward references must evaluate to types.", is_argument=self.__forward_is_argument__, + is_class=self.__forward_is_class__, ) self.__forward_value__ = _eval_type( type_, globalns, localns, recursive_guard | {self.__forward_arg__} @@ -918,6 +960,9 @@ def __mro_entries__(self, bases): return tuple(res) def __getattr__(self, attr): + if attr in {'__name__', '__qualname__'}: + return self._name or self.__origin__.__name__ + # We are careful for copy and pickle. # Also for simplicity we just don't relay all dunder names if '__origin__' in self.__dict__ and not _is_dunder(attr): @@ -925,7 +970,8 @@ def __getattr__(self, attr): raise AttributeError(attr) def __setattr__(self, attr, val): - if _is_dunder(attr) or attr in ('_name', '_inst', '_nparams'): + if _is_dunder(attr) or attr in {'_name', '_inst', '_nparams', + '_typevar_types', '_paramspec_tvars'}: super().__setattr__(attr, val) else: setattr(self.__origin__, attr, val) @@ -937,6 +983,9 @@ def __subclasscheck__(self, cls): raise TypeError("Subscripted generics cannot be used with" " class and instance checks") + def __dir__(self): + return list(set(super().__dir__() + + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)])) # Special typing constructs Union, Optional, Generic, Callable and Tuple # use three special attributes for internal bookkeeping of generic types: @@ -950,14 +999,18 @@ def __subclasscheck__(self, cls): class _GenericAlias(_BaseGenericAlias, _root=True): - def __init__(self, origin, params, *, inst=True, name=None): + def __init__(self, origin, params, *, inst=True, name=None, + _typevar_types=TypeVar, + _paramspec_tvars=False): super().__init__(origin, inst=inst, name=name) if not isinstance(params, tuple): params = (params,) self.__args__ = tuple(... if a is _TypingEllipsis else () if a is _TypingEmpty else a for a in params) - self.__parameters__ = _collect_type_vars(params) + self.__parameters__ = _collect_type_vars(params, typevar_types=_typevar_types) + self._typevar_types = _typevar_types + self._paramspec_tvars = _paramspec_tvars if not name: self.__module__ = origin.__module__ @@ -973,8 +1026,8 @@ def __hash__(self): def __or__(self, right): return Union[self, right] - def __ror__(self, right): - return Union[self, right] + def __ror__(self, left): + return Union[left, self] @_tp_cache def __getitem__(self, params): @@ -984,16 +1037,24 @@ def __getitem__(self, params): if not isinstance(params, tuple): params = (params,) params = tuple(_type_convert(p) for p in params) - if any(isinstance(t, ParamSpec) for t in self.__parameters__): + if (self._paramspec_tvars + and any(isinstance(t, ParamSpec) for t in self.__parameters__)): params = _prepare_paramspec_params(self, params) - _check_generic(self, params, len(self.__parameters__)) + else: + _check_generic(self, params, len(self.__parameters__)) subst = dict(zip(self.__parameters__, params)) new_args = [] for arg in self.__args__: - if isinstance(arg, _TypeVarLike): - arg = subst[arg] - elif isinstance(arg, (_GenericAlias, GenericAlias)): + if isinstance(arg, self._typevar_types): + if isinstance(arg, ParamSpec): + arg = subst[arg] + if not _is_param_expr(arg): + raise TypeError(f"Expected a list of types, an ellipsis, " + f"ParamSpec, or Concatenate. Got {arg}") + else: + arg = subst[arg] + elif isinstance(arg, (_GenericAlias, GenericAlias, types.UnionType)): subparams = arg.__parameters__ if subparams: subargs = tuple(subst[x] for x in subparams) @@ -1027,6 +1088,9 @@ def __reduce__(self): return operator.getitem, (origin, args) def __mro_entries__(self, bases): + if isinstance(self.__origin__, _SpecialForm): + raise TypeError(f"Cannot subclass {self!r}") + if self._name: # generic version of an ABC or built-in class return super().__mro_entries__(bases) if self.__origin__ is Generic: @@ -1083,15 +1147,14 @@ def __reduce__(self): def __or__(self, right): return Union[self, right] - def __ror__(self, right): - return Union[self, right] + def __ror__(self, left): + return Union[left, self] class _CallableGenericAlias(_GenericAlias, _root=True): def __repr__(self): assert self._name == 'Callable' args = self.__args__ - if len(args) == 2 and (args[0] is Ellipsis - or isinstance(args[0], (ParamSpec, _ConcatenateGenericAlias))): + if len(args) == 2 and _is_param_expr(args[0]): return super().__repr__() return (f'typing.Callable' f'[[{", ".join([_type_repr(a) for a in args[:-1]])}], ' @@ -1099,8 +1162,7 @@ def __repr__(self): def __reduce__(self): args = self.__args__ - if not (len(args) == 2 and (args[0] is Ellipsis - or isinstance(args[0], (ParamSpec, _ConcatenateGenericAlias)))): + if not (len(args) == 2 and _is_param_expr(args[0])): args = list(args[:-1]), args[-1] return operator.getitem, (Callable, args) @@ -1108,7 +1170,9 @@ def __reduce__(self): class _CallableType(_SpecialGenericAlias, _root=True): def copy_with(self, params): return _CallableGenericAlias(self.__origin__, params, - name=self._name, inst=self._inst) + name=self._name, inst=self._inst, + _typevar_types=(TypeVar, ParamSpec), + _paramspec_tvars=True) def __getitem__(self, params): if not isinstance(params, tuple) or len(params) != 2: @@ -1159,7 +1223,7 @@ def copy_with(self, params): return Union[params] def __eq__(self, other): - if not isinstance(other, _UnionGenericAlias): + if not isinstance(other, (_UnionGenericAlias, types.UnionType)): return NotImplemented return set(self.__args__) == set(other.__args__) @@ -1183,6 +1247,10 @@ def __subclasscheck__(self, cls): if issubclass(cls, arg): return True + def __reduce__(self): + func, (origin, args) = super().__reduce__() + return func, (Union, args) + def _value_and_type_iter(parameters): return ((p, type(p)) for p in parameters) @@ -1201,7 +1269,10 @@ def __hash__(self): class _ConcatenateGenericAlias(_GenericAlias, _root=True): - pass + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs, + _typevar_types=(TypeVar, ParamSpec), + _paramspec_tvars=True) class Generic: @@ -1237,7 +1308,7 @@ def __class_getitem__(cls, params): params = tuple(_type_convert(p) for p in params) if cls in (Generic, Protocol): # Generic and Protocol can only be subscripted with unique type variables. - if not all(isinstance(p, _TypeVarLike) for p in params): + if not all(isinstance(p, (TypeVar, ParamSpec)) for p in params): raise TypeError( f"Parameters to {cls.__name__}[...] must all be type variables " f"or parameter specification variables.") @@ -1248,8 +1319,11 @@ def __class_getitem__(cls, params): # Subscripting a regular Generic subclass. if any(isinstance(t, ParamSpec) for t in cls.__parameters__): params = _prepare_paramspec_params(cls, params) - _check_generic(cls, params, len(cls.__parameters__)) - return _GenericAlias(cls, params) + else: + _check_generic(cls, params, len(cls.__parameters__)) + return _GenericAlias(cls, params, + _typevar_types=(TypeVar, ParamSpec), + _paramspec_tvars=True) def __init_subclass__(cls, *args, **kwargs): super().__init_subclass__(*args, **kwargs) @@ -1261,7 +1335,7 @@ def __init_subclass__(cls, *args, **kwargs): if error: raise TypeError("Cannot inherit from plain Generic") if '__orig_bases__' in cls.__dict__: - tvars = _collect_type_vars(cls.__orig_bases__) + tvars = _collect_type_vars(cls.__orig_bases__, (TypeVar, ParamSpec)) # Look for Generic[T1, ..., Tn]. # If found, tvars must be a subset of it. # If not found, tvars is it. @@ -1331,19 +1405,50 @@ def _is_callable_members_only(cls): return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls)) -def _no_init(self, *args, **kwargs): - if type(self)._is_protocol: +def _no_init_or_replace_init(self, *args, **kwargs): + cls = type(self) + + if cls._is_protocol: raise TypeError('Protocols cannot be instantiated') + # Already using a custom `__init__`. No need to calculate correct + # `__init__` to call. This can lead to RecursionError. See bpo-45121. + if cls.__init__ is not _no_init_or_replace_init: + return + + # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`. + # The first instantiation of the subclass will call `_no_init_or_replace_init` which + # searches for a proper new `__init__` in the MRO. The new `__init__` + # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent + # instantiation of the protocol subclass will thus use the new + # `__init__` and no longer call `_no_init_or_replace_init`. + for base in cls.__mro__: + init = base.__dict__.get('__init__', _no_init_or_replace_init) + if init is not _no_init_or_replace_init: + cls.__init__ = init + break + else: + # should not happen + cls.__init__ = object.__init__ + + cls.__init__(self, *args, **kwargs) + + +def _caller(depth=1, default='__main__'): + try: + return sys._getframe(depth + 1).f_globals.get('__name__', default) + except (AttributeError, ValueError): # For platforms without _getframe() + return None + -def _allow_reckless_class_checks(): +def _allow_reckless_class_checks(depth=3): """Allow instance and class checks for special stdlib modules. The abc and functools modules indiscriminately call isinstance() and issubclass() on the whole MRO of a user class, which may contain protocols. """ try: - return sys._getframe(3).f_globals['__name__'] in ['abc', 'functools'] + return sys._getframe(depth).f_globals['__name__'] in ['abc', 'functools'] except (AttributeError, ValueError): # For platforms without _getframe(). return True @@ -1363,6 +1468,14 @@ class _ProtocolMeta(ABCMeta): def __instancecheck__(cls, instance): # We need this method for situations where attributes are # assigned in __init__. + if ( + getattr(cls, '_is_protocol', False) and + not getattr(cls, '_is_runtime_protocol', False) and + not _allow_reckless_class_checks(depth=2) + ): + raise TypeError("Instance and class checks can only be used with" + " @runtime_checkable protocols") + if ((not getattr(cls, '_is_protocol', False) or _is_callable_members_only(cls)) and issubclass(instance.__class__, cls)): @@ -1472,7 +1585,7 @@ def _proto_hook(other): issubclass(base, Generic) and base._is_protocol): raise TypeError('Protocols can only inherit from other' ' protocols, got %r' % base) - cls.__init__ = _no_init + cls.__init__ = _no_init_or_replace_init class _AnnotatedAlias(_GenericAlias, _root=True): @@ -1515,6 +1628,11 @@ def __eq__(self, other): def __hash__(self): return hash((self.__origin__, self.__metadata__)) + def __getattr__(self, attr): + if attr in {'__name__', '__qualname__'}: + return 'Annotated' + return super().__getattr__(attr) + class Annotated: """Add context specific metadata to a type. @@ -1670,10 +1788,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): hints = {} for base in reversed(obj.__mro__): if globalns is None: - try: - base_globals = sys.modules[base.__module__].__dict__ - except KeyError: - continue + base_globals = getattr(sys.modules.get(base.__module__, None), '__dict__', {}) else: base_globals = globalns ann = base.__dict__.get('__annotations__', {}) @@ -1692,7 +1807,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value, is_argument=False) + value = ForwardRef(value, is_argument=False, is_class=True) value = _eval_type(value, base_globals, base_locals) hints[name] = value return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} @@ -1724,7 +1839,13 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value) + # class-level forward refs were handled above, this must be either + # a module-level annotation or a function argument annotation + value = ForwardRef( + value, + is_argument=not isinstance(obj, types.ModuleType), + is_class=False, + ) value = _eval_type(value, globalns, localns) if name in defaults and defaults[name] is None: value = Optional[value] @@ -1747,6 +1868,12 @@ def _strip_annotations(t): if stripped_args == t.__args__: return t return GenericAlias(t.__origin__, stripped_args) + if isinstance(t, types.UnionType): + stripped_args = tuple(_strip_annotations(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return functools.reduce(operator.or_, stripped_args) + return t @@ -1772,8 +1899,8 @@ def get_origin(tp): return tp.__origin__ if tp is Generic: return Generic - if isinstance(tp, types.Union): - return types.Union + if isinstance(tp, types.UnionType): + return types.UnionType return None @@ -1793,11 +1920,10 @@ def get_args(tp): if isinstance(tp, (_GenericAlias, GenericAlias)): res = tp.__args__ if (tp.__origin__ is collections.abc.Callable - and not (res[0] is Ellipsis - or isinstance(res[0], (ParamSpec, _ConcatenateGenericAlias)))): + and not (len(res) == 2 and _is_param_expr(res[0]))): res = (list(res[:-1]), res[-1]) return res - if isinstance(tp, types.Union): + if isinstance(tp, types.UnionType): return tp.__args__ return () @@ -2206,7 +2332,8 @@ def __new__(cls, name, bases, ns, total=True): own_annotation_keys = set(own_annotations.keys()) msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" own_annotations = { - n: _type_check(tp, msg) for n, tp in own_annotations.items() + n: _type_check(tp, msg, module=tp_dict.__module__) + for n, tp in own_annotations.items() } required_keys = set() optional_keys = set() @@ -2299,11 +2426,11 @@ class body be required. TypedDict.__mro_entries__ = lambda bases: (_TypedDict,) -def NewType(name, tp): +class NewType: """NewType creates simple unique types with almost zero runtime overhead. NewType(name, tp) is considered a subtype of tp by static type checkers. At runtime, NewType(name, tp) returns - a dummy function that simply returns its argument. Usage:: + a dummy callable that simply returns its argument. Usage:: UserId = NewType('UserId', int) @@ -2318,12 +2445,30 @@ def name_by_id(user_id: UserId) -> str: num = UserId(5) + 1 # type: int """ - def new_type(x): + def __init__(self, name, tp): + self.__qualname__ = name + if '.' in name: + name = name.rpartition('.')[-1] + self.__name__ = name + self.__supertype__ = tp + def_mod = _caller() + if def_mod != 'typing': + self.__module__ = def_mod + + def __repr__(self): + return f'{self.__module__}.{self.__qualname__}' + + def __call__(self, x): return x - new_type.__name__ = name - new_type.__supertype__ = tp - return new_type + def __reduce__(self): + return self.__qualname__ + + def __or__(self, other): + return Union[self, other] + + def __ror__(self, other): + return Union[other, self] # Python-version-specific alias (Python 2: unicode; Python 3: str) diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index 520213c3727555..23231199f98706 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -4,7 +4,6 @@ from .case import TestCase - class IsolatedAsyncioTestCase(TestCase): # Names intentionally have a long prefix # to reduce a chance of clashing with user-defined attributes @@ -52,7 +51,7 @@ def addAsyncCleanup(self, func, /, *args, **kwargs): # We intentionally don't add inspect.iscoroutinefunction() check # for func argument because there is no way # to check for async function reliably: - # 1. It can be "async def func()" iself + # 1. It can be "async def func()" itself # 2. Class can implement "async def __call__()" method # 3. Regular "def func()" that returns awaitable object self.addCleanup(*(func, *args), **kwargs) @@ -72,15 +71,15 @@ def _callCleanup(self, function, *args, **kwargs): self._callMaybeAsync(function, *args, **kwargs) def _callAsync(self, func, /, *args, **kwargs): - assert self._asyncioTestLoop is not None + assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized' ret = func(*args, **kwargs) - assert inspect.isawaitable(ret) + assert inspect.isawaitable(ret), f'{func!r} returned non-awaitable' fut = self._asyncioTestLoop.create_future() self._asyncioCallsQueue.put_nowait((fut, ret)) return self._asyncioTestLoop.run_until_complete(fut) def _callMaybeAsync(self, func, /, *args, **kwargs): - assert self._asyncioTestLoop is not None + assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized' ret = func(*args, **kwargs) if inspect.isawaitable(ret): fut = self._asyncioTestLoop.create_future() @@ -109,7 +108,7 @@ async def _asyncioLoopRunner(self, fut): fut.set_exception(ex) def _setupAsyncioLoop(self): - assert self._asyncioTestLoop is None + assert self._asyncioTestLoop is None, 'asyncio test loop already initialized' loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.set_debug(True) @@ -119,7 +118,7 @@ def _setupAsyncioLoop(self): loop.run_until_complete(fut) def _tearDownAsyncioLoop(self): - assert self._asyncioTestLoop is not None + assert self._asyncioTestLoop is not None, 'asyncio test loop is not initialized' loop = self._asyncioTestLoop self._asyncioTestLoop = None self._asyncioCallsQueue.put_nowait(None) @@ -135,7 +134,7 @@ def _tearDownAsyncioLoop(self): task.cancel() loop.run_until_complete( - asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)) + asyncio.gather(*to_cancel, return_exceptions=True)) for task in to_cancel: if task.cancelled(): @@ -158,3 +157,12 @@ def run(self, result=None): return super().run(result) finally: self._tearDownAsyncioLoop() + + def debug(self): + self._setupAsyncioLoop() + super().debug() + self._tearDownAsyncioLoop() + + def __del__(self): + if self._asyncioTestLoop is not None: + self._tearDownAsyncioLoop() diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 872f12112755e9..61003d0c6ead93 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -555,73 +555,71 @@ def _callCleanup(self, function, /, *args, **kwargs): function(*args, **kwargs) def run(self, result=None): - orig_result = result if result is None: result = self.defaultTestResult() startTestRun = getattr(result, 'startTestRun', None) + stopTestRun = getattr(result, 'stopTestRun', None) if startTestRun is not None: startTestRun() + else: + stopTestRun = None result.startTest(self) - - testMethod = getattr(self, self._testMethodName) - if (getattr(self.__class__, "__unittest_skip__", False) or - getattr(testMethod, "__unittest_skip__", False)): - # If the class or method was skipped. - try: + try: + testMethod = getattr(self, self._testMethodName) + if (getattr(self.__class__, "__unittest_skip__", False) or + getattr(testMethod, "__unittest_skip__", False)): + # If the class or method was skipped. skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') or getattr(testMethod, '__unittest_skip_why__', '')) self._addSkip(result, self, skip_why) - finally: - result.stopTest(self) - return - expecting_failure_method = getattr(testMethod, - "__unittest_expecting_failure__", False) - expecting_failure_class = getattr(self, - "__unittest_expecting_failure__", False) - expecting_failure = expecting_failure_class or expecting_failure_method - outcome = _Outcome(result) - try: - self._outcome = outcome + return result + + expecting_failure = ( + getattr(self, "__unittest_expecting_failure__", False) or + getattr(testMethod, "__unittest_expecting_failure__", False) + ) + outcome = _Outcome(result) + try: + self._outcome = outcome - with outcome.testPartExecutor(self): - self._callSetUp() - if outcome.success: - outcome.expecting_failure = expecting_failure - with outcome.testPartExecutor(self, isTest=True): - self._callTestMethod(testMethod) - outcome.expecting_failure = False with outcome.testPartExecutor(self): - self._callTearDown() - - self.doCleanups() - for test, reason in outcome.skipped: - self._addSkip(result, test, reason) - self._feedErrorsToResult(result, outcome.errors) - if outcome.success: - if expecting_failure: - if outcome.expectedFailure: - self._addExpectedFailure(result, outcome.expectedFailure) + self._callSetUp() + if outcome.success: + outcome.expecting_failure = expecting_failure + with outcome.testPartExecutor(self, isTest=True): + self._callTestMethod(testMethod) + outcome.expecting_failure = False + with outcome.testPartExecutor(self): + self._callTearDown() + + self.doCleanups() + for test, reason in outcome.skipped: + self._addSkip(result, test, reason) + self._feedErrorsToResult(result, outcome.errors) + if outcome.success: + if expecting_failure: + if outcome.expectedFailure: + self._addExpectedFailure(result, outcome.expectedFailure) + else: + self._addUnexpectedSuccess(result) else: - self._addUnexpectedSuccess(result) - else: - result.addSuccess(self) - return result - finally: - result.stopTest(self) - if orig_result is None: - stopTestRun = getattr(result, 'stopTestRun', None) - if stopTestRun is not None: - stopTestRun() + result.addSuccess(self) + return result + finally: + # explicitly break reference cycles: + # outcome.errors -> frame -> outcome -> outcome.errors + # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure + outcome.errors.clear() + outcome.expectedFailure = None - # explicitly break reference cycles: - # outcome.errors -> frame -> outcome -> outcome.errors - # outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure - outcome.errors.clear() - outcome.expectedFailure = None + # clear the outcome, no more needed + self._outcome = None - # clear the outcome, no more needed - self._outcome = None + finally: + result.stopTest(self) + if stopTestRun is not None: + stopTestRun() def doCleanups(self): """Execute all cleanup functions. Normally called for you after @@ -653,12 +651,20 @@ def __call__(self, *args, **kwds): def debug(self): """Run the test without collecting errors in a TestResult""" - self.setUp() - getattr(self, self._testMethodName)() - self.tearDown() + testMethod = getattr(self, self._testMethodName) + if (getattr(self.__class__, "__unittest_skip__", False) or + getattr(testMethod, "__unittest_skip__", False)): + # If the class or method was skipped. + skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') + or getattr(testMethod, '__unittest_skip_why__', '')) + raise SkipTest(skip_why) + + self._callSetUp() + self._callTestMethod(testMethod) + self._callTearDown() while self._cleanups: - function, args, kwargs = self._cleanups.pop(-1) - function(*args, **kwargs) + function, args, kwargs = self._cleanups.pop() + self._callCleanup(function, *args, **kwargs) def skipTest(self, reason): """Skip this test.""" @@ -1140,7 +1146,8 @@ def assertDictEqual(self, d1, d2, msg=None): def assertDictContainsSubset(self, subset, dictionary, msg=None): """Checks whether dictionary is a superset of subset.""" warnings.warn('assertDictContainsSubset is deprecated', - DeprecationWarning) + DeprecationWarning, + stacklevel=2) missing = [] mismatched = [] for key, value in subset.items(): diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index c6067151de14fe..6226bd4bc0c195 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1004,6 +1004,11 @@ def _get_child_mock(self, /, **kw): if _new_name in self.__dict__['_spec_asyncs']: return AsyncMock(**kw) + if self._mock_sealed: + attribute = f".{kw['name']}" if "name" in kw else "()" + mock_name = self._extract_mock_name() + attribute + raise AttributeError(mock_name) + _type = type(self) if issubclass(_type, MagicMock) and _new_name in _async_method_magics: # Any asynchronous magic becomes an AsyncMock @@ -1022,12 +1027,6 @@ def _get_child_mock(self, /, **kw): klass = Mock else: klass = _type.__mro__[1] - - if self._mock_sealed: - attribute = "." + kw["name"] if "name" in kw else "()" - mock_name = self._extract_mock_name() + attribute - raise AttributeError(mock_name) - return klass(**kw) @@ -2927,6 +2926,8 @@ def seal(mock): continue if not isinstance(m, NonCallableMock): continue + if isinstance(m._mock_children.get(attr), _SpecState): + continue if m._mock_new_parent is mock: seal(m) diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py index 45e7e4c0458d4c..caf159002d8bb6 100644 --- a/Lib/unittest/runner.py +++ b/Lib/unittest/runner.py @@ -59,6 +59,7 @@ def addSuccess(self, test): super(TextTestResult, self).addSuccess(test) if self.showAll: self.stream.writeln("ok") + self.stream.flush() elif self.dots: self.stream.write('.') self.stream.flush() @@ -67,6 +68,7 @@ def addError(self, test, err): super(TextTestResult, self).addError(test, err) if self.showAll: self.stream.writeln("ERROR") + self.stream.flush() elif self.dots: self.stream.write('E') self.stream.flush() @@ -75,6 +77,7 @@ def addFailure(self, test, err): super(TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.writeln("FAIL") + self.stream.flush() elif self.dots: self.stream.write('F') self.stream.flush() @@ -83,6 +86,7 @@ def addSkip(self, test, reason): super(TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.writeln("skipped {0!r}".format(reason)) + self.stream.flush() elif self.dots: self.stream.write("s") self.stream.flush() @@ -91,6 +95,7 @@ def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.writeln("expected failure") + self.stream.flush() elif self.dots: self.stream.write("x") self.stream.flush() @@ -99,6 +104,7 @@ def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.writeln("unexpected success") + self.stream.flush() elif self.dots: self.stream.write("u") self.stream.flush() @@ -106,6 +112,7 @@ def addUnexpectedSuccess(self, test): def printErrors(self): if self.dots or self.showAll: self.stream.writeln() + self.stream.flush() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) @@ -115,6 +122,7 @@ def printErrorList(self, flavour, errors): self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) + self.stream.flush() class TextTestRunner(object): @@ -218,4 +226,5 @@ def run(self, test): self.stream.writeln(" (%s)" % (", ".join(infos),)) else: self.stream.write("\n") + self.stream.flush() return result diff --git a/Lib/unittest/suite.py b/Lib/unittest/suite.py index 41993f9cf69afc..6f45b6fe5f6039 100644 --- a/Lib/unittest/suite.py +++ b/Lib/unittest/suite.py @@ -149,6 +149,7 @@ def _handleClassSetUp(self, test, result): if getattr(currentClass, "__unittest_skip__", False): return + failed = False try: currentClass._classSetupFailed = False except TypeError: @@ -157,27 +158,32 @@ def _handleClassSetUp(self, test, result): pass setUpClass = getattr(currentClass, 'setUpClass', None) + doClassCleanups = getattr(currentClass, 'doClassCleanups', None) if setUpClass is not None: _call_if_exists(result, '_setupStdout') try: - setUpClass() - except Exception as e: - if isinstance(result, _DebugResult): - raise - currentClass._classSetupFailed = True - className = util.strclass(currentClass) - self._createClassOrModuleLevelException(result, e, - 'setUpClass', - className) + try: + setUpClass() + except Exception as e: + if isinstance(result, _DebugResult): + raise + failed = True + try: + currentClass._classSetupFailed = True + except TypeError: + pass + className = util.strclass(currentClass) + self._createClassOrModuleLevelException(result, e, + 'setUpClass', + className) + if failed and doClassCleanups is not None: + doClassCleanups() + for exc_info in currentClass.tearDown_exceptions: + self._createClassOrModuleLevelException( + result, exc_info[1], 'setUpClass', className, + info=exc_info) finally: _call_if_exists(result, '_restoreStdout') - if currentClass._classSetupFailed is True: - currentClass.doClassCleanups() - if len(currentClass.tearDown_exceptions) > 0: - for exc in currentClass.tearDown_exceptions: - self._createClassOrModuleLevelException( - result, exc[1], 'setUpClass', className, - info=exc) def _get_previous_module(self, result): previousModule = None @@ -205,20 +211,22 @@ def _handleModuleFixture(self, test, result): if setUpModule is not None: _call_if_exists(result, '_setupStdout') try: - setUpModule() - except Exception as e: try: - case.doModuleCleanups() - except Exception as exc: - self._createClassOrModuleLevelException(result, exc, + setUpModule() + except Exception as e: + if isinstance(result, _DebugResult): + raise + result._moduleSetUpFailed = True + self._createClassOrModuleLevelException(result, e, 'setUpModule', currentModule) - if isinstance(result, _DebugResult): - raise - result._moduleSetUpFailed = True - self._createClassOrModuleLevelException(result, e, - 'setUpModule', - currentModule) + if result._moduleSetUpFailed: + try: + case.doModuleCleanups() + except Exception as e: + self._createClassOrModuleLevelException(result, e, + 'setUpModule', + currentModule) finally: _call_if_exists(result, '_restoreStdout') @@ -251,30 +259,33 @@ def _handleModuleTearDown(self, result): except KeyError: return - tearDownModule = getattr(module, 'tearDownModule', None) - if tearDownModule is not None: - _call_if_exists(result, '_setupStdout') + _call_if_exists(result, '_setupStdout') + try: + tearDownModule = getattr(module, 'tearDownModule', None) + if tearDownModule is not None: + try: + tearDownModule() + except Exception as e: + if isinstance(result, _DebugResult): + raise + self._createClassOrModuleLevelException(result, e, + 'tearDownModule', + previousModule) try: - tearDownModule() + case.doModuleCleanups() except Exception as e: if isinstance(result, _DebugResult): raise self._createClassOrModuleLevelException(result, e, 'tearDownModule', previousModule) - finally: - _call_if_exists(result, '_restoreStdout') - try: - case.doModuleCleanups() - except Exception as e: - self._createClassOrModuleLevelException(result, e, - 'tearDownModule', - previousModule) + finally: + _call_if_exists(result, '_restoreStdout') def _tearDownPreviousClass(self, test, result): previousClass = getattr(result, '_previousTestClass', None) currentClass = test.__class__ - if currentClass == previousClass: + if currentClass == previousClass or previousClass is None: return if getattr(previousClass, '_classSetupFailed', False): return @@ -284,27 +295,34 @@ def _tearDownPreviousClass(self, test, result): return tearDownClass = getattr(previousClass, 'tearDownClass', None) - if tearDownClass is not None: - _call_if_exists(result, '_setupStdout') - try: - tearDownClass() - except Exception as e: - if isinstance(result, _DebugResult): - raise - className = util.strclass(previousClass) - self._createClassOrModuleLevelException(result, e, - 'tearDownClass', - className) - finally: - _call_if_exists(result, '_restoreStdout') - previousClass.doClassCleanups() - if len(previousClass.tearDown_exceptions) > 0: - for exc in previousClass.tearDown_exceptions: - className = util.strclass(previousClass) - self._createClassOrModuleLevelException(result, exc[1], - 'tearDownClass', - className, - info=exc) + doClassCleanups = getattr(previousClass, 'doClassCleanups', None) + if tearDownClass is None and doClassCleanups is None: + return + + _call_if_exists(result, '_setupStdout') + try: + if tearDownClass is not None: + try: + tearDownClass() + except Exception as e: + if isinstance(result, _DebugResult): + raise + className = util.strclass(previousClass) + self._createClassOrModuleLevelException(result, e, + 'tearDownClass', + className) + if doClassCleanups is not None: + doClassCleanups() + for exc_info in previousClass.tearDown_exceptions: + if isinstance(result, _DebugResult): + raise exc_info[1] + className = util.strclass(previousClass) + self._createClassOrModuleLevelException(result, exc_info[1], + 'tearDownClass', + className, + info=exc_info) + finally: + _call_if_exists(result, '_restoreStdout') class _ErrorHolder(object): diff --git a/Lib/unittest/test/test_assertions.py b/Lib/unittest/test/test_assertions.py index f5e64d68e7b101..a0db3423b868aa 100644 --- a/Lib/unittest/test/test_assertions.py +++ b/Lib/unittest/test/test_assertions.py @@ -2,6 +2,7 @@ import warnings import weakref import unittest +from test.support import gc_collect from itertools import product @@ -124,8 +125,10 @@ def test_with(self): self.foo() Foo("test_functional").run() + gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) Foo("test_with").run() + gc_collect() # For PyPy or other GCs. self.assertIsNone(wr()) def testAssertNotRegex(self): diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py index d01864b6936ca8..e46b99fd002648 100644 --- a/Lib/unittest/test/test_async_case.py +++ b/Lib/unittest/test/test_async_case.py @@ -1,5 +1,10 @@ import asyncio import unittest +from test import support + + +class MyException(Exception): + pass def tearDownModule(): @@ -7,9 +12,14 @@ def tearDownModule(): class TestAsyncCase(unittest.TestCase): - def test_full_cycle(self): - events = [] + maxDiff = None + + def tearDown(self): + # Ensure that IsolatedAsyncioTestCase instances are destroyed before + # starting a new event loop + support.gc_collect() + def test_full_cycle(self): class Test(unittest.IsolatedAsyncioTestCase): def setUp(self): self.assertEqual(events, []) @@ -18,12 +28,13 @@ def setUp(self): async def asyncSetUp(self): self.assertEqual(events, ['setUp']) events.append('asyncSetUp') + self.addAsyncCleanup(self.on_cleanup1) async def test_func(self): self.assertEqual(events, ['setUp', 'asyncSetUp']) events.append('test') - self.addAsyncCleanup(self.on_cleanup) + self.addAsyncCleanup(self.on_cleanup2) async def asyncTearDown(self): self.assertEqual(events, ['setUp', @@ -38,34 +49,48 @@ def tearDown(self): 'asyncTearDown']) events.append('tearDown') - async def on_cleanup(self): + async def on_cleanup1(self): + self.assertEqual(events, ['setUp', + 'asyncSetUp', + 'test', + 'asyncTearDown', + 'tearDown', + 'cleanup2']) + events.append('cleanup1') + + async def on_cleanup2(self): self.assertEqual(events, ['setUp', 'asyncSetUp', 'test', 'asyncTearDown', 'tearDown']) - events.append('cleanup') + events.append('cleanup2') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['setUp', - 'asyncSetUp', - 'test', - 'asyncTearDown', - 'tearDown', - 'cleanup']) + result = test.run() + self.assertEqual(result.errors, []) + self.assertEqual(result.failures, []) + expected = ['setUp', 'asyncSetUp', 'test', + 'asyncTearDown', 'tearDown', 'cleanup2', 'cleanup1'] + self.assertEqual(events, expected) - def test_exception_in_setup(self): events = [] + test = Test("test_func") + test.debug() + self.assertEqual(events, expected) + test.doCleanups() + self.assertEqual(events, expected) + def test_exception_in_setup(self): class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') - raise Exception() + self.addAsyncCleanup(self.on_cleanup) + raise MyException() async def test_func(self): events.append('test') - self.addAsyncCleanup(self.on_cleanup) async def asyncTearDown(self): events.append('asyncTearDown') @@ -74,21 +99,34 @@ async def on_cleanup(self): events.append('cleanup') + events = [] + test = Test("test_func") + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) + + events = [] test = Test("test_func") - test.run() + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') self.assertEqual(events, ['asyncSetUp']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'cleanup']) def test_exception_in_test(self): - events = [] - class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') async def test_func(self): events.append('test') - raise Exception() self.addAsyncCleanup(self.on_cleanup) + raise MyException() async def asyncTearDown(self): events.append('asyncTearDown') @@ -96,13 +134,26 @@ async def asyncTearDown(self): async def on_cleanup(self): events.append('cleanup') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown']) + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) - def test_exception_in_test_after_adding_cleanup(self): events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup']) + def test_exception_in_tear_down(self): class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') @@ -110,62 +161,73 @@ async def asyncSetUp(self): async def test_func(self): events.append('test') self.addAsyncCleanup(self.on_cleanup) - raise Exception() async def asyncTearDown(self): events.append('asyncTearDown') + raise MyException() async def on_cleanup(self): events.append('cleanup') + events = [] test = Test("test_func") - test.run() + result = test.run() self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException', result.errors[0][1]) - def test_exception_in_tear_down(self): events = [] - - class Test(unittest.IsolatedAsyncioTestCase): - async def asyncSetUp(self): - events.append('asyncSetUp') - - async def test_func(self): - events.append('test') - self.addAsyncCleanup(self.on_cleanup) - - async def asyncTearDown(self): - events.append('asyncTearDown') - raise Exception() - - async def on_cleanup(self): - events.append('cleanup') - test = Test("test_func") - test.run() + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown']) + test.doCleanups() self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) - def test_exception_in_tear_clean_up(self): - events = [] - class Test(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): events.append('asyncSetUp') async def test_func(self): events.append('test') - self.addAsyncCleanup(self.on_cleanup) + self.addAsyncCleanup(self.on_cleanup1) + self.addAsyncCleanup(self.on_cleanup2) async def asyncTearDown(self): events.append('asyncTearDown') - async def on_cleanup(self): - events.append('cleanup') - raise Exception() + async def on_cleanup1(self): + events.append('cleanup1') + raise MyException('some error') + + async def on_cleanup2(self): + events.append('cleanup2') + raise MyException('other error') + events = [] test = Test("test_func") - test.run() - self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1']) + self.assertIs(result.errors[0][0], test) + self.assertIn('MyException: other error', result.errors[0][1]) + self.assertIn('MyException: some error', result.errors[1][1]) + + events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup2', 'cleanup1']) def test_cleanups_interleave_order(self): events = [] @@ -216,6 +278,68 @@ async def test_cancel(self): output = test.run() self.assertFalse(output.wasSuccessful()) + def test_cancellation_hanging_tasks(self): + cancelled = False + class Test(unittest.IsolatedAsyncioTestCase): + async def test_leaking_task(self): + async def coro(): + nonlocal cancelled + try: + await asyncio.sleep(1) + except asyncio.CancelledError: + cancelled = True + raise + + # Leave this running in the background + asyncio.create_task(coro()) + + test = Test("test_leaking_task") + output = test.run() + self.assertTrue(cancelled) + + def test_debug_cleanup_same_loop(self): + class Test(unittest.IsolatedAsyncioTestCase): + async def asyncSetUp(self): + async def coro(): + await asyncio.sleep(0) + fut = asyncio.ensure_future(coro()) + self.addAsyncCleanup(self.cleanup, fut) + events.append('asyncSetUp') + + async def test_func(self): + events.append('test') + raise MyException() + + async def asyncTearDown(self): + events.append('asyncTearDown') + + async def cleanup(self, fut): + try: + # Raises an exception if in different loop + await asyncio.wait([fut]) + events.append('cleanup') + except: + import traceback + traceback.print_exc() + raise + + events = [] + test = Test("test_func") + result = test.run() + self.assertEqual(events, ['asyncSetUp', 'test', 'asyncTearDown', 'cleanup']) + self.assertIn('MyException', result.errors[0][1]) + + events = [] + test = Test("test_func") + try: + test.debug() + except MyException: + pass + else: + self.fail('Expected a MyException exception') + self.assertEqual(events, ['asyncSetUp', 'test']) + test.doCleanups() + self.assertEqual(events, ['asyncSetUp', 'test', 'cleanup']) if __name__ == "__main__": diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py index b8aca92a8ebe9f..9b3a598ba6c857 100644 --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -19,7 +19,7 @@ TestEquality, TestHashing, LoggingResult, LegacyLoggingResult, ResultWithNoStartTestRunStopTestRun ) -from test.support import captured_stderr +from test.support import captured_stderr, gc_collect log_foo = logging.getLogger('foo') @@ -611,6 +611,8 @@ def testShortDescriptionWithMultiLineDocstring(self): 'Tests shortDescription() for a method with a longer ' 'docstring.') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def testShortDescriptionWhitespaceTrimming(self): """ Tests shortDescription() whitespace is trimmed, so that the first @@ -706,6 +708,10 @@ def testAssertDictContainsSubset(self): with self.assertRaises(self.failureException): self.assertDictContainsSubset({'foo': one}, {'foo': '\uFFFD'}) + with self.assertWarns(DeprecationWarning) as warninfo: + self.assertDictContainsSubset({}, {}) + self.assertEqual(warninfo.warnings[0].filename, __file__) + def testAssertEqual(self): equal_pairs = [ ((), ()), @@ -1947,6 +1953,7 @@ def test2(self): for method_name in ('test1', 'test2'): testcase = TestCase(method_name) testcase.run() + gc_collect() # For PyPy or other GCs. self.assertEqual(MyException.ninstance, 0) diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py index eef82ff937ab7c..4746d71e0b6039 100644 --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -6,6 +6,7 @@ from test import support import unittest import unittest.test +from .test_result import BufferedWriter class Test_TestProgram(unittest.TestCase): @@ -57,9 +58,9 @@ def removeTest(): class FooBar(unittest.TestCase): def testPass(self): - assert True + pass def testFail(self): - assert False + raise AssertionError class FooBarLoader(unittest.TestLoader): """Test loader that returns a suite containing FooBar.""" @@ -104,30 +105,39 @@ def run(self, test): program.testNames) def test_NonExit(self): + stream = BufferedWriter() program = unittest.main(exit=False, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) self.assertTrue(hasattr(program, 'result')) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_Exit(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), exit=True, testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) def test_ExitAsDefault(self): + stream = BufferedWriter() self.assertRaises( SystemExit, unittest.main, argv=["foobar"], - testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testRunner=unittest.TextTestRunner(stream=stream), testLoader=self.FooBarLoader()) + self.assertIn('\nFAIL: testFail ', stream.getvalue()) + self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n')) class InitialisableProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index a4af67bd8d56de..5416735f2923c2 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -2,10 +2,11 @@ import sys import textwrap -from test.support import warnings_helper +from test.support import warnings_helper, captured_stdout, captured_stderr import traceback import unittest +from unittest.util import strclass class MockTraceback(object): @@ -22,6 +23,32 @@ def restore_traceback(): unittest.result.traceback = traceback +def bad_cleanup1(): + print('do cleanup1') + raise TypeError('bad cleanup1') + + +def bad_cleanup2(): + print('do cleanup2') + raise ValueError('bad cleanup2') + + +class BufferedWriter: + def __init__(self): + self.result = '' + self.buffer = '' + + def write(self, arg): + self.buffer += arg + + def flush(self): + self.result += self.buffer + self.buffer = '' + + def getvalue(self): + return self.result + + class Test_TestResult(unittest.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -433,10 +460,13 @@ def testFailFast(self): self.assertTrue(result.shouldStop) def testFailFastSetByRunner(self): - runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True) + stream = BufferedWriter() + runner = unittest.TextTestRunner(stream=stream, failfast=True) def test(result): self.assertTrue(result.failfast) result = runner.run(test) + stream.flush() + self.assertTrue(stream.getvalue().endswith('\n\nOK\n')) classDict = dict(unittest.TestResult.__dict__) @@ -633,36 +663,320 @@ def testBufferOutputAddErrorOrFailure(self): self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage) self.assertMultiLineEqual(message, expectedFullMessage) + def testBufferSetUp(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def setUp(self): + print('set up') + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 1) + description = f'test_foo ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(str(test_case), description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferTearDown(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def tearDown(self): + print('tear down') + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\ntear down\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 1) + description = f'test_foo ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(str(test_case), description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferDoCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def setUp(self): + print('set up') + self.addCleanup(bad_cleanup1) + self.addCleanup(bad_cleanup2) + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 2) + description = f'test_foo ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(str(test_case), description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(str(test_case), description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferSetUp_DoCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def setUp(self): + print('set up') + self.addCleanup(bad_cleanup1) + self.addCleanup(bad_cleanup2) + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 3) + description = f'test_foo ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(str(test_case), description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(str(test_case), description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[2] + self.assertEqual(str(test_case), description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferTearDown_DoCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def setUp(self): + print('set up') + self.addCleanup(bad_cleanup1) + self.addCleanup(bad_cleanup2) + def tearDown(self): + print('tear down') + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up\ntear down\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 3) + description = f'test_foo ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(str(test_case), description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(str(test_case), description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[2] + self.assertEqual(str(test_case), description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + def testBufferSetupClass(self): - result = unittest.TestResult() + with captured_stdout() as stdout: + result = unittest.TestResult() result.buffer = True class Foo(unittest.TestCase): @classmethod def setUpClass(cls): + print('set up class') 1/0 def test_foo(self): pass suite = unittest.TestSuite([Foo('test_foo')]) suite(result) + expected_out = '\nStdout:\nset up class\n' + self.assertEqual(stdout.getvalue(), expected_out) self.assertEqual(len(result.errors), 1) + description = f'setUpClass ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) def testBufferTearDownClass(self): - result = unittest.TestResult() + with captured_stdout() as stdout: + result = unittest.TestResult() result.buffer = True class Foo(unittest.TestCase): @classmethod def tearDownClass(cls): + print('tear down class') 1/0 def test_foo(self): pass suite = unittest.TestSuite([Foo('test_foo')]) suite(result) + expected_out = '\nStdout:\ntear down class\n' + self.assertEqual(stdout.getvalue(), expected_out) self.assertEqual(len(result.errors), 1) + description = f'tearDownClass ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferDoClassCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + @classmethod + def setUpClass(cls): + print('set up class') + cls.addClassCleanup(bad_cleanup1) + cls.addClassCleanup(bad_cleanup2) + @classmethod + def tearDownClass(cls): + print('tear down class') + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 2) + description = f'tearDownClass ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(test_case.description, description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferSetupClass_DoClassCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + @classmethod + def setUpClass(cls): + print('set up class') + cls.addClassCleanup(bad_cleanup1) + cls.addClassCleanup(bad_cleanup2) + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up class\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 3) + description = f'setUpClass ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn('\nStdout:\nset up class\n', formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[2] + self.assertEqual(test_case.description, description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferTearDownClass_DoClassCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + @classmethod + def setUpClass(cls): + print('set up class') + cls.addClassCleanup(bad_cleanup1) + cls.addClassCleanup(bad_cleanup2) + @classmethod + def tearDownClass(cls): + print('tear down class') + 1/0 + def test_foo(self): + pass + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 3) + description = f'tearDownClass ({strclass(Foo)})' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn('\nStdout:\ntear down class\n', formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + test_case, formatted_exc = result.errors[2] + self.assertEqual(test_case.description, description) + self.assertIn('TypeError: bad cleanup1', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertIn(expected_out, formatted_exc) def testBufferSetUpModule(self): - result = unittest.TestResult() + with captured_stdout() as stdout: + result = unittest.TestResult() result.buffer = True class Foo(unittest.TestCase): @@ -671,6 +985,7 @@ def test_foo(self): class Module(object): @staticmethod def setUpModule(): + print('set up module') 1/0 Foo.__module__ = 'Module' @@ -678,10 +993,18 @@ def setUpModule(): self.addCleanup(sys.modules.pop, 'Module') suite = unittest.TestSuite([Foo('test_foo')]) suite(result) + expected_out = '\nStdout:\nset up module\n' + self.assertEqual(stdout.getvalue(), expected_out) self.assertEqual(len(result.errors), 1) + description = 'setUpModule (Module)' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) def testBufferTearDownModule(self): - result = unittest.TestResult() + with captured_stdout() as stdout: + result = unittest.TestResult() result.buffer = True class Foo(unittest.TestCase): @@ -690,6 +1013,7 @@ def test_foo(self): class Module(object): @staticmethod def tearDownModule(): + print('tear down module') 1/0 Foo.__module__ = 'Module' @@ -697,7 +1021,124 @@ def tearDownModule(): self.addCleanup(sys.modules.pop, 'Module') suite = unittest.TestSuite([Foo('test_foo')]) suite(result) + expected_out = '\nStdout:\ntear down module\n' + self.assertEqual(stdout.getvalue(), expected_out) self.assertEqual(len(result.errors), 1) + description = 'tearDownModule (Module)' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferDoModuleCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def test_foo(self): + pass + class Module(object): + @staticmethod + def setUpModule(): + print('set up module') + unittest.addModuleCleanup(bad_cleanup1) + unittest.addModuleCleanup(bad_cleanup2) + + Foo.__module__ = 'Module' + sys.modules['Module'] = Module + self.addCleanup(sys.modules.pop, 'Module') + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 1) + description = 'tearDownModule (Module)' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferSetUpModule_DoModuleCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def test_foo(self): + pass + class Module(object): + @staticmethod + def setUpModule(): + print('set up module') + unittest.addModuleCleanup(bad_cleanup1) + unittest.addModuleCleanup(bad_cleanup2) + 1/0 + + Foo.__module__ = 'Module' + sys.modules['Module'] = Module + self.addCleanup(sys.modules.pop, 'Module') + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\nset up module\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 2) + description = 'setUpModule (Module)' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn('\nStdout:\nset up module\n', formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertIn(expected_out, formatted_exc) + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) + + def testBufferTearDownModule_DoModuleCleanups(self): + with captured_stdout() as stdout: + result = unittest.TestResult() + result.buffer = True + + class Foo(unittest.TestCase): + def test_foo(self): + pass + class Module(object): + @staticmethod + def setUpModule(): + print('set up module') + unittest.addModuleCleanup(bad_cleanup1) + unittest.addModuleCleanup(bad_cleanup2) + @staticmethod + def tearDownModule(): + print('tear down module') + 1/0 + + Foo.__module__ = 'Module' + sys.modules['Module'] = Module + self.addCleanup(sys.modules.pop, 'Module') + suite = unittest.TestSuite([Foo('test_foo')]) + suite(result) + expected_out = '\nStdout:\ntear down module\ndo cleanup2\ndo cleanup1\n' + self.assertEqual(stdout.getvalue(), expected_out) + self.assertEqual(len(result.errors), 2) + description = 'tearDownModule (Module)' + test_case, formatted_exc = result.errors[0] + self.assertEqual(test_case.description, description) + self.assertIn('ZeroDivisionError: division by zero', formatted_exc) + self.assertNotIn('ValueError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn('\nStdout:\ntear down module\n', formatted_exc) + test_case, formatted_exc = result.errors[1] + self.assertEqual(test_case.description, description) + self.assertIn('ValueError: bad cleanup2', formatted_exc) + self.assertNotIn('ZeroDivisionError', formatted_exc) + self.assertNotIn('TypeError', formatted_exc) + self.assertIn(expected_out, formatted_exc) if __name__ == '__main__': diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py index dd9a1b6d9aeddf..453e6c3d11cfaa 100644 --- a/Lib/unittest/test/test_runner.py +++ b/Lib/unittest/test/test_runner.py @@ -222,14 +222,42 @@ def tearDownClass(cls): self.assertEqual(ordering, ['setUpClass', 'test', 'tearDownClass', 'cleanup_good']) - def test_debug_executes_classCleanUp(self): + def test_run_class_cleanUp_without_tearDownClass(self): ordering = [] + blowUp = True class TestableTest(unittest.TestCase): @classmethod def setUpClass(cls): ordering.append('setUpClass') cls.addClassCleanup(cleanup, ordering) + if blowUp: + raise Exception() + def testNothing(self): + ordering.append('test') + @classmethod + @property + def tearDownClass(cls): + raise AttributeError + + runTests(TestableTest) + self.assertEqual(ordering, ['setUpClass', 'cleanup_good']) + + ordering = [] + blowUp = False + runTests(TestableTest) + self.assertEqual(ordering, + ['setUpClass', 'test', 'cleanup_good']) + + def test_debug_executes_classCleanUp(self): + ordering = [] + blowUp = False + + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + cls.addClassCleanup(cleanup, ordering, blowUp=blowUp) def testNothing(self): ordering.append('test') @classmethod @@ -241,6 +269,48 @@ def tearDownClass(cls): self.assertEqual(ordering, ['setUpClass', 'test', 'tearDownClass', 'cleanup_good']) + ordering = [] + blowUp = True + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'CleanUpExc') + self.assertEqual(ordering, + ['setUpClass', 'test', 'tearDownClass', 'cleanup_exc']) + + def test_debug_executes_classCleanUp_when_teardown_exception(self): + ordering = [] + blowUp = False + + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + cls.addClassCleanup(cleanup, ordering, blowUp=blowUp) + def testNothing(self): + ordering.append('test') + @classmethod + def tearDownClass(cls): + raise Exception('TearDownClassExc') + + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'TearDownClassExc') + self.assertEqual(ordering, ['setUpClass', 'test']) + self.assertTrue(TestableTest._class_cleanups) + TestableTest._class_cleanups.clear() + + ordering = [] + blowUp = True + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'TearDownClassExc') + self.assertEqual(ordering, ['setUpClass', 'test']) + self.assertTrue(TestableTest._class_cleanups) + TestableTest._class_cleanups.clear() + def test_doClassCleanups_with_errors_addClassCleanUp(self): class TestableTest(unittest.TestCase): def testNothing(self): @@ -332,6 +402,7 @@ def tearDownClass(cls): self.assertEqual(ordering, ['setUpClass', 'setUp', 'test', 'tearDownClass', 'cleanup_exc']) + ordering = [] class_blow_up = True method_blow_up = False @@ -355,6 +426,26 @@ def tearDownClass(cls): ['setUpClass', 'setUp', 'tearDownClass', 'cleanup_exc']) + def test_with_errors_in_tearDownClass(self): + ordering = [] + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + cls.addClassCleanup(cleanup, ordering) + def testNothing(self): + ordering.append('test') + @classmethod + def tearDownClass(cls): + ordering.append('tearDownClass') + raise Exception('TearDownExc') + + result = runTests(TestableTest) + self.assertEqual(result.errors[0][1].splitlines()[-1], + 'Exception: TearDownExc') + self.assertEqual(ordering, + ['setUpClass', 'test', 'tearDownClass', 'cleanup_good']) + class TestModuleCleanUp(unittest.TestCase): def test_add_and_do_ModuleCleanup(self): @@ -532,13 +623,69 @@ def tearDownClass(cls): 'tearDownModule2', 'cleanup_good']) self.assertEqual(unittest.case._module_cleanups, []) - def test_debug_module_executes_cleanUp(self): + def test_run_module_cleanUp_without_teardown(self): ordering = [] class Module(object): @staticmethod def setUpModule(): ordering.append('setUpModule') unittest.addModuleCleanup(cleanup, ordering) + + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + def testNothing(self): + ordering.append('test') + @classmethod + def tearDownClass(cls): + ordering.append('tearDownClass') + + TestableTest.__module__ = 'Module' + sys.modules['Module'] = Module + runTests(TestableTest) + self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', + 'tearDownClass', 'cleanup_good']) + self.assertEqual(unittest.case._module_cleanups, []) + + def test_run_module_cleanUp_when_teardown_exception(self): + ordering = [] + class Module(object): + @staticmethod + def setUpModule(): + ordering.append('setUpModule') + unittest.addModuleCleanup(cleanup, ordering) + @staticmethod + def tearDownModule(): + raise Exception('CleanUpExc') + + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + def testNothing(self): + ordering.append('test') + @classmethod + def tearDownClass(cls): + ordering.append('tearDownClass') + + TestableTest.__module__ = 'Module' + sys.modules['Module'] = Module + result = runTests(TestableTest) + self.assertEqual(result.errors[0][1].splitlines()[-1], + 'Exception: CleanUpExc') + self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', + 'tearDownClass', 'cleanup_good']) + self.assertEqual(unittest.case._module_cleanups, []) + + def test_debug_module_executes_cleanUp(self): + ordering = [] + blowUp = False + class Module(object): + @staticmethod + def setUpModule(): + ordering.append('setUpModule') + unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp) @staticmethod def tearDownModule(): ordering.append('tearDownModule') @@ -562,6 +709,60 @@ def tearDownClass(cls): 'tearDownModule', 'cleanup_good']) self.assertEqual(unittest.case._module_cleanups, []) + ordering = [] + blowUp = True + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'CleanUpExc') + self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', + 'tearDownClass', 'tearDownModule', 'cleanup_exc']) + self.assertEqual(unittest.case._module_cleanups, []) + + def test_debug_module_cleanUp_when_teardown_exception(self): + ordering = [] + blowUp = False + class Module(object): + @staticmethod + def setUpModule(): + ordering.append('setUpModule') + unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp) + @staticmethod + def tearDownModule(): + raise Exception('TearDownModuleExc') + + class TestableTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + ordering.append('setUpClass') + def testNothing(self): + ordering.append('test') + @classmethod + def tearDownClass(cls): + ordering.append('tearDownClass') + + TestableTest.__module__ = 'Module' + sys.modules['Module'] = Module + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'TearDownModuleExc') + self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', + 'tearDownClass']) + self.assertTrue(unittest.case._module_cleanups) + unittest.case._module_cleanups.clear() + + ordering = [] + blowUp = True + suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest) + with self.assertRaises(Exception) as cm: + suite.debug() + self.assertEqual(str(cm.exception), 'TearDownModuleExc') + self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test', + 'tearDownClass']) + self.assertTrue(unittest.case._module_cleanups) + unittest.case._module_cleanups.clear() + def test_addClassCleanup_arg_errors(self): cleanups = [] def cleanup(*args, **kwargs): @@ -717,9 +918,9 @@ def tearDownClass(cls): method_blow_up = False result = runTests(TestableTest) self.assertEqual(result.errors[0][1].splitlines()[-1], - 'Exception: CleanUpExc') - self.assertEqual(result.errors[1][1].splitlines()[-1], 'Exception: ModuleExc') + self.assertEqual(result.errors[1][1].splitlines()[-1], + 'Exception: CleanUpExc') self.assertEqual(ordering, ['setUpModule', 'cleanup_exc']) ordering = [] diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py index 1c178a95f750ff..7cb9d33f5e5f38 100644 --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -7,30 +7,50 @@ class Test_TestSkipping(unittest.TestCase): def test_skipping(self): class Foo(unittest.TestCase): + def defaultTestResult(self): + return LoggingResult(events) def test_skip_me(self): self.skipTest("skip") events = [] result = LoggingResult(events) test = Foo("test_skip_me") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) self.assertEqual(result.skipped, [(test, "skip")]) + events = [] + result = test.run() + self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + 'stopTest', 'stopTestRun']) + self.assertEqual(result.skipped, [(test, "skip")]) + self.assertEqual(result.testsRun, 1) + # Try letting setUp skip the test now. class Foo(unittest.TestCase): + def defaultTestResult(self): + return LoggingResult(events) def setUp(self): self.skipTest("testing") def test_nothing(self): pass events = [] result = LoggingResult(events) test = Foo("test_nothing") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(result.testsRun, 1) + events = [] + result = test.run() + self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + 'stopTest', 'stopTestRun']) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(result.testsRun, 1) + def test_skipping_subtests(self): class Foo(unittest.TestCase): + def defaultTestResult(self): + return LoggingResult(events) def test_skip_me(self): with self.subTest(a=1): with self.subTest(b=2): @@ -40,7 +60,7 @@ def test_skip_me(self): events = [] result = LoggingResult(events) test = Foo("test_skip_me") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addSkip', 'addSkip', 'addSkip', 'stopTest']) self.assertEqual(len(result.skipped), 3) @@ -54,11 +74,22 @@ def test_skip_me(self): self.assertIsNot(subtest, test) self.assertEqual(result.skipped[2], (test, "skip 3")) + events = [] + result = test.run() + self.assertEqual(events, + ['startTestRun', 'startTest', 'addSkip', 'addSkip', + 'addSkip', 'stopTest', 'stopTestRun']) + self.assertEqual([msg for subtest, msg in result.skipped], + ['skip 1', 'skip 2', 'skip 3']) + def test_skipping_decorators(self): op_table = ((unittest.skipUnless, False, True), (unittest.skipIf, True, False)) for deco, do_skip, dont_skip in op_table: class Foo(unittest.TestCase): + def defaultTestResult(self): + return LoggingResult(events) + @deco(do_skip, "testing") def test_skip(self): pass @@ -66,10 +97,11 @@ def test_skip(self): pass def test_dont_skip(self): pass test_do_skip = Foo("test_skip") test_dont_skip = Foo("test_dont_skip") + suite = unittest.TestSuite([test_do_skip, test_dont_skip]) events = [] result = LoggingResult(events) - suite.run(result) + self.assertIs(suite.run(result), result) self.assertEqual(len(result.skipped), 1) expected = ['startTest', 'addSkip', 'stopTest', 'startTest', 'addSuccess', 'stopTest'] @@ -78,16 +110,39 @@ def test_dont_skip(self): pass self.assertEqual(result.skipped, [(test_do_skip, "testing")]) self.assertTrue(result.wasSuccessful()) + events = [] + result = test_do_skip.run() + self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + 'stopTest', 'stopTestRun']) + self.assertEqual(result.skipped, [(test_do_skip, "testing")]) + + events = [] + result = test_dont_skip.run() + self.assertEqual(events, ['startTestRun', 'startTest', 'addSuccess', + 'stopTest', 'stopTestRun']) + self.assertEqual(result.skipped, []) + def test_skip_class(self): @unittest.skip("testing") class Foo(unittest.TestCase): + def defaultTestResult(self): + return LoggingResult(events) def test_1(self): record.append(1) + events = [] record = [] - result = unittest.TestResult() + result = LoggingResult(events) test = Foo("test_1") suite = unittest.TestSuite([test]) - suite.run(result) + self.assertIs(suite.run(result), result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "testing")]) + self.assertEqual(record, []) + + events = [] + result = test.run() + self.assertEqual(events, ['startTestRun', 'startTest', 'addSkip', + 'stopTest', 'stopTestRun']) self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) @@ -102,10 +157,62 @@ class Foo(Mixin, unittest.TestCase): result = unittest.TestResult() test = Foo("test_1") suite = unittest.TestSuite([test]) - suite.run(result) + self.assertIs(suite.run(result), result) self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(record, []) + def test_skip_in_setup(self): + class Foo(unittest.TestCase): + def setUp(self): + self.skipTest("skip") + def test_skip_me(self): + self.fail("shouldn't come here") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + self.assertIs(test.run(result), result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + + def test_skip_in_cleanup(self): + class Foo(unittest.TestCase): + def test_skip_me(self): + pass + def tearDown(self): + self.skipTest("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + self.assertIs(test.run(result), result) + self.assertEqual(events, ['startTest', 'addSkip', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + + def test_failure_and_skip_in_cleanup(self): + class Foo(unittest.TestCase): + def test_skip_me(self): + self.fail("fail") + def tearDown(self): + self.skipTest("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + self.assertIs(test.run(result), result) + self.assertEqual(events, ['startTest', 'addSkip', 'addFailure', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + + def test_skipping_and_fail_in_cleanup(self): + class Foo(unittest.TestCase): + def test_skip_me(self): + self.skipTest("skip") + def tearDown(self): + self.fail("fail") + events = [] + result = LoggingResult(events) + test = Foo("test_skip_me") + self.assertIs(test.run(result), result) + self.assertEqual(events, ['startTest', 'addSkip', 'addFailure', 'stopTest']) + self.assertEqual(result.skipped, [(test, "skip")]) + def test_expected_failure(self): class Foo(unittest.TestCase): @unittest.expectedFailure @@ -114,10 +221,12 @@ def test_die(self): events = [] result = LoggingResult(events) test = Foo("test_die") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertFalse(result.failures) self.assertEqual(result.expectedFailures[0][0], test) + self.assertFalse(result.unexpectedSuccesses) self.assertTrue(result.wasSuccessful()) def test_expected_failure_with_wrapped_class(self): @@ -129,10 +238,12 @@ def test_1(self): events = [] result = LoggingResult(events) test = Foo("test_1") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertFalse(result.failures) self.assertEqual(result.expectedFailures[0][0], test) + self.assertFalse(result.unexpectedSuccesses) self.assertTrue(result.wasSuccessful()) def test_expected_failure_with_wrapped_subclass(self): @@ -147,10 +258,12 @@ class Bar(Foo): events = [] result = LoggingResult(events) test = Bar("test_1") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addExpectedFailure', 'stopTest']) + self.assertFalse(result.failures) self.assertEqual(result.expectedFailures[0][0], test) + self.assertFalse(result.unexpectedSuccesses) self.assertTrue(result.wasSuccessful()) def test_expected_failure_subtests(self): @@ -170,12 +283,52 @@ def test_die(self): events = [] result = LoggingResult(events) test = Foo("test_die") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addSubTestSuccess', 'addExpectedFailure', 'stopTest']) + self.assertFalse(result.failures) self.assertEqual(len(result.expectedFailures), 1) self.assertIs(result.expectedFailures[0][0], test) + self.assertFalse(result.unexpectedSuccesses) + self.assertTrue(result.wasSuccessful()) + + def test_expected_failure_and_fail_in_cleanup(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + self.fail("help me!") + def tearDown(self): + self.fail("bad tearDown") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + self.assertIs(test.run(result), result) + self.assertEqual(events, + ['startTest', 'addFailure', 'stopTest']) + self.assertEqual(len(result.failures), 1) + self.assertIn('AssertionError: bad tearDown', result.failures[0][1]) + self.assertFalse(result.expectedFailures) + self.assertFalse(result.unexpectedSuccesses) + self.assertFalse(result.wasSuccessful()) + + def test_expected_failure_and_skip_in_cleanup(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + self.fail("help me!") + def tearDown(self): + self.skipTest("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + self.assertIs(test.run(result), result) + self.assertEqual(events, + ['startTest', 'addSkip', 'stopTest']) + self.assertFalse(result.failures) + self.assertFalse(result.expectedFailures) + self.assertFalse(result.unexpectedSuccesses) + self.assertEqual(result.skipped, [(test, "skip")]) self.assertTrue(result.wasSuccessful()) def test_unexpected_success(self): @@ -186,10 +339,11 @@ def test_die(self): events = [] result = LoggingResult(events) test = Foo("test_die") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addUnexpectedSuccess', 'stopTest']) self.assertFalse(result.failures) + self.assertFalse(result.expectedFailures) self.assertEqual(result.unexpectedSuccesses, [test]) self.assertFalse(result.wasSuccessful()) @@ -208,15 +362,54 @@ def test_die(self): events = [] result = LoggingResult(events) test = Foo("test_die") - test.run(result) + self.assertIs(test.run(result), result) self.assertEqual(events, ['startTest', 'addSubTestSuccess', 'addSubTestSuccess', 'addUnexpectedSuccess', 'stopTest']) self.assertFalse(result.failures) + self.assertFalse(result.expectedFailures) self.assertEqual(result.unexpectedSuccesses, [test]) self.assertFalse(result.wasSuccessful()) + def test_unexpected_success_and_fail_in_cleanup(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + pass + def tearDown(self): + self.fail("bad tearDown") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + self.assertIs(test.run(result), result) + self.assertEqual(events, + ['startTest', 'addFailure', 'stopTest']) + self.assertEqual(len(result.failures), 1) + self.assertIn('AssertionError: bad tearDown', result.failures[0][1]) + self.assertFalse(result.expectedFailures) + self.assertFalse(result.unexpectedSuccesses) + self.assertFalse(result.wasSuccessful()) + + def test_unexpected_success_and_skip_in_cleanup(self): + class Foo(unittest.TestCase): + @unittest.expectedFailure + def test_die(self): + pass + def tearDown(self): + self.skipTest("skip") + events = [] + result = LoggingResult(events) + test = Foo("test_die") + self.assertIs(test.run(result), result) + self.assertEqual(events, + ['startTest', 'addSkip', 'stopTest']) + self.assertFalse(result.failures) + self.assertFalse(result.expectedFailures) + self.assertFalse(result.unexpectedSuccesses) + self.assertEqual(result.skipped, [(test, "skip")]) + self.assertTrue(result.wasSuccessful()) + def test_skip_doesnt_run_setup(self): class Foo(unittest.TestCase): wasSetUp = False @@ -232,7 +425,7 @@ def test_1(self): result = unittest.TestResult() test = Foo("test_1") suite = unittest.TestSuite([test]) - suite.run(result) + self.assertIs(suite.run(result), result) self.assertEqual(result.skipped, [(test, "testing")]) self.assertFalse(Foo.wasSetUp) self.assertFalse(Foo.wasTornDown) @@ -252,7 +445,7 @@ def test_1(self): result = unittest.TestResult() test = Foo("test_1") suite = unittest.TestSuite([test]) - suite.run(result) + self.assertIs(suite.run(result), result) self.assertEqual(result.skipped, [(test, "testing")]) def test_skip_without_reason(self): @@ -264,8 +457,74 @@ def test_1(self): result = unittest.TestResult() test = Foo("test_1") suite = unittest.TestSuite([test]) - suite.run(result) + self.assertIs(suite.run(result), result) self.assertEqual(result.skipped, [(test, "")]) + def test_debug_skipping(self): + class Foo(unittest.TestCase): + def setUp(self): + events.append("setUp") + def tearDown(self): + events.append("tearDown") + def test1(self): + self.skipTest('skipping exception') + events.append("test1") + @unittest.skip("skipping decorator") + def test2(self): + events.append("test2") + + events = [] + test = Foo("test1") + with self.assertRaises(unittest.SkipTest) as cm: + test.debug() + self.assertIn("skipping exception", str(cm.exception)) + self.assertEqual(events, ["setUp"]) + + events = [] + test = Foo("test2") + with self.assertRaises(unittest.SkipTest) as cm: + test.debug() + self.assertIn("skipping decorator", str(cm.exception)) + self.assertEqual(events, []) + + def test_debug_skipping_class(self): + @unittest.skip("testing") + class Foo(unittest.TestCase): + def setUp(self): + events.append("setUp") + def tearDown(self): + events.append("tearDown") + def test(self): + events.append("test") + + events = [] + test = Foo("test") + with self.assertRaises(unittest.SkipTest) as cm: + test.debug() + self.assertIn("testing", str(cm.exception)) + self.assertEqual(events, []) + + def test_debug_skipping_subtests(self): + class Foo(unittest.TestCase): + def setUp(self): + events.append("setUp") + def tearDown(self): + events.append("tearDown") + def test(self): + with self.subTest(a=1): + events.append('subtest') + self.skipTest("skip subtest") + events.append('end subtest') + events.append('end test') + + events = [] + result = LoggingResult(events) + test = Foo("test") + with self.assertRaises(unittest.SkipTest) as cm: + test.debug() + self.assertIn("skip subtest", str(cm.exception)) + self.assertEqual(events, ['setUp', 'subtest']) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/unittest/test/testmock/testpatch.py b/Lib/unittest/test/testmock/testpatch.py index d8c1515f8346c3..233a5afffaed4a 100644 --- a/Lib/unittest/test/testmock/testpatch.py +++ b/Lib/unittest/test/testmock/testpatch.py @@ -1875,9 +1875,10 @@ def foo(x=0): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) + orig_doc = foo.__doc__ with patch.object(foo, '__doc__', "FUN"): self.assertEqual(foo.__doc__, "FUN") - self.assertEqual(foo.__doc__, "TEST") + self.assertEqual(foo.__doc__, orig_doc) with patch.object(foo, '__module__', "testpatch2"): self.assertEqual(foo.__module__, "testpatch2") diff --git a/Lib/unittest/test/testmock/testsealable.py b/Lib/unittest/test/testmock/testsealable.py index 59f52338d411e6..daba2b49b46f63 100644 --- a/Lib/unittest/test/testmock/testsealable.py +++ b/Lib/unittest/test/testmock/testsealable.py @@ -128,7 +128,7 @@ def test_integration_with_spec_att_definition(self): m.attr_sample2 def test_integration_with_spec_method_definition(self): - """You need to defin the methods, even if they are in the spec""" + """You need to define the methods, even if they are in the spec""" m = mock.Mock(SampleObject) m.method_sample1.return_value = 1 @@ -171,6 +171,67 @@ def test_call_chain_is_maintained(self): m.test1().test2.test3().test4() self.assertIn("mock.test1().test2.test3().test4", str(cm.exception)) + def test_seal_with_autospec(self): + # https://bugs.python.org/issue45156 + class Foo: + foo = 0 + def bar1(self): + return 1 + def bar2(self): + return 2 + + class Baz: + baz = 3 + def ban(self): + return 4 + + for spec_set in (True, False): + with self.subTest(spec_set=spec_set): + foo = mock.create_autospec(Foo, spec_set=spec_set) + foo.bar1.return_value = 'a' + foo.Baz.ban.return_value = 'b' + + mock.seal(foo) + + self.assertIsInstance(foo.foo, mock.NonCallableMagicMock) + self.assertIsInstance(foo.bar1, mock.MagicMock) + self.assertIsInstance(foo.bar2, mock.MagicMock) + self.assertIsInstance(foo.Baz, mock.MagicMock) + self.assertIsInstance(foo.Baz.baz, mock.NonCallableMagicMock) + self.assertIsInstance(foo.Baz.ban, mock.MagicMock) + + self.assertEqual(foo.bar1(), 'a') + foo.bar1.return_value = 'new_a' + self.assertEqual(foo.bar1(), 'new_a') + self.assertEqual(foo.Baz.ban(), 'b') + foo.Baz.ban.return_value = 'new_b' + self.assertEqual(foo.Baz.ban(), 'new_b') + + with self.assertRaises(TypeError): + foo.foo() + with self.assertRaises(AttributeError): + foo.bar = 1 + with self.assertRaises(AttributeError): + foo.bar2() + + foo.bar2.return_value = 'bar2' + self.assertEqual(foo.bar2(), 'bar2') + + with self.assertRaises(AttributeError): + foo.missing_attr + with self.assertRaises(AttributeError): + foo.missing_attr = 1 + with self.assertRaises(AttributeError): + foo.missing_method() + with self.assertRaises(TypeError): + foo.Baz.baz() + with self.assertRaises(AttributeError): + foo.Baz.missing_attr + with self.assertRaises(AttributeError): + foo.Baz.missing_attr = 1 + with self.assertRaises(AttributeError): + foo.Baz.missing_method() + if __name__ == "__main__": unittest.main() diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 4249163f0edde7..b35997bc00ce16 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -456,6 +456,11 @@ def urlsplit(url, scheme='', allow_fragments=True): """ url, scheme, _coerce_result = _coerce_args(url, scheme) + + for b in _UNSAFE_URL_BYTES_TO_REMOVE: + url = url.replace(b, "") + scheme = scheme.replace(b, "") + allow_fragments = bool(allow_fragments) key = url, scheme, allow_fragments, type(url), type(scheme) cached = _parse_cache.get(key, None) @@ -472,9 +477,6 @@ def urlsplit(url, scheme='', allow_fragments=True): else: scheme, url = url[:i].lower(), url[i+1:] - for b in _UNSAFE_URL_BYTES_TO_REMOVE: - url = url.replace(b, "") - if url[:2] == '//': netloc, url = _splitnetloc(url, 2) if (('[' in netloc and ']' not in netloc) or diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 8363905f20fa35..eca6cc350161f2 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -64,7 +64,7 @@ # install it urllib.request.install_opener(opener) -f = urllib.request.urlopen('http://www.python.org/') +f = urllib.request.urlopen('https://www.python.org/') """ # XXX issues: diff --git a/Lib/uuid.py b/Lib/uuid.py index 67da88560cfb12..5ae0a3e5fa449d 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -47,7 +47,7 @@ import os import sys -from enum import Enum, _simple_enum +from enum import Enum __author__ = 'Ka-Ping Yee ' @@ -75,8 +75,7 @@ bytes_ = bytes # The built-in bytes type -@_simple_enum(Enum) -class SafeUUID: +class SafeUUID(Enum): safe = 0 unsafe = -1 unknown = None diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 8009deb3ea7003..6f1af294ae63e3 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -142,6 +142,20 @@ def create_if_needed(d): context.bin_name = binname context.env_exe = os.path.join(binpath, exename) create_if_needed(binpath) + # Assign and update the command to use when launching the newly created + # environment, in case it isn't simply the executable script (e.g. bpo-45337) + context.env_exec_cmd = context.env_exe + if sys.platform == 'win32': + # bpo-45337: Fix up env_exec_cmd to account for file system redirections. + # Some redirects only apply to CreateFile and not CreateProcess + real_env_exe = os.path.realpath(context.env_exe) + if os.path.normcase(real_env_exe) != os.path.normcase(context.env_exe): + logger.warning('Actual environment location may have moved due to ' + 'redirects, links or junctions.\n' + ' Requested location: "%s"\n' + ' Actual location: "%s"', + context.env_exe, real_env_exe) + context.env_exec_cmd = real_env_exe return context def create_configuration(self, context): @@ -267,8 +281,9 @@ def setup_python(self, context): os.path.normcase(f).startswith(('python', 'vcruntime')) ] else: - suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', - 'pythonw_d.exe'] + suffixes = {'python.exe', 'python_d.exe', 'pythonw.exe', 'pythonw_d.exe'} + base_exe = os.path.basename(context.env_exe) + suffixes.add(base_exe) for suffix in suffixes: src = os.path.join(dirname, suffix) @@ -293,8 +308,8 @@ def _setup_pip(self, context): # We run ensurepip in isolated mode to avoid side effects from # environment vars, the current directory and anything else # intended for the global Python environment - cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade', - '--default-pip'] + cmd = [context.env_exec_cmd, '-Im', 'ensurepip', '--upgrade', + '--default-pip'] subprocess.check_output(cmd, stderr=subprocess.STDOUT) def setup_scripts(self, context): @@ -394,11 +409,7 @@ def upgrade_dependencies(self, context): logger.debug( f'Upgrading {CORE_VENV_DEPS} packages in {context.bin_path}' ) - if sys.platform == 'win32': - python_exe = os.path.join(context.bin_path, 'python.exe') - else: - python_exe = os.path.join(context.bin_path, 'python') - cmd = [python_exe, '-m', 'pip', 'install', '--upgrade'] + cmd = [context.env_exec_cmd, '-m', 'pip', 'install', '--upgrade'] cmd.extend(CORE_VENV_DEPS) subprocess.check_call(cmd) diff --git a/Lib/venv/scripts/common/Activate.ps1 b/Lib/venv/scripts/common/Activate.ps1 index 51fc55c4ec7cb9..eeea3583fa130d 100644 --- a/Lib/venv/scripts/common/Activate.ps1 +++ b/Lib/venv/scripts/common/Activate.ps1 @@ -202,7 +202,7 @@ else { $Prompt = $pyvenvCfg['prompt']; } else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" $Prompt = Split-Path -Path $venvDir -Leaf } diff --git a/Lib/weakref.py b/Lib/weakref.py index 5fa851dd6d771c..994ea8aa37de58 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -2,7 +2,7 @@ This module is an implementation of PEP 205: -http://www.python.org/dev/peps/pep-0205/ +https://www.python.org/dev/peps/pep-0205/ """ # Naming convention: Variables named "wr" are weak reference objects; @@ -119,14 +119,17 @@ def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref): self.data = {} self.update(other, **kw) - def _commit_removals(self): - l = self._pending_removals + def _commit_removals(self, _atomic_removal=_remove_dead_weakref): + pop = self._pending_removals.pop d = self.data # We shouldn't encounter any KeyError, because this method should # always be called *before* mutating the dict. - while l: - key = l.pop() - _remove_dead_weakref(d, key) + while True: + try: + key = pop() + except IndexError: + return + _atomic_removal(d, key) def __getitem__(self, key): if self._pending_removals: @@ -370,7 +373,10 @@ def remove(k, selfref=ref(self)): if self._iterating: self._pending_removals.append(k) else: - del self.data[k] + try: + del self.data[k] + except KeyError: + pass self._remove = remove # A list of dead weakrefs (keys to be removed) self._pending_removals = [] @@ -384,11 +390,16 @@ def _commit_removals(self): # because a dead weakref never compares equal to a live weakref, # even if they happened to refer to equal objects. # However, it means keys may already have been removed. - l = self._pending_removals + pop = self._pending_removals.pop d = self.data - while l: + while True: + try: + key = pop() + except IndexError: + return + try: - del d[l.pop()] + del d[key] except KeyError: pass diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py index 6023c1e13841d2..ec3cece48c9587 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -1,5 +1,5 @@ #! /usr/bin/env python3 -"""Interfaces for launching and remotely controlling Web browsers.""" +"""Interfaces for launching and remotely controlling web browsers.""" # Maintained by Georg Brandl. import os @@ -532,6 +532,10 @@ def register_standard_browsers(): # OS X can use below Unix support (but we prefer using the OS X # specific stuff) + if sys.platform == "serenityos": + # SerenityOS webbrowser, simply called "Browser". + register("Browser", None, BackgroundBrowser("Browser")) + if sys.platform[:3] == "win": # First try to use the default Windows browser register("windows-default", WindowsDefault) diff --git a/Lib/wsgiref/validate.py b/Lib/wsgiref/validate.py index 48ac0070549b3f..6e16578dbb648f 100644 --- a/Lib/wsgiref/validate.py +++ b/Lib/wsgiref/validate.py @@ -137,7 +137,7 @@ def validator(application): """ When applied between a WSGI server and a WSGI application, this - middleware will check for WSGI compliancy on a number of levels. + middleware will check for WSGI compliance on a number of levels. This middleware does not modify the request or response in any way, but will raise an AssertionError if anything seems off (except for a failure to close the application iterator, which diff --git a/Lib/xml/etree/ElementInclude.py b/Lib/xml/etree/ElementInclude.py index 5303062716c47a..40a9b22292479f 100644 --- a/Lib/xml/etree/ElementInclude.py +++ b/Lib/xml/etree/ElementInclude.py @@ -42,7 +42,7 @@ # -------------------------------------------------------------------- # Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/psf/license for licensing details. +# See https://www.python.org/psf/license for licensing details. ## # Limited XInclude support for the ElementTree package. diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py index 1cbd8399d14c50..a1170b572feea0 100644 --- a/Lib/xml/etree/ElementPath.py +++ b/Lib/xml/etree/ElementPath.py @@ -48,7 +48,7 @@ # -------------------------------------------------------------------- # Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/psf/license for licensing details. +# See https://www.python.org/psf/license for licensing details. ## # Implementation module for XPath support. There's usually no reason diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index 99246800b98663..e9409fd29a1157 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -35,7 +35,7 @@ #--------------------------------------------------------------------- # Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/psf/license for licensing details. +# See https://www.python.org/psf/license for licensing details. # # ElementTree # Copyright (c) 1999-2008 by Fredrik Lundh. All rights reserved. @@ -1283,7 +1283,7 @@ class XMLPullParser: def __init__(self, events=None, *, _parser=None): # The _parser argument is for internal use only and must not be relied # upon in user code. It will be removed in a future release. - # See http://bugs.python.org/issue17741 for more details. + # See https://bugs.python.org/issue17741 for more details. self._events_queue = collections.deque() self._parser = _parser or XMLParser(target=TreeBuilder()) diff --git a/Lib/xml/etree/__init__.py b/Lib/xml/etree/__init__.py index 27fd8f6d4e3602..e2ec53421d3f70 100644 --- a/Lib/xml/etree/__init__.py +++ b/Lib/xml/etree/__init__.py @@ -30,4 +30,4 @@ # -------------------------------------------------------------------- # Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/psf/license for licensing details. +# See https://www.python.org/psf/license for licensing details. diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 9e7449c88dfc0d..a614cef6ab2f1a 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -264,16 +264,22 @@ def __repr__(self): # Issue #13305: different format codes across platforms _day0 = datetime(1, 1, 1) -if _day0.strftime('%Y') == '0001': # Mac OS X +def _try(fmt): + try: + return _day0.strftime(fmt) == '0001' + except ValueError: + return False +if _try('%Y'): # Mac OS X def _iso8601_format(value): return value.strftime("%Y%m%dT%H:%M:%S") -elif _day0.strftime('%4Y') == '0001': # Linux +elif _try('%4Y'): # Linux def _iso8601_format(value): return value.strftime("%4Y%m%dT%H:%M:%S") else: def _iso8601_format(value): return value.strftime("%Y%m%dT%H:%M:%S").zfill(17) del _day0 +del _try def _strftime(value): diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index 287e3243b10cc5..69a260f5b12c07 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -750,7 +750,7 @@ def markup(self, text, escape=None, funcs={}, classes={}, methods={}): url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc) results.append('%s' % (url, escape(all))) elif pep: - url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep) + url = 'https://www.python.org/dev/peps/pep-%04d/' % int(pep) results.append('%s' % (url, escape(all))) elif text[end:end+1] == '(': results.append(self.namelink(name, methods, funcs, classes)) diff --git a/Lib/zipimport.py b/Lib/zipimport.py index c55fec6aa1c47d..25eaee9c0f291b 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -334,7 +334,7 @@ def invalidate_caches(self): _zip_directory_cache[self.archive] = self._files except ZipImportError: _zip_directory_cache.pop(self.archive, None) - self._files = None + self._files = {} def __repr__(self): diff --git a/Lib/zoneinfo/_zoneinfo.py b/Lib/zoneinfo/_zoneinfo.py index 9810637d3ef65e..de68380792f17c 100644 --- a/Lib/zoneinfo/_zoneinfo.py +++ b/Lib/zoneinfo/_zoneinfo.py @@ -338,7 +338,7 @@ def _utcoff_to_dstoff(trans_idx, utcoffsets, isdsts): comp_idx = trans_idx[i + 1] # If the following transition is also DST and we couldn't - # find the DST offset by this point, we're going ot have to + # find the DST offset by this point, we're going to have to # skip it and hope this transition gets assigned later if isdsts[comp_idx]: continue diff --git a/Mac/BuildScript/README.rst b/Mac/BuildScript/README.rst index 94a6bb28cadfa5..4f74e7dc00520a 100644 --- a/Mac/BuildScript/README.rst +++ b/Mac/BuildScript/README.rst @@ -19,33 +19,87 @@ Starting with macOS 10.15 Catalina, Gatekeeper now also requires that installer packages are submitted to and pass Apple's automated notarization service using the altool command. To pass notarization, the binaries included in the package must be built with at least -the macOS 10.9 SDK, mout now be signed with the codesign utility +the macOS 10.9 SDK, must now be signed with the codesign utility, and executables must opt in to the hardened run time option with any necessary entitlements. Details of these processes are available in the on-line Apple Developer Documentation and man pages. -As of 3.8.0 and 3.7.7, PSF practice is to build one installer variants -for each release. Note that as of this writing, no Pythons support -building on a newer version of macOS that will run on older versions +A goal of PSF-provided (python.org) Python binaries for macOS is to +support a wide-range of operating system releases with one set of +binaries. Currently, the oldest release supported by python.org +binaries is macOS 10.9; it is still possible to build Python and +Python installers on older versions of macOS but we not regularly +test on those systems nor provide binaries for them. + +Prior to Python 3.9.1, no Python releases supported building on a +newer version of macOS that will run on older versions by setting MACOSX_DEPLOYMENT_TARGET. This is because the various -Python C modules do not yet support runtime testing of macOS +Python C modules did not yet support runtime testing of macOS feature availability (for example, by using macOS AvailabilityMacros.h -and weak-linking). To build a Python that is to be used on a -range of macOS releases, always build on the oldest release to be -supported; the necessary shared libraries for that release will -normally also be available on later systems, with the occasional -exception such as the removal of 32-bit libraries in macOS 10.15. - -build-installer requires Apple Developer tools, either from the +and weak-linking). To build a Python that is to be used on a +range of macOS releases, it was necessary to always build on the +oldest release to be supported; the necessary shared libraries for +that release will normally also be available on later systems, +with the occasional exception such as the removal of 32-bit +libraries in macOS 10.15. For 3.9.x and recent earlier systems, +PSF practice was to provide a "macOS 64-bit Intel installer" variant +that was built on 10.9 that would run on macOS 10.9 and later. + +Starting with 3.9.1, Python fully supports macOS "weaklinking", +meaning it is now possible to build a Python on a current macOS version +with a deployment target of an earlier macOS system. For 3.9.1 and +later systems, we provide a "macOS 64-bit universal2 installer" +variant, currently build on macOS 11 Big Sur with fat binaries +natively supporting both Apple Silicon (arm64) and Intel-64 +(x86_64) Macs running macOS 10.9 or later. + +The legacy "macOS 64-bit Intel installer" variant is expected to +be retired prior to the end of 3.9.x support. + +build-installer.py requires Apple Developer tools, either from the Command Line Tools package or from a full Xcode installation. You should use the most recent version of either for the operating system version in use. (One notable exception: on macOS 10.6, Snow Leopard, use Xcode 3, not Xcode 4 which was released later -in the 10.6 support cycle.) +in the 10.6 support cycle.) build-installer.py also must be run +with recent versions of Python 3.x or 2.7. On older systems, +due to changes in TLS practices, it may be easier to manually +download and cache third-party source distributions used by +build-installer.py rather than have it attempt to automatically +download them. + +1. universal2, arm64 and x86_64, for OS X 10.9 (and later):: + + /path/to/bootstrap/python3 build-installer.py \ + --universal-archs=universal2 \ + --dep-target=10.9 + + - builds the following third-party libraries + + * OpenSSL 1.1.1 + * Tcl/Tk 8.6 + * NCurses + * SQLite + * XZ + * libffi + + - uses system-supplied versions of third-party libraries + + * readline module links with Apple BSD editline (libedit) + * zlib + * bz2 + + - recommended build environment: + + * Mac OS X 11 or later + * Xcode Command Line Tools 12.5 or later + * current default macOS SDK + * ``MACOSX_DEPLOYMENT_TARGET=10.9`` + * Apple ``clang`` -1. 64-bit, x86_64, for OS X 10.9 (and later):: +2. legacy Intel 64-bit, x86_64, for OS X 10.9 (and later):: - /path/to/bootstrap/python2.7 build-installer.py \ + /path/to/bootstrap/python3 build-installer.py \ --universal-archs=intel-64 \ --dep-target=10.9 diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 60174eb6962bae..1eef40fc940f43 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -2,6 +2,10 @@ """ This script is used to build "official" universal installers on macOS. +NEW for 3.10 and backports: +- support universal2 variant with arm64 and x86_64 archs +- enable clang optimizations when building on 10.15+ + NEW for 3.9.0 and backports: - 2.7 end-of-life issues: - Python 3 installs now update the Current version link @@ -236,17 +240,15 @@ def tweak_tcl_build(basedir, archList): def library_recipes(): result = [] - LT_10_5 = bool(getDeptargetTuple() < (10, 5)) - # Since Apple removed the header files for the deprecated system # OpenSSL as of the Xcode 7 release (for OS X 10.10+), we do not # have much choice but to build our own copy here, too. result.extend([ dict( - name="OpenSSL 1.1.1k", - url="https://www.openssl.org/source/openssl-1.1.1k.tar.gz", - checksum='c4e7d95f782b08116afa27b30393dd27', + name="OpenSSL 1.1.1m", + url="https://www.openssl.org/source/openssl-1.1.1m.tar.gz", + checksum='8ec70f665c145c3103f6e330f538a9db', buildrecipe=build_universal_openssl, configure=None, install=None, @@ -262,10 +264,10 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.11' - tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4' + tcl_tk_ver='8.6.12' + tcl_checksum='87ea890821d2221f2ab5157bc5eb885f' - tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6' + tk_checksum='1d6dcf6120356e3d211e056dff5e462a' tk_patches = [ ] @@ -367,7 +369,7 @@ def library_recipes(): '-DSQLITE_ENABLE_RTREE ' '-DSQLITE_OMIT_AUTOINIT ' '-DSQLITE_TCL=0 ' - '%s' % ('','-DSQLITE_WITHOUT_ZONEMALLOC ')[LT_10_5]), + ), configure_pre=[ '--enable-threadsafe', '--enable-shared=no', @@ -378,47 +380,6 @@ def library_recipes(): ), ]) - if getDeptargetTuple() < (10, 5): - result.extend([ - dict( - name="Bzip2 1.0.6", - url="http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz", - checksum='00b516f4704d4a7cb50a1d97e6e8e15b', - configure=None, - install='make install CC=%s CXX=%s, PREFIX=%s/usr/local/ CFLAGS="-arch %s"'%( - CC, CXX, - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - ), - ), - dict( - name="ZLib 1.2.3", - url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz", - checksum='debc62758716a169df9f62e6ab2bc634', - configure=None, - install='make install CC=%s CXX=%s, prefix=%s/usr/local/ CFLAGS="-arch %s"'%( - CC, CXX, - shellQuote(os.path.join(WORKDIR, 'libraries')), - ' -arch '.join(ARCHLIST), - ), - ), - dict( - # Note that GNU readline is GPL'd software - name="GNU Readline 6.1.2", - url="http://ftp.gnu.org/pub/gnu/readline/readline-6.1.tar.gz" , - checksum='fc2f7e714fe792db1ce6ddc4c9fb4ef3', - patchlevel='0', - patches=[ - # The readline maintainers don't do actual micro releases, but - # just ship a set of patches. - ('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-001', - 'c642f2e84d820884b0bf9fd176bc6c3f'), - ('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002', - '1a76781a1ea734e831588285db7ec9b1'), - ] - ), - ]) - if not PYTHON_3: result.extend([ dict( @@ -492,7 +453,7 @@ def pkg_recipes(): source="/pydocs", readme="""\ This package installs the python documentation at a location - that is useable for pydoc and IDLE. + that is usable for pydoc and IDLE. """, postflight="scripts/postflight.documentation", required=False, @@ -1640,7 +1601,7 @@ def buildDMG(): # instead of 11. We should not run into that situation here.) # Also we should use "macos" instead of "macosx" going forward. # - # To maintain compability for legacy variants, the file name for + # To maintain compatibility for legacy variants, the file name for # builds on macOS 10.15 and earlier remains: # python-3.x.y-macosx10.z.{dmg->pkg} # e.g. python-3.9.4-macosx10.9.{dmg->pkg} diff --git a/Mac/BuildScript/resources/License.rtf b/Mac/BuildScript/resources/License.rtf index 1dfdc1edc17fab..7fe7e66f4c0b69 100644 --- a/Mac/BuildScript/resources/License.rtf +++ b/Mac/BuildScript/resources/License.rtf @@ -16,7 +16,7 @@ Python was created in the early 1990s by Guido van Rossum at Stichting Mathemati \ In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software.\ \ -In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.org). In 2001, the Python Software Foundation (PSF, see http://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF.\ +In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.org). In 2001, the Python Software Foundation (PSF, see https://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF.\ \ All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases.\ \ @@ -106,7 +106,7 @@ BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1\ \f1\b0 \ 1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation.\ \ -2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013".\ +2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the internet using the following URL: http://hdl.handle.net/1895.22/1013".\ \ 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1.\ \ @@ -161,4 +161,4 @@ This installer incorporates portions of the following third-party software:\ \ \ \ -} \ No newline at end of file +} diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index a6bfeb9f164eab..4edfa5f3069f43 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -8,12 +8,6 @@ \f0\fs24 \cf0 This package will install Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\ \ -\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 - -\f1\b \cf0 NOTE: -\f0\b0 This is a beta test preview of Python 3.10.0, the next feature release of Python 3. It is not intended for production use.\ -\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\cf0 \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 \f1\b \cf0 \ul \ulc0 Certificate verification and OpenSSL\ @@ -26,7 +20,7 @@ This package includes its own private copy of OpenSSL 1.1.1. The trust certifi \f0\i0 command line utility are not used as defaults by the Python \f3 ssl \f0 module. A sample command script is included in -\f3 /Applications/Python 3.9 +\f3 /Applications/Python 3.10 \f0 to install a curated bundle of default root certificates from the third-party \f3 certifi \f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). Double-click on diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index c65119b7fa2e2c..57ffdb53d6f248 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -3,7 +3,7 @@ } {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} -\paperw11905\paperh16837\margl1440\margr1440\vieww12200\viewh10880\viewkind0 +\paperw11900\paperh16840\margl1440\margr1440\vieww12200\viewh10880\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 \f0\fs24 \cf0 This package will install @@ -23,8 +23,4 @@ At the end of this install, click on \f2 Install Certificates \f0 to install a set of current SSL root certificates.\ -\ - -\f1\b NOTE: -\f0\b0 This is a beta test preview of Python 3.10.0, the next feature release of Python 3. It is not intended for production use.\ } \ No newline at end of file diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist index f6b5cfe8d5451f..d197c77ed4b1a3 100644 --- a/Mac/IDLE/IDLE.app/Contents/Info.plist +++ b/Mac/IDLE/IDLE.app/Contents/Info.plist @@ -36,7 +36,7 @@ CFBundleExecutable IDLE CFBundleGetInfoString - %version%, © 2001-2021 Python Software Foundation + %version%, © 2001-2022 Python Software Foundation CFBundleIconFile IDLE.icns CFBundleIdentifier diff --git a/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py b/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py index 5994c18ff876b3..ccc18d4aee4386 100644 --- a/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py +++ b/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py @@ -35,7 +35,7 @@ # idlemain.py running under the symlinked python. # This is the magic step. # 4. During interpreter initialization, because PYTHONEXECUTABLE is defined, -# sys.executable may get set to an unuseful value. +# sys.executable may get set to an useless value. # # (Note that the IDLE script and the setting of PYTHONEXECUTABLE is # generated automatically by bundlebuilder in the Python 2.x build. diff --git a/Mac/PythonLauncher/Info.plist.in b/Mac/PythonLauncher/Info.plist.in index 3d8bc3e4154ee2..dec0a2eaf5c569 100644 --- a/Mac/PythonLauncher/Info.plist.in +++ b/Mac/PythonLauncher/Info.plist.in @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - English + en CFBundleDocumentTypes @@ -39,8 +39,10 @@ CFBundleExecutable Python Launcher + NSHumanReadableCopyright + Copyright © 2001-2022 Python Software Foundation CFBundleGetInfoString - %VERSION%, © 2001-2021 Python Software Foundation + %VERSION%, © 2001-2022 Python Software Foundation CFBundleIconFile PythonLauncher.icns CFBundleIdentifier @@ -61,5 +63,7 @@ MainMenu NSPrincipalClass NSApplication + NSAppleEventsUsageDescription + Python Launcher uses Apple events to launch your Python script in a Terminal window. diff --git a/Mac/PythonLauncher/MyAppDelegate.m b/Mac/PythonLauncher/MyAppDelegate.m index 25779a2540a37e..9cc2aa0ad90982 100644 --- a/Mac/PythonLauncher/MyAppDelegate.m +++ b/Mac/PythonLauncher/MyAppDelegate.m @@ -22,7 +22,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { // Test that the file mappings are correct [self testFileTypeBinding]; - // If we were opened because of a file drag or doubleclick + // If we were opened because of a file drag or double-click // we've set initial_action_done in shouldShowUI // Otherwise we open a preferences dialog. if (!initial_action_done) { diff --git a/Mac/PythonLauncher/doscript.m b/Mac/PythonLauncher/doscript.m index cbb783ba3e893d..f07326bce46fb8 100644 --- a/Mac/PythonLauncher/doscript.m +++ b/Mac/PythonLauncher/doscript.m @@ -19,7 +19,7 @@ AEDesc desc; OSStatus err; - [[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Utilities/Terminal.app/"]; + [[NSWorkspace sharedWorkspace] launchApplication:@"Terminal.app"]; // Build event err = AEBuildAppleEvent(kAECoreSuite, kAEDoScript, diff --git a/Mac/README.rst b/Mac/README.rst index 35bbfded7f175f..8f2f153d500194 100644 --- a/Mac/README.rst +++ b/Mac/README.rst @@ -226,7 +226,7 @@ distribution, this is installed by default on macOS 10.4 or later. Be aware, though, that the Cocoa-based AquaTk's supplied starting with macOS 10.6 have proven to be unstable. If possible, you should consider installing a newer version before building on macOS 10.6 or later, such as -the ActiveTcl 8.6. See http://www.python.org/download/mac/tcltk/. If you +the ActiveTcl 8.6. See https://www.python.org/download/mac/tcltk/. If you are building with an SDK, ensure that the newer Tcl and Tk frameworks are seen in the SDK's ``Library/Frameworks`` directory; you may need to manually create symlinks to their installed location, ``/Library/Frameworks``. @@ -293,10 +293,10 @@ GUI programs. As of 3.4.0, the ``pythonwx.x`` aliases are no longer installed. How do I create a binary distribution? ====================================== -Download and unpack the source release from http://www.python.org/download/. +Download and unpack the source release from https://www.python.org/download/. Go to the directory ``Mac/BuildScript``. There you will find a script ``build-installer.py`` that does all the work. This will download and build -a number of 3rd-party libaries, configures and builds a framework Python, +a number of 3rd-party libraries, configures and builds a framework Python, installs it, creates the installer package files and then packs this in a DMG image. The script also builds an HTML copy of the current Python documentation set for this release for inclusion in the framework. The @@ -334,9 +334,9 @@ The configure script sometimes emits warnings like the one below:: configure: WARNING: libintl.h: section "Present But Cannot Be Compiled" configure: WARNING: libintl.h: proceeding with the preprocessor's result configure: WARNING: libintl.h: in the future, the compiler will take precedence - configure: WARNING: ## -------------------------------------- ## - configure: WARNING: ## Report this to http://bugs.python.org/ ## - configure: WARNING: ## -------------------------------------- ## + configure: WARNING: ## --------------------------------------- ## + configure: WARNING: ## Report this to https://bugs.python.org/ ## + configure: WARNING: ## --------------------------------------- ## This almost always means you are trying to build a universal binary for Python and have libraries in ``/usr/local`` that don't contain the required @@ -399,8 +399,8 @@ The basic implementation pattern is: Resources ========= - * http://www.python.org/download/mac/ + * https://www.python.org/downloads/macos/ - * http://www.python.org/community/sigs/current/pythonmac-sig/ + * https://www.python.org/community/sigs/current/pythonmac-sig/ * https://devguide.python.org/ diff --git a/Mac/Resources/app/Info.plist.in b/Mac/Resources/app/Info.plist.in index 2c801332332b30..84843b734e3d62 100644 --- a/Mac/Resources/app/Info.plist.in +++ b/Mac/Resources/app/Info.plist.in @@ -37,7 +37,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - %version%, (c) 2001-2021 Python Software Foundation. + %version%, (c) 2001-2022 Python Software Foundation. CFBundleName Python CFBundlePackageType diff --git a/Mac/Resources/framework/Info.plist.in b/Mac/Resources/framework/Info.plist.in index 0dc2e17156f186..863b45238fe4d5 100644 --- a/Mac/Resources/framework/Info.plist.in +++ b/Mac/Resources/framework/Info.plist.in @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2019 Python Software Foundation. + %VERSION%, (c) 2001-2021 Python Software Foundation. CFBundleSignature ???? CFBundleVersion diff --git a/Makefile.pre.in b/Makefile.pre.in index 92cc48657a2af0..ee85f35b10da41 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -103,7 +103,6 @@ PY_CPPFLAGS= $(BASECPPFLAGS) -I. -I$(srcdir)/Include $(CONFIGURE_CPPFLAGS) $(CPP PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) PY_LDFLAGS_NODIST=$(CONFIGURE_LDFLAGS_NODIST) $(LDFLAGS_NODIST) NO_AS_NEEDED= @NO_AS_NEEDED@ -SGI_ABI= @SGI_ABI@ CCSHARED= @CCSHARED@ # LINKFORSHARED are the flags passed to the $(CC) command that links # the python executable -- this is only needed for a few systems @@ -753,6 +752,13 @@ regen-importlib: Programs/_freeze_importlib $(srcdir)/Python/importlib_zipimport.h.new $(UPDATE_FILE) $(srcdir)/Python/importlib_zipimport.h $(srcdir)/Python/importlib_zipimport.h.new +regen-abidump: all + @$(MKDIR_P) $(srcdir)/Doc/data/ + abidw "libpython$(LDVERSION).so" --no-architecture --out-file $(srcdir)/Doc/data/python$(LDVERSION).abi.new + @$(UPDATE_FILE) $(srcdir)/Doc/data/python$(LDVERSION).abi $(srcdir)/Doc/data/python$(LDVERSION).abi.new + +check-abidump: all + abidiff $(srcdir)/Doc/data/python$(LDVERSION).abi "libpython$(LDVERSION).so" --drop-private-types --no-architecture --no-added-syms regen-limited-abi: all $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/stable_abi.py --generate-all $(srcdir)/Misc/stable_abi.txt @@ -1253,10 +1259,10 @@ quicktest: @DEF_MAKE_RULE@ platform # SSL tests .PHONY: multisslcompile multissltest multisslcompile: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py --steps=modules + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py --steps=modules multissltest: build_all - $(RUNSHARED) ./$(BUILDPYTHON) Tools/ssl/multissltests.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/ssl/multissltests.py install: @FRAMEWORKINSTALLFIRST@ commoninstall bininstall maninstall @FRAMEWORKINSTALLLAST@ if test "x$(ENSUREPIP)" != "xno" ; then \ @@ -1688,7 +1694,7 @@ LIBPL= @LIBPL@ LIBPC= $(LIBDIR)/pkgconfig libainstall: @DEF_MAKE_RULE@ python-config - @for i in $(LIBDIR) $(LIBPL) $(LIBPC); \ + @for i in $(LIBDIR) $(LIBPL) $(LIBPC) $(BINDIR); \ do \ if test ! -d $(DESTDIR)$$i; then \ echo "Creating directory $$i"; \ @@ -1956,7 +1962,7 @@ distclean: clobber # Check that all symbols exported by libpython start with "Py" or "_Py" smelly: @DEF_MAKE_RULE@ - $(RUNSHARED) ./$(BUILDPYTHON) Tools/scripts/smelly.py + $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/smelly.py # Find files with funny names funny: @@ -1996,6 +2002,12 @@ patchcheck: @DEF_MAKE_RULE@ check-limited-abi: all $(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/stable_abi.py --all $(srcdir)/Misc/stable_abi.txt +.PHONY: update-config +update-config: + curl -sL -o config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' + curl -sL -o config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' + chmod +x config.guess config.sub + # Dependencies Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h diff --git a/Misc/ACKS b/Misc/ACKS index fb84c00622c314..94b0ed0b241cd6 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -227,6 +227,7 @@ Tom Bridgman Anthony Briggs Keith Briggs Tobias Brink +Miguel Brito Dillon Brock Richard Brodie Michael Broghton @@ -641,6 +642,7 @@ Andrea Griffini Duncan Grisby Olivier Grisel Fabian Groffen +Linus Groh Eric Groo Daniel Andrade Groppe Dag Gruneau @@ -735,6 +737,7 @@ David Hobley Tim Hochberg Benjamin Hodgson Joerg-Cyril Hoehle +Douwe Hoekstra Gregor Hoffleit Chris Hoffman Tim Hoffmann @@ -778,6 +781,7 @@ Christian Hudon Benoît Hudson Lawrence Hudson Michael Hudson +Roberto Hueso Gomez Jim Hugunin Greg Humphreys Chris Hunt @@ -791,6 +795,7 @@ Fredrik Håård Florian Höch Oleg Höfling Robert Hölzl +Stefan Hölzl Catalin Iacob Mihai Ibanescu Ali Ikinci @@ -967,6 +972,7 @@ Andrew Kuchling Jakub Kuczys Dave Kuhlman Jon Kuhn +Andrei Kulakov Ilya Kulakov Upendra Kumar Toshio Kuratomi @@ -1294,6 +1300,7 @@ Peter Otten Michael Otteneder Richard Oudkerk Russel Owen +Noah Oxer Joonas Paalasmaa Yaroslav Pankovych Martin Packman @@ -1614,6 +1621,7 @@ Yue Shuaijie Jaysinh Shukla Terrel Shumway Eric Siegerman +Reilly Tucker Siemens Paul Sijben SilentGhost Tim Silk @@ -1818,6 +1826,7 @@ Andi Vajda Case Van Horsen John Mark Vandenberg Kyle VanderBeek +Wm. Keith van der Meulen Eric N. Vander Weele Andrew Vant Atul Varma @@ -1871,6 +1880,7 @@ Bob Watson Colin Watson David Watson Aaron Watters +Alex Waygood Henrik Weber Leon Weber Steve Weber diff --git a/Misc/HISTORY b/Misc/HISTORY index 32b2a37866bc51..32d814c31bfd14 100644 --- a/Misc/HISTORY +++ b/Misc/HISTORY @@ -1429,7 +1429,7 @@ Library by Devin Cook. - Lax cookie parsing in http.cookies could be a security issue when combined - with non-standard cookie handling in some Web browsers. Reported by + with non-standard cookie handling in some web browsers. Reported by Sergey Bobrov. - Issue #22384: An exception in Tkinter callback no longer crashes the program @@ -10380,7 +10380,7 @@ Tests - Avoid failing in test_robotparser when mueblesmoraleda.com is flaky and an overzealous DNS service (e.g. OpenDNS) redirects to a placeholder - Web site. + web site. - Avoid failing in test_urllibnet.test_bad_address when some overzealous DNS service (e.g. OpenDNS) resolves a non-existent domain name. The test @@ -11273,7 +11273,7 @@ Library - Issue #10549: Fix pydoc traceback when text-documenting certain classes. -- Issue #2001: New HTML server with enhanced Web page features. Patch by Ron +- Issue #2001: New HTML server with enhanced web page features. Patch by Ron Adam. - Issue #10360: In WeakSet, do not raise TypeErrors when testing for membership @@ -21043,7 +21043,7 @@ IDLE own when any program opens a socket. IDLE does use sockets, talking on the computer's internal loopback interface. This connection is not visible on any external interface and no data is sent to or received - from the Internet. So, if you get such a dialog when opening IDLE, + from the internet. So, if you get such a dialog when opening IDLE, asking whether to let pythonw.exe talk to address 127.0.0.1, say yes, and rest assured no communication external to your machine is taking place. If you don't allow it, IDLE won't be able to start. @@ -32325,7 +32325,7 @@ the Tutorial. of that chapter.) -Changes to the WWW and Internet tools +Changes to the WWW and internet tools ===================================== The "htmllib" module has been rewritten in an incompatible fashion. @@ -32485,7 +32485,7 @@ notice them anyway :-) - The Library Reference has been restructured, and many new and existing modules are now documented, in particular the debugger and -the profiler, as well as the persistency and the WWW/Internet support +the profiler, as well as the persistency and the WWW/internet support modules. - All known bugs have been fixed. For example the pow(2,2,3L) bug on @@ -32720,7 +32720,7 @@ New standard library modules: - types.py defines standard names for built-in types, e.g. StringType - - urlparse.py parses URLs according to the latest Internet draft + - urlparse.py parses URLs according to the latest internet draft - uu.py does uuencode/uudecode (not the fastest in the world, but quicker than installing uuencode on a non-UNIX machine :-) diff --git a/Misc/NEWS.d/3.10.0.rst b/Misc/NEWS.d/3.10.0.rst new file mode 100644 index 00000000000000..9911344030cce7 --- /dev/null +++ b/Misc/NEWS.d/3.10.0.rst @@ -0,0 +1,95 @@ +.. bpo: 45121 +.. date: 2021-09-07-17-10-16 +.. nonce: iG-Hsf +.. release date: 2021-10-04 +.. section: Core and Builtins + +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's +called directly or via ``super()``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 45234 +.. date: 2021-09-17-11-20-55 +.. nonce: qUcTVt +.. section: Library + +Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, +:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a +directory, which should raise :exc:`IsADirectoryError` + +.. + +.. bpo: 45216 +.. date: 2021-09-18-13-45-19 +.. nonce: o56nyt +.. section: Documentation + +Remove extra documentation listing methods in ``difflib``. It was rendering +twice in pydoc and was outdated in some places. + +.. + +.. bpo: 45024 +.. date: 2021-09-08-17-20-19 +.. nonce: dkNPNi +.. section: Documentation + +:mod:`collections.abc` documentation has been expanded to explicitly cover +how instance and subclass checks work, with additional doctest examples and +an exhaustive list of ABCs which test membership purely by presence of the +right :term:`special method`\s. Patch by Raymond Hettinger. + +.. + +.. bpo: 45128 +.. date: 2021-09-16-17-22-35 +.. nonce: Jz6fl2 +.. section: Tests + +Fix ``test_multiprocessing_fork`` failure due to ``test_logging`` and +``sys.modules`` manipulation. + +.. + +.. bpo: 44860 +.. date: 2021-09-08-13-01-37 +.. nonce: qXd0kx +.. section: Tests + +Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: +``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. + +.. + +.. bpo: 45067 +.. date: 2021-09-09-16-45-26 +.. nonce: mFmY92 +.. section: Build + +The ncurses function extended_color_content was introduced in 2017 + +(https://invisible-island.net/ncurses/NEWS.html#index-t20170401). The + +ncurses-devel package in CentOS 7 had a older version ncurses resulted in +compilation error. For compiling ncurses with extended color support, we +verify the version of the ncurses library >= 20170401. + +.. + +.. bpo: 45193 +.. date: 2021-09-15-03-20-06 +.. nonce: G61_GV +.. section: IDLE + +Make completion boxes appear on Ubuntu again. + +.. + +.. bpo: 45307 +.. date: 2021-09-28-12-00-55 +.. nonce: 3ETFfX +.. section: C API + +Restore the private C API function :func:`_PyImport_FindExtensionObject`. It +will be removed in Python 3.11. diff --git a/Misc/NEWS.d/3.10.0a1.rst b/Misc/NEWS.d/3.10.0a1.rst index 044bd20594cc37..1c1c2d54e8c20a 100644 --- a/Misc/NEWS.d/3.10.0a1.rst +++ b/Misc/NEWS.d/3.10.0a1.rst @@ -178,7 +178,7 @@ Convert the :mod:`_sha256` extension module types to heap types. .. section: Core and Builtins Fix a possible stack overflow in the parser when parsing functions and -classes with a huge ammount of arguments. Patch by Pablo Galindo. +classes with a huge amount of arguments. Patch by Pablo Galindo. .. diff --git a/Misc/NEWS.d/3.10.0a2.rst b/Misc/NEWS.d/3.10.0a2.rst index 3cfef17160336b..61a291914f9333 100644 --- a/Misc/NEWS.d/3.10.0a2.rst +++ b/Misc/NEWS.d/3.10.0a2.rst @@ -258,7 +258,7 @@ The :func:`repr` of :mod:`typing` types containing :ref:`Generic Alias Types .. nonce: 6aDbty .. section: Library -``binhex.binhex()`` consisently writes macOS 9 line endings. +``binhex.binhex()`` consistently writes macOS 9 line endings. .. @@ -534,7 +534,7 @@ belong to. Patch by Batuhan Taskaya. .. nonce: LR4fnY .. section: Library -Handle exceptions caused by unparseable date headers when using email +Handle exceptions caused by unparsable date headers when using email "default" policy. Patch by Tim Bell, Georges Toth .. diff --git a/Misc/NEWS.d/3.10.0a3.rst b/Misc/NEWS.d/3.10.0a3.rst index 0b76367f944451..4f182e8e3f1f0c 100644 --- a/Misc/NEWS.d/3.10.0a3.rst +++ b/Misc/NEWS.d/3.10.0a3.rst @@ -949,7 +949,7 @@ branches, are now handled by docsbuild-script. .. nonce: W_updK .. section: Tests -Reenable test_gdb on gdb 9.2 and newer: +Re-enable test_gdb on gdb 9.2 and newer: https://bugzilla.redhat.com/show_bug.cgi?id=1866884 bug is fixed in gdb 10.1. diff --git a/Misc/NEWS.d/3.10.0a4.rst b/Misc/NEWS.d/3.10.0a4.rst index 57da9254587b44..214f9e521a55d0 100644 --- a/Misc/NEWS.d/3.10.0a4.rst +++ b/Misc/NEWS.d/3.10.0a4.rst @@ -767,7 +767,7 @@ results. Patch by Ammar Askar. .. nonce: -7-XGz .. section: Tests -Update test_nntplib to use offical group name of news.aioe.org for testing. +Update test_nntplib to use official group name of news.aioe.org for testing. Patch by Dong-hee Na. .. @@ -863,7 +863,7 @@ and Peixing Xin. Now all platforms use a value for the "EXT_SUFFIX" build variable derived from SOABI (for instance in freeBSD, "EXT_SUFFIX" is now ".cpython-310d.so" -instead of ".so"). Previosuly only Linux, Mac and VxWorks were using a value +instead of ".so"). Previously only Linux, Mac and VxWorks were using a value for "EXT_SUFFIX" that included "SOABI". .. diff --git a/Misc/NEWS.d/3.10.0a5.rst b/Misc/NEWS.d/3.10.0a5.rst index 3362d494602d4e..1c7c7447cae065 100644 --- a/Misc/NEWS.d/3.10.0a5.rst +++ b/Misc/NEWS.d/3.10.0a5.rst @@ -386,7 +386,7 @@ initialization (:pep:`489`). Patch by Erlend E. Aasland. .. section: Library The distutils ``bdist_wininst`` command deprecated in Python 3.8 has been -removed. The distutils ``bidst_wheel`` command is now recommended to +removed. The distutils ``bdist_wheel`` command is now recommended to distribute binary packages on Windows. .. @@ -549,7 +549,7 @@ Pass ``--timeout=$(TESTTIMEOUT)`` option to the default profile task .. section: Build Removed the grep -q and -E flags in the tzpath validation section of the -configure script to better accomodate users of some platforms (specifically +configure script to better accommodate users of some platforms (specifically Solaris 10). .. diff --git a/Misc/NEWS.d/3.10.0a6.rst b/Misc/NEWS.d/3.10.0a6.rst index 46d06add9115f7..a4ee9ae098bd93 100644 --- a/Misc/NEWS.d/3.10.0a6.rst +++ b/Misc/NEWS.d/3.10.0a6.rst @@ -49,7 +49,7 @@ The :data:`types.FunctionType` constructor now inherits the current builtins if the *globals* dictionary has no ``"__builtins__"`` key, rather than using ``{"None": None}`` as builtins: same behavior as :func:`eval` and :func:`exec` functions. Defining a function with ``def function(...): ...`` -in Python is not affected, globals cannot be overriden with this syntax: it +in Python is not affected, globals cannot be overridden with this syntax: it also inherits the current builtins. Patch by Victor Stinner. .. @@ -355,7 +355,7 @@ in 4.0" to "3.12". See :pep:`623` for detail. .. nonce: LfTvL- .. section: Tests -Fix test_importlib to correctly skip Unicode file tests if the fileystem +Fix test_importlib to correctly skip Unicode file tests if the filesystem does not support them. .. diff --git a/Misc/NEWS.d/3.10.0a7.rst b/Misc/NEWS.d/3.10.0a7.rst index a20072b7ae11e0..6c32e60dc8a469 100644 --- a/Misc/NEWS.d/3.10.0a7.rst +++ b/Misc/NEWS.d/3.10.0a7.rst @@ -195,7 +195,7 @@ decoded as Unicode characters outside the [U+0000; U+10ffff] range. .. nonce: lCzIg0 .. section: Core and Builtins -Fix a bug that was causing the parser to crash when emiting syntax errors +Fix a bug that was causing the parser to crash when emitting syntax errors when reading input from stdin. Patch by Pablo Galindo .. diff --git a/Misc/NEWS.d/3.10.0b1.rst b/Misc/NEWS.d/3.10.0b1.rst new file mode 100644 index 00000000000000..ca524fe16b7cf8 --- /dev/null +++ b/Misc/NEWS.d/3.10.0b1.rst @@ -0,0 +1,1807 @@ +.. bpo: 43434 +.. date: 2021-05-02-17-50-23 +.. nonce: cy7xz6 +.. release date: 2021-05-03 +.. section: Security + +Creating :class:`sqlite3.Connection` objects now also produces +``sqlite3.connect`` and ``sqlite3.connect/handle`` :ref:`auditing events +`. Previously these events were only produced by +:func:`sqlite3.connect` calls. Patch by Erlend E. Aasland. + +.. + +.. bpo: 43998 +.. date: 2021-05-01-13-13-40 +.. nonce: xhmWD7 +.. section: Security + +The :mod:`ssl` module sets more secure cipher suites defaults. Ciphers +without forward secrecy and with SHA-1 MAC are disabled by default. Security +level 2 prohibits weak RSA, DH, and ECC keys with less than 112 bits of +security. :class:`~ssl.SSLContext` defaults to minimum protocol version TLS +1.2. Settings are based on Hynek Schlawack's research. + +.. + +.. bpo: 43882 +.. date: 2021-04-25-07-46-37 +.. nonce: Jpwx85 +.. section: Security + +The presence of newline or tab characters in parts of a URL could allow some +forms of attacks. + +Following the controlling specification for URLs defined by WHATWG +:func:`urllib.parse` now removes ASCII newlines and tabs from URLs, +preventing such attacks. + +.. + +.. bpo: 43472 +.. date: 2021-04-21-22-53-31 +.. nonce: gjLBTb +.. section: Security + +Ensures interpreter-level audit hooks receive the +``cpython.PyInterpreterState_New`` event when called through the +``_xxsubinterpreters`` module. + +.. + +.. bpo: 43362 +.. date: 2021-04-18-00-56-44 +.. nonce: __5aiP +.. section: Security + +Fix invalid free in _sha3 module. The issue was introduced in 3.10.0a1. +Python 3.9 and earlier are not affected. + +.. + +.. bpo: 43762 +.. date: 2021-04-07-12-57-41 +.. nonce: 7lMtpT +.. section: Security + +Add audit events for :func:`sqlite3.connect/handle`, +:meth:`sqlite3.Connection.enable_load_extension`, and +:meth:`sqlite3.Connection.load_extension`. Patch by Erlend E. Aasland. + +.. + +.. bpo: 43756 +.. date: 2021-04-06-18-07-48 +.. nonce: DLBNqQ +.. section: Security + +Add new audit event ``glob.glob/2`` to incorporate the new *root_dir* and +*dir_fd* arguments added to :func:`glob.glob` and :func:`glob.iglob`. + +.. + +.. bpo: 36384 +.. date: 2021-03-30-16-29-51 +.. nonce: sCAmLs +.. section: Security + +:mod:`ipaddress` module no longer accepts any leading zeros in IPv4 address +strings. Leading zeros are ambiguous and interpreted as octal notation by +some libraries. For example the legacy function :func:`socket.inet_aton` +treats leading zeros as octal notatation. glibc implementation of modern +:func:`~socket.inet_pton` does not accept any leading zeros. For a while the +:mod:`ipaddress` module used to accept ambiguous leading zeros. + +.. + +.. bpo: 43075 +.. date: 2021-01-31-05-28-14 +.. nonce: DoAXqO +.. section: Security + +Fix Regular Expression Denial of Service (ReDoS) vulnerability in +:class:`urllib.request.AbstractBasicAuthHandler`. The ReDoS-vulnerable +regex has quadratic worst-case complexity and it allows cause a denial of +service when identifying crafted invalid RFCs. This ReDoS issue is on the +client side and needs remote attackers to control the HTTP server. + +.. + +.. bpo: 42800 +.. date: 2021-01-09-17-07-36 +.. nonce: _dtZvW +.. section: Security + +Audit hooks are now fired for frame.f_code, traceback.tb_frame, and +generator code/frame attribute access. + +.. + +.. bpo: 37363 +.. date: 2020-07-04-22-14-46 +.. nonce: NDjHNw +.. section: Security + +Add audit events to the :mod:`http.client` module. + +.. + +.. bpo: 43977 +.. date: 2021-05-02-11-59-00 +.. nonce: R0hSDo +.. section: Core and Builtins + +Prevent classes being both a sequence and a mapping when pattern matching. + +.. + +.. bpo: 43977 +.. date: 2021-04-29-17-40-25 +.. nonce: FrQhge +.. section: Core and Builtins + +Use :c:member:`~PyTypeObject.tp_flags` on the class object to determine if +the subject is a sequence or mapping when pattern matching. Avoids the need +to import :mod:`collections.abc` when pattern matching. + +.. + +.. bpo: 43892 +.. date: 2021-04-29-16-00-28 +.. nonce: WXIehI +.. section: Core and Builtins + +Restore proper validation of complex literal value patterns when parsing +:keyword:`!match` blocks. + +.. + +.. bpo: 43933 +.. date: 2021-04-29-13-49-57 +.. nonce: TueFdQ +.. section: Core and Builtins + +Set frame.f_lineno to the line number of the 'with' kweyword when executing +the call to ``__exit__``. + +.. + +.. bpo: 43933 +.. date: 2021-04-29-13-11-44 +.. nonce: mvoV6O +.. section: Core and Builtins + +If the current position in a frame has no line number then set the f_lineno +attribute to None, instead of -1, to conform to PEP 626. This should not +normally be possible, but might occur in some unusual circumstances. + +.. + +.. bpo: 43963 +.. date: 2021-04-28-01-23-38 +.. nonce: u5Y6bS +.. section: Core and Builtins + +Importing the :mod:`_signal` module in a subinterpreter has no longer side +effects. + +.. + +.. bpo: 42739 +.. date: 2021-04-27-10-59-10 +.. nonce: PrVkKM +.. section: Core and Builtins + +The internal representation of line number tables is changed to not use +sentinels, and an explicit length parameter is added to the out of process +API function ``PyLineTable_InitAddressRange``. This makes the handling of +line number tables more robust in some circumstances. + +.. + +.. bpo: 43908 +.. date: 2021-04-26-21-20-41 +.. nonce: 2L51nO +.. section: Core and Builtins + +Make :mod:`re` types immutable. Patch by Erlend E. Aasland. + +.. + +.. bpo: 43908 +.. date: 2021-04-26-20-59-17 +.. nonce: -COW4- +.. section: Core and Builtins + +Make the :class:`array.array` type immutable. Patch by Erlend E. Aasland. + +.. + +.. bpo: 43901 +.. date: 2021-04-25-22-50-47 +.. nonce: oKjG5E +.. section: Core and Builtins + +Change class and module objects to lazy-create empty annotations dicts on +demand. The annotations dicts are stored in the object's __dict__ for +backwards compatibility. + +.. + +.. bpo: 43892 +.. date: 2021-04-25-08-35-11 +.. nonce: hr5Ke2 +.. section: Core and Builtins + +Match patterns now use new dedicated AST nodes (``MatchValue``, +``MatchSingleton``, ``MatchSequence``, ``MatchStar``, ``MatchMapping``, +``MatchClass``) rather than reusing expression AST nodes. ``MatchAs`` and +``MatchOr`` are now defined as pattern nodes rather than as expression +nodes. Patch by Nick Coghlan. + +.. + +.. bpo: 42725 +.. date: 2021-04-25-05-40-51 +.. nonce: WGloYm +.. section: Core and Builtins + +Usage of ``await``/``yield``/``yield from`` and named expressions within an +annotation is now forbidden when PEP 563 is activated. + +.. + +.. bpo: 43754 +.. date: 2021-04-24-16-40-23 +.. nonce: 9SzHWG +.. section: Core and Builtins + +When performing structural pattern matching (:pep:`634`), captured names are +now left unbound until the *entire* pattern has matched successfully. + +.. + +.. bpo: 42737 +.. date: 2021-04-22-22-48-30 +.. nonce: lsJ7pD +.. section: Core and Builtins + +Annotations for complex targets (everything beside simple names) no longer +cause any runtime effects with ``from __future__ import annotations``. + +.. + +.. bpo: 43914 +.. date: 2021-04-22-19-09-58 +.. nonce: 0Ik1AM +.. section: Core and Builtins + +:exc:`SyntaxError` exceptions raised by the interpreter will highlight the +full error range of the expression that consistutes the syntax error itself, +instead of just where the problem is detected. Patch by Pablo Galindo. + +.. + +.. bpo: 38605 +.. date: 2021-04-20-22-17-47 +.. nonce: 9eeCNZ +.. section: Core and Builtins + +Revert making ``from __future__ import annotations`` the default. This +follows the Steering Council decision to postpone PEP 563 changes to at +least Python 3.11. See the original email for more information regarding the +decision: +https://mail.python.org/archives/list/python-dev@python.org/thread/CLVXXPQ2T2LQ5MP2Y53VVQFCXYWQJHKZ/. +Patch by Pablo Galindo. + +.. + +.. bpo: 43475 +.. date: 2021-04-20-20-10-46 +.. nonce: oV8Mbs +.. section: Core and Builtins + +Hashes of NaN values now depend on object identity. Formerly, they always +hashed to 0 even though NaN values are not equal to one another. Having the +same hash for unequal values caused pile-ups in hash tables. + +.. + +.. bpo: 43859 +.. date: 2021-04-16-01-26-57 +.. nonce: QfqjFL +.. section: Core and Builtins + +Improve the error message for :exc:`IndentationError` exceptions. Patch by +Pablo Galindo + +.. + +.. bpo: 41323 +.. date: 2021-04-15-10-19-59 +.. nonce: nsvpSg +.. section: Core and Builtins + +Constant tuple folding in bytecode optimizer now reuses tuple in constant +table. + +.. + +.. bpo: 43846 +.. date: 2021-04-14-13-53-08 +.. nonce: 2jO97c +.. section: Core and Builtins + +Data stack usage is much reduced for large literal and call expressions. + +.. + +.. bpo: 38530 +.. date: 2021-04-14-03-53-06 +.. nonce: rNI_G1 +.. section: Core and Builtins + +When printing :exc:`NameError` raised by the interpreter, +:c:func:`PyErr_Display` will offer suggestions of similar variable names in +the function that the exception was raised from. Patch by Pablo Galindo + +.. + +.. bpo: 43823 +.. date: 2021-04-13-03-06-09 +.. nonce: xpuHBi +.. section: Core and Builtins + +Improve syntax errors for invalid dictionary literals. Patch by Pablo +Galindo. + +.. + +.. bpo: 43822 +.. date: 2021-04-13-02-32-18 +.. nonce: lej0OO +.. section: Core and Builtins + +Improve syntax errors in the parser for missing commas between expressions. +Patch by Pablo Galindo. + +.. + +.. bpo: 43798 +.. date: 2021-04-10-00-01-43 +.. nonce: p_nJFM +.. section: Core and Builtins + +:class:`ast.alias` nodes now include source location metadata attributes +e.g. lineno, col_offset. + +.. + +.. bpo: 43797 +.. date: 2021-04-09-19-12-48 +.. nonce: HfRqNP +.. section: Core and Builtins + +Improve ``SyntaxError`` error messages for invalid comparisons. Patch by +Pablo Galindo. + +.. + +.. bpo: 43760 +.. date: 2021-04-08-12-20-29 +.. nonce: tBIsD8 +.. section: Core and Builtins + +Move the flag for checking whether tracing is enabled to the C stack, from +the heap. Should speed up dispatch in the interpreter. + +.. + +.. bpo: 43682 +.. date: 2021-04-08-01-06-22 +.. nonce: eUn4p5 +.. section: Core and Builtins + +Static methods (:func:`@staticmethod `) and class methods +(:func:`@classmethod `) now inherit the method attributes +(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``, +``__annotations__``) and have a new ``__wrapped__`` attribute. Patch by +Victor Stinner. + +.. + +.. bpo: 43751 +.. date: 2021-04-07-18-00-05 +.. nonce: 8fHsqQ +.. section: Core and Builtins + +Fixed a bug where ``anext(ait, default)`` would erroneously return None. + +.. + +.. bpo: 42128 +.. date: 2021-04-05-17-38-08 +.. nonce: 1uVeGK +.. section: Core and Builtins + +:data:`~object.__match_args__` is no longer allowed to be a list. + +.. + +.. bpo: 43683 +.. date: 2021-04-01-12-30-30 +.. nonce: AjxOx2 +.. section: Core and Builtins + +Add GEN_START opcode. Marks start of generator, including async, or +coroutine and handles sending values to a newly created generator or +coroutine. + +.. + +.. bpo: 43105 +.. date: 2021-03-31-20-35-11 +.. nonce: PBVmHm +.. section: Core and Builtins + +Importlib now resolves relative paths when creating module spec objects from +file locations. + +.. + +.. bpo: 43682 +.. date: 2021-03-31-16-32-57 +.. nonce: VSF3vg +.. section: Core and Builtins + +Static methods (:func:`@staticmethod `) are now callable as +regular functions. Patch by Victor Stinner. + +.. + +.. bpo: 42609 +.. date: 2020-12-12-14-28-31 +.. nonce: Qcd54b +.. section: Core and Builtins + +Prevented crashes in the AST validator and optimizer when compiling some +absurdly long expressions like ``"+0"*1000000``. :exc:`RecursionError` is +now raised instead. + +.. + +.. bpo: 38530 +.. date: 2019-10-27-20-20-07 +.. nonce: ZyoDNn +.. section: Core and Builtins + +When printing :exc:`AttributeError`, :c:func:`PyErr_Display` will offer +suggestions of similar attribute names in the object that the exception was +raised from. Patch by Pablo Galindo + +.. + +.. bpo: 44015 +.. date: 2021-05-03-03-03-49 +.. nonce: V5936k +.. section: Library + +In @dataclass(), raise a TypeError if KW_ONLY is specified more than once. + +.. + +.. bpo: 25478 +.. date: 2021-05-02-19-17-20 +.. nonce: AwlwdA +.. section: Library + +Added a *total()* method to collections.Counter() to compute the sum of the +counts. + +.. + +.. bpo: 43733 +.. date: 2021-05-01-22-59-20 +.. nonce: gJWwEQ +.. section: Library + +Change :class:`netrc.netrc` to use UTF-8 encoding before using locale +encoding. + +.. + +.. bpo: 43979 +.. date: 2021-05-01-01-36-51 +.. nonce: 43oJ9L +.. section: Library + +Removed an unnecessary list comprehension before looping from +:func:`urllib.parse.parse_qsl`. Patch by Christoph Zwerschke and Dong-hee +Na. + +.. + +.. bpo: 43993 +.. date: 2021-04-30-19-23-45 +.. nonce: T7_yoq +.. section: Library + +Update bundled pip to 21.1.1. + +.. + +.. bpo: 43957 +.. date: 2021-04-27-12-13-51 +.. nonce: 6EaPD- +.. section: Library + +[Enum] Deprecate ``TypeError`` when non-member is used in a containment +check; In 3.12 ``True`` or ``False`` will be returned instead, and +containment will return ``True`` if the value is either a member of that +enum or one of its members' value. + +.. + +.. bpo: 42904 +.. date: 2021-04-26-23-39-47 +.. nonce: ejjsyR +.. section: Library + +For backwards compatibility with previous minor versions of Python, if +:func:`typing.get_type_hints` receives no namespace dictionary arguments, +:func:`typing.get_type_hints` will search through the global then local +namespaces during evaluation of stringized type annotations (string forward +references) inside a class. + +.. + +.. bpo: 43945 +.. date: 2021-04-26-20-52-16 +.. nonce: NgERXO +.. section: Library + +[Enum] Deprecate non-standard mixin format() behavior: in 3.12 the enum +member, not the member's value, will be used for format() calls. + +.. + +.. bpo: 41139 +.. date: 2021-04-26-17-47-48 +.. nonce: ROhn1k +.. section: Library + +Deprecate undocumented ``cgi.log()`` API. + +.. + +.. bpo: 43937 +.. date: 2021-04-25-13-34-13 +.. nonce: isx95l +.. section: Library + +Fixed the :mod:`turtle` module working with non-default root window. + +.. + +.. bpo: 43930 +.. date: 2021-04-24-14-23-07 +.. nonce: R7ah0m +.. section: Library + +Update bundled pip to 21.1 and setuptools to 56.0.0 + +.. + +.. bpo: 43907 +.. date: 2021-04-23-20-57-20 +.. nonce: 3RJEjv +.. section: Library + +Fix a bug in the pure-Python pickle implementation when using protocol 5, +where bytearray instances that occur several time in the pickled object +graph would incorrectly unpickle into repeated copies of the bytearray +object. + +.. + +.. bpo: 43926 +.. date: 2021-04-23-17-48-55 +.. nonce: HMUlGU +.. section: Library + +In ``importlib.metadata``, provide a uniform interface to ``Description``, +allow for any field to be encoded with multiline values, remove continuation +lines from multiline values, and add a ``.json`` property for easy access to +the PEP 566 JSON-compatible form. Sync with ``importlib_metadata 4.0``. + +.. + +.. bpo: 43920 +.. date: 2021-04-23-11-54-38 +.. nonce: cJMQ2D +.. section: Library + +OpenSSL 3.0.0: :meth:`~ssl.SSLContext.load_verify_locations` now returns a +consistent error message when cadata contains no valid certificate. + +.. + +.. bpo: 43607 +.. date: 2021-04-22-22-39-58 +.. nonce: 7IYDkG +.. section: Library + +:mod:`urllib` can now convert Windows paths with ``\\?\`` prefixes into URL +paths. + +.. + +.. bpo: 43817 +.. date: 2021-04-22-04-12-13 +.. nonce: FQ-XlH +.. section: Library + +Add :func:`inspect.get_annotations`, which safely computes the annotations +defined on an object. It works around the quirks of accessing the +annotations from various types of objects, and makes very few assumptions +about the object passed in. :func:`inspect.get_annotations` can also +correctly un-stringize stringized annotations. + +:func:`inspect.signature`, :func:`inspect.from_callable`, and +:func:`inspect.from_function` now call :func:`inspect.get_annotations` to +retrieve annotations. This means :func:`inspect.signature` and +:func:`inspect.from_callable` can now un-stringize stringized annotations, +too. + +.. + +.. bpo: 43284 +.. date: 2021-04-21-14-50-57 +.. nonce: 2QZn2T +.. section: Library + +platform.win32_ver derives the windows version from +sys.getwindowsversion().platform_version which in turn derives the version +from kernel32.dll (which can be of a different version than Windows itself). +Therefore change the platform.win32_ver to determine the version using the +platform module's _syscmd_ver private function to return an accurate +version. + +.. + +.. bpo: 42854 +.. date: 2021-04-19-03-54-29 +.. nonce: Y4M7Tv +.. section: Library + +The :mod:`ssl` module now uses ``SSL_read_ex`` and ``SSL_write_ex`` +internally. The functions support reading and writing of data larger than 2 +GB. Writing zero-length data no longer fails with a protocol violation +error. + +.. + +.. bpo: 42333 +.. date: 2021-04-17-19-31-17 +.. nonce: cgbtZO +.. section: Library + +Port ``_ssl`` extension module to multiphase initialization. + +.. + +.. bpo: 43880 +.. date: 2021-04-17-13-53-33 +.. nonce: -fC2JD +.. section: Library + +:mod:`ssl` now raises DeprecationWarning for OP_NO_SSL/TLS* options, old TLS +versions, old protocols, and other features that have been deprecated since +Python 3.6, 3.7, or OpenSSL 1.1.0. + +.. + +.. bpo: 41559 +.. date: 2021-04-17-10-49-57 +.. nonce: caIwt9 +.. section: Library + +:pep:`612` is now implemented purely in Python; builtin +``types.GenericAlias`` objects no longer include ``typing.ParamSpec`` in +``__parameters__`` (with the exception of ``collections.abc.Callable``\ 's +``GenericAlias``). This means previously invalid uses of ``ParamSpec`` (such +as ``list[P]``) which worked in earlier versions of Python 3.10 alpha, will +now raise ``TypeError`` during substitution. + +.. + +.. bpo: 43867 +.. date: 2021-04-16-16-46-44 +.. nonce: xT9QjF +.. section: Library + +The :mod:`multiprocessing` ``Server`` class now explicitly catches +:exc:`SystemExit` and closes the client connection in this case. It happens +when the ``Server.serve_client()`` method reaches the end of file (EOF). + +.. + +.. bpo: 40443 +.. date: 2021-04-16-02-03-00 +.. nonce: Io6FHL +.. section: Library + +Remove unused imports: pyclbr no longer uses copy, and typing no longer uses +ast. Patch by Victor Stinner. + +.. + +.. bpo: 43820 +.. date: 2021-04-12-18-01-10 +.. nonce: YkqYW4 +.. section: Library + +Remove an unneeded copy of the namespace passed to +dataclasses.make_dataclass(). + +.. + +.. bpo: 43787 +.. date: 2021-04-12-15-15-50 +.. nonce: wCy_Wd +.. section: Library + +Add ``__iter__()`` method to :class:`bz2.BZ2File`, :class:`gzip.GzipFile`, +and :class:`lzma.LZMAFile`. It makes iterating them about 2x faster. Patch +by Inada Naoki. + +.. + +.. bpo: 43680 +.. date: 2021-04-12-11-20-34 +.. nonce: SR0Epv +.. section: Library + +Deprecate io.OpenWrapper and _pyio.OpenWrapper: use io.open and _pyio.open +instead. Until Python 3.9, _pyio.open was not a static method and +builtins.open was set to OpenWrapper to not become a bound method when set +to a class variable. _io.open is a built-in function whereas _pyio.open is a +Python function. In Python 3.10, _pyio.open() is now a static method, and +builtins.open() is now io.open(). + +.. + +.. bpo: 43680 +.. date: 2021-04-12-09-57-37 +.. nonce: o1zEk_ +.. section: Library + +The Python :func:`_pyio.open` function becomes a static method to behave as +:func:`io.open` built-in function: don't become a bound method when stored +as a class variable. It becomes possible since static methods are now +callable in Python 3.10. Moreover, :func:`_pyio.OpenWrapper` becomes a +simple alias to :func:`_pyio.open`. Patch by Victor Stinner. + +.. + +.. bpo: 41515 +.. date: 2021-04-12-06-01-10 +.. nonce: YaVReb +.. section: Library + +Fix :exc:`KeyError` raised in :func:`typing.get_type_hints` due to synthetic +modules that don't appear in ``sys.modules``. + +.. + +.. bpo: 43776 +.. date: 2021-04-12-00-00-00 +.. nonce: p14y7a +.. section: Library + +When :class:`subprocess.Popen` args are provided as a string or as +:class:`pathlib.Path`, the Popen instance repr now shows the right thing. + +.. + +.. bpo: 42248 +.. date: 2021-04-11-21-10-57 +.. nonce: pedB1E +.. section: Library + +[Enum] ensure exceptions raised in ``_missing__`` are released + +.. + +.. bpo: 43744 +.. date: 2021-04-11-20-52-32 +.. nonce: uf0E68 +.. section: Library + +fix issue with enum member name matching the start of a private variable +name + +.. + +.. bpo: 43772 +.. date: 2021-04-10-19-14-49 +.. nonce: Bxq0zQ +.. section: Library + +Fixed the return value of ``TypeVar.__ror__``. Patch by Jelle Zijlstra. + +.. + +.. bpo: 43764 +.. date: 2021-04-10-18-23-09 +.. nonce: Le5KJp +.. section: Library + +Add match_args parameter to @dataclass decorator to allow suppression of +__match_args__ generation. + +.. + +.. bpo: 43799 +.. date: 2021-04-10-11-35-50 +.. nonce: 1iV4pX +.. section: Library + +OpenSSL 3.0.0: define ``OPENSSL_API_COMPAT`` 1.1.1 to suppress deprecation +warnings. Python requires OpenSSL 1.1.1 APIs. + +.. + +.. bpo: 43478 +.. date: 2021-04-10-03-30-36 +.. nonce: iZcBTq +.. section: Library + +Mocks can no longer be used as the specs for other Mocks. As a result, an +already-mocked object cannot have an attribute mocked using +``autospec=True`` or be the subject of a ``create_autospec(...)`` call. This +can uncover bugs in tests since these Mock-derived Mocks will always pass +certain tests (e.g. :func:`isinstance`) and builtin assert functions (e.g. +assert_called_once_with) will unconditionally pass. + +.. + +.. bpo: 43794 +.. date: 2021-04-09-16-14-22 +.. nonce: -1XPDH +.. section: Library + +Add :data:`ssl.OP_IGNORE_UNEXPECTED_EOF` constants (OpenSSL 3.0.0) + +.. + +.. bpo: 43785 +.. date: 2021-04-09-14-51-58 +.. nonce: 1mM5xE +.. section: Library + +Improve ``bz2.BZ2File`` performance by removing the RLock from BZ2File. This +makes BZ2File thread unsafe in the face of multiple simultaneous readers or +writers, just like its equivalent classes in :mod:`gzip` and :mod:`lzma` +have always been. Patch by Inada Naoki. + +.. + +.. bpo: 43789 +.. date: 2021-04-09-14-08-03 +.. nonce: eaHlAm +.. section: Library + +OpenSSL 3.0.0: Don't call the password callback function a second time when +first call has signaled an error condition. + +.. + +.. bpo: 43788 +.. date: 2021-04-09-12-08-01 +.. nonce: YsvInM +.. section: Library + +The header files for :mod:`ssl` error codes are now OpenSSL +version-specific. Exceptions will now show correct reason and library codes. +The ``make_ssl_data.py`` script has been rewritten to use OpenSSL's text +file with error codes. + +.. + +.. bpo: 43766 +.. date: 2021-04-09-00-16-22 +.. nonce: nYNQP0 +.. section: Library + +Implement :pep:`647` in the :mod:`typing` module by adding +:data:`TypeGuard`. + +.. + +.. bpo: 25264 +.. date: 2021-04-08-22-11-27 +.. nonce: b33fa0 +.. section: Library + +:func:`os.path.realpath` now accepts a *strict* keyword-only argument. When +set to ``True``, :exc:`OSError` is raised if a path doesn't exist or a +symlink loop is encountered. + +.. + +.. bpo: 43780 +.. date: 2021-04-08-20-04-46 +.. nonce: hUOgCh +.. section: Library + +In ``importlib.metadata``, incorporate changes from importlib_metadata 3.10: +Add mtime-based caching during distribution discovery. Flagged use of dict +result from ``entry_points()`` as deprecated. + +.. + +.. bpo: 47383 +.. date: 2021-04-08-19-32-26 +.. nonce: YI1hdL +.. section: Library + +The ``P.args`` and ``P.kwargs`` attributes of :class:`typing.ParamSpec` are +now instances of the new classes :class:`typing.ParamSpecArgs` and +:class:`typing.ParamSpecKwargs`, which enables a more useful ``repr()``. +Patch by Jelle Zijlstra. + +.. + +.. bpo: 43731 +.. date: 2021-04-08-15-19-20 +.. nonce: nnVd3h +.. section: Library + +Add an ``encoding`` parameter :func:`logging.fileConfig()`. + +.. + +.. bpo: 43712 +.. date: 2021-04-08-12-25-08 +.. nonce: f8WXCX +.. section: Library + +Add ``encoding`` and ``errors`` parameters to :func:`fileinput.input` and +:class:`fileinput.FileInput`. + +.. + +.. bpo: 38659 +.. date: 2021-04-08-11-47-31 +.. nonce: r_HFnU +.. section: Library + +A ``simple_enum`` decorator is added to the ``enum`` module to convert a +normal class into an Enum. ``test_simple_enum`` added to test simple enums +against a corresponding normal Enum. Standard library modules updated to +use ``simple_enum``. + +.. + +.. bpo: 43764 +.. date: 2021-04-08-09-59-20 +.. nonce: tHjO60 +.. section: Library + +Fix an issue where :data:`~object.__match_args__` generation could fail for +some :mod:`dataclasses`. + +.. + +.. bpo: 43752 +.. date: 2021-04-06-21-18-29 +.. nonce: K7qmAF +.. section: Library + +Fix :mod:`sqlite3` regression for zero-sized blobs with converters, where +``b""`` was returned instead of ``None``. The regression was introduced by +GH-24723. Patch by Erlend E. Aasland. + +.. + +.. bpo: 43655 +.. date: 2021-04-04-20-51-19 +.. nonce: LwGy8R +.. section: Library + +:mod:`tkinter` dialog windows are now recognized as dialogs by window +managers on macOS and X Window. + +.. + +.. bpo: 43723 +.. date: 2021-04-03-18-03-44 +.. nonce: uBhBZS +.. section: Library + +The following ``threading`` methods are now deprecated and should be +replaced: + +- ``currentThread`` => :func:`threading.current_thread` + +- ``activeCount`` => :func:`threading.active_count` + +- ``Condition.notifyAll`` => :meth:`threading.Condition.notify_all` + +- ``Event.isSet`` => :meth:`threading.Event.is_set` + +- ``Thread.setName`` => :attr:`threading.Thread.name` + +- ``thread.getName`` => :attr:`threading.Thread.name` + +- ``Thread.isDaemon`` => :attr:`threading.Thread.daemon` + +- ``Thread.setDaemon`` => :attr:`threading.Thread.daemon` + +Patch by Jelle Zijlstra. + +.. + +.. bpo: 2135 +.. date: 2021-04-03-15-24-59 +.. nonce: xmDAYJ +.. section: Library + +Deprecate find_module() and find_loader() implementations in importlib and +zipimport. + +.. + +.. bpo: 43534 +.. date: 2021-03-18-15-46-08 +.. nonce: vPE9Us +.. section: Library + +:func:`turtle.textinput` and :func:`turtle.numinput` create now a transient +window working on behalf of the canvas window. + +.. + +.. bpo: 43532 +.. date: 2021-03-17-19-06-45 +.. nonce: W2Ntnm +.. section: Library + +Add the ability to specify keyword-only fields to dataclasses. These fields +will become keyword-only arguments to the generated __init__. + +.. + +.. bpo: 43522 +.. date: 2021-03-16-22-37-32 +.. nonce: dhNwOu +.. section: Library + +Fix problem with :attr:`~ssl.SSLContext.hostname_checks_common_name`. +OpenSSL does not copy hostflags from *struct SSL_CTX* to *struct SSL*. + +.. + +.. bpo: 8978 +.. date: 2021-03-13-14-02-07 +.. nonce: CRxG-O +.. section: Library + +Improve error message for :func:`tarfile.open` when :mod:`lzma` / :mod:`bz2` +are unavailable. Patch by Anthony Sottile. + +.. + +.. bpo: 42967 +.. date: 2021-03-11-00-31-41 +.. nonce: 2PeQRw +.. section: Library + +Allow :class:`bytes` ``separator`` argument in ``urllib.parse.parse_qs`` and +``urllib.parse.parse_qsl`` when parsing :class:`str` query strings. +Previously, this raised a ``TypeError``. + +.. + +.. bpo: 43296 +.. date: 2021-03-01-13-01-33 +.. nonce: p_gU6T +.. section: Library + +Improve :mod:`sqlite3` error handling: ``sqlite3_value_blob()`` errors that +set ``SQLITE_NOMEM`` now raise :exc:`MemoryError`. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 43312 +.. date: 2021-02-25-14-43-59 +.. nonce: 6dg9_2 +.. section: Library + +New functions :func:`sysconfig.get_preferred_scheme` and +:func:`sysconfig.get_default_scheme` are added to query a platform for its +preferred "user", "home", and "prefix" (default) scheme names. + +.. + +.. bpo: 43265 +.. date: 2021-02-19-22-24-33 +.. nonce: MyAzCH +.. section: Library + +Improve :meth:`sqlite3.Connection.backup` error handling. The error message +for non-existent target database names is now ``unknown database `` instead of ``SQL logic error``. Patch by Erlend E. Aasland. + +.. + +.. bpo: 41282 +.. date: 2021-02-16-13-18-38 +.. nonce: GK9a0l +.. section: Library + +Install schemes in :mod:`distutils.command.install` are now loaded from +:mod:`sysconfig`. + +.. + +.. bpo: 41282 +.. date: 2021-02-15-12-52-23 +.. nonce: SenEje +.. section: Library + +:mod:`distutils.sysconfig` has been merged to :mod:`sysconfig`. + +.. + +.. bpo: 43176 +.. date: 2021-02-09-07-24-29 +.. nonce: bocNQn +.. section: Library + +Fixed processing of a dataclass that inherits from a frozen dataclass with +no fields. It is now correctly detected as an error. + +.. + +.. bpo: 43080 +.. date: 2021-01-31-00-23-13 +.. nonce: -fDg4Q +.. section: Library + +:mod:`pprint` now has support for :class:`dataclasses.dataclass`. Patch by +Lewis Gaul. + +.. + +.. bpo: 39950 +.. date: 2021-01-22-00-15-37 +.. nonce: NzLVaR +.. section: Library + +Add `pathlib.Path.hardlink_to()` method that supersedes `link_to()`. The new +method has the same argument order as `symlink_to()`. + +.. + +.. bpo: 42904 +.. date: 2021-01-12-23-17-02 +.. nonce: -4qkTD +.. section: Library + +:func:`typing.get_type_hints` now checks the local namespace of a class when +evaluating :pep:`563` annotations inside said class. + +.. + +.. bpo: 42269 +.. date: 2021-01-08-22-32-13 +.. nonce: W5v8z4 +.. section: Library + +Add ``slots`` parameter to ``dataclasses.dataclass`` decorator to +automatically generate ``__slots__`` for class. Patch provided by Yurii +Karabas. + +.. + +.. bpo: 39529 +.. date: 2020-12-06-20-21-16 +.. nonce: 9Zrg43 +.. section: Library + +Deprecated use of :func:`asyncio.get_event_loop` without running event loop. +Emit deprecation warning for :mod:`asyncio` functions which implicitly +create a :class:`~asyncio.Future` or :class:`~asyncio.Task` objects if there +is no running event loop and no explicit *loop* argument is passed: +:func:`~asyncio.ensure_future`, :func:`~asyncio.wrap_future`, +:func:`~asyncio.gather`, :func:`~asyncio.shield`, +:func:`~asyncio.as_completed` and constructors of :class:`~asyncio.Future`, +:class:`~asyncio.Task`, :class:`~asyncio.StreamReader`, +:class:`~asyncio.StreamReaderProtocol`. + +.. + +.. bpo: 18369 +.. date: 2020-11-19-09-52-24 +.. nonce: qzvYH2 +.. section: Library + +Certificate and PrivateKey classes were added to the ssl module. +Certificates and keys can now be loaded from memory buffer, too. + +.. + +.. bpo: 41486 +.. date: 2020-10-16-15-34-30 +.. nonce: Mu9Iit +.. section: Library + +Use a new output buffer management code for :mod:`bz2` / :mod:`lzma` / +:mod:`zlib` modules, and add ``.readall()`` function to +``_compression.DecompressReader`` class. These bring some performance +improvements. Patch by Ma Lin. + +.. + +.. bpo: 31870 +.. date: 2020-09-15-23-44-07 +.. nonce: nVwd38 +.. section: Library + +The :func:`ssl.get_server_certificate` function now has a *timeout* +parameter. + +.. + +.. bpo: 41735 +.. date: 2020-09-07-11-15-15 +.. nonce: NKqGKy +.. section: Library + +Fix thread locks in zlib module may go wrong in rare case. Patch by Ma Lin. + +.. + +.. bpo: 36470 +.. date: 2020-06-13-23-33-32 +.. nonce: oi6Kdb +.. section: Library + +Fix dataclasses with ``InitVar``\s and :func:`~dataclasses.replace()`. Patch +by Claudiu Popa. + +.. + +.. bpo: 40849 +.. date: 2020-06-02-21-32-33 +.. nonce: zpeKx3 +.. section: Library + +Expose X509_V_FLAG_PARTIAL_CHAIN ssl flag + +.. + +.. bpo: 35114 +.. date: 2020-05-17-14-10-24 +.. nonce: uLIHfn +.. section: Library + +:func:`ssl.RAND_status` now returns a boolean value (as documented) instead +of ``1`` or ``0``. + +.. + +.. bpo: 39906 +.. date: 2020-03-30-00-13-27 +.. nonce: eaR3fN +.. section: Library + +:meth:`pathlib.Path.stat` and :meth:`~pathlib.Path.chmod` now accept a +*follow_symlinks* keyword-only argument for consistency with corresponding +functions in the :mod:`os` module. + +.. + +.. bpo: 39899 +.. date: 2020-03-09-20-36-07 +.. nonce: 9adF3E +.. section: Library + +:func:`os.path.expanduser()` now refuses to guess Windows home directories +if the basename of current user's home directory does not match their +username. + +:meth:`pathlib.Path.expanduser()` and :meth:`~pathlib.Path.home()` now +consistently raise :exc:`RuntimeError` exception when a home directory +cannot be resolved. Previously a :exc:`KeyError` exception could be raised +on Windows when the ``"USERNAME"`` environment variable was unset. + +.. + +.. bpo: 36076 +.. date: 2019-10-16-17-21-53 +.. nonce: FGeQQT +.. section: Library + +Added SNI support to :func:`ssl.get_server_certificate`. + +.. + +.. bpo: 38490 +.. date: 2019-10-16-08-08-14 +.. nonce: QbDXEF +.. section: Library + +Covariance, Pearson's correlation, and simple linear regression +functionality was added to statistics module. Patch by Tymoteusz Wołodźko. + +.. + +.. bpo: 33731 +.. date: 2019-08-14-13-19-50 +.. nonce: 9esS0d +.. section: Library + +Provide a locale.localize() function, which converts a normalized number +string into a locale format. + +.. + +.. bpo: 32745 +.. date: 2018-08-09-23-47-10 +.. nonce: iQi9hI +.. section: Library + +Fix a regression in the handling of ctypes' :data:`ctypes.c_wchar_p` type: +embedded null characters would cause a :exc:`ValueError` to be raised. Patch +by Zackery Spytz. + +.. + +.. bpo: 43987 +.. date: 2021-04-30-04-27-02 +.. nonce: 1DftVa +.. section: Documentation + +Add "Annotations Best Practices" document as a new HOWTO. + +.. + +.. bpo: 43977 +.. date: 2021-04-29-15-06-03 +.. nonce: K5aSl1 +.. section: Documentation + +Document the new :const:`Py_TPFLAGS_MAPPING` and +:const:`Py_TPFLAGS_SEQUENCE` type flags. + +.. + +.. bpo: 43959 +.. date: 2021-04-27-22-22-22 +.. nonce: n2261q +.. section: Documentation + +The documentation on the PyContextVar C-API was clarified. + +.. + +.. bpo: 43938 +.. date: 2021-04-25-22-44-27 +.. nonce: nC660q +.. section: Documentation + +Update dataclasses documentation to express that FrozenInstanceError is +derived from AttributeError. + +.. + +.. bpo: 43778 +.. date: 2021-04-08-22-42-02 +.. nonce: MszRnY +.. section: Documentation + +Fix the Sphinx glossary_search extension: create the _static/ sub-directory +if it doesn't exist. + +.. + +.. bpo: 43755 +.. date: 2021-04-06-14-55-45 +.. nonce: 1m0fGq +.. section: Documentation + +Update documentation to reflect that unparenthesized lambda expressions can +no longer be the expression part in an ``if`` clause in comprehensions and +generator expressions since Python 3.9. + +.. + +.. bpo: 43739 +.. date: 2021-04-06-07-05-49 +.. nonce: L4HjiX +.. section: Documentation + +Fixing the example code in Doc/extending/extending.rst to declare and +initialize the pmodule variable to be of the right type. + +.. + +.. bpo: 43961 +.. date: 2021-04-28-13-21-52 +.. nonce: gNchls +.. section: Tests + +Fix test_logging.test_namer_rotator_inheritance() on Windows: use +:func:`os.replace` rather than :func:`os.rename`. Patch by Victor Stinner. + +.. + +.. bpo: 43842 +.. date: 2021-04-16-14-07-40 +.. nonce: w60GAH +.. section: Tests + +Fix a race condition in the SMTP test of test_logging. Don't close a file +descriptor (socket) from a different thread while asyncore.loop() is polling +the file descriptor. Patch by Victor Stinner. + +.. + +.. bpo: 43843 +.. date: 2021-04-14-13-22-44 +.. nonce: ruIQKD +.. section: Tests + +:mod:`test.libregrtest` now marks a test as ENV_CHANGED (altered the +execution environment) if a thread raises an exception but does not catch +it. It sets a hook on :func:`threading.excepthook`. Use +``--fail-env-changed`` option to mark the test as failed. Patch by Victor +Stinner. + +.. + +.. bpo: 43811 +.. date: 2021-04-12-11-14-28 +.. nonce: vGNbnD +.. section: Tests + +Tests multiple OpenSSL versions on GitHub Actions. Use ccache to speed up +testing. + +.. + +.. bpo: 43791 +.. date: 2021-04-09-15-10-38 +.. nonce: 4KxiXK +.. section: Tests + +OpenSSL 3.0.0: Disable testing of legacy protocols TLS 1.0 and 1.1. Tests +are failing with TLSV1_ALERT_INTERNAL_ERROR. + +.. + +.. bpo: 43567 +.. date: 2021-03-31-19-50-01 +.. nonce: vd0a-p +.. section: Build + +Improved generated code refresh (AST/tokens/opcodes/keywords) on Windows. + +.. + +.. bpo: 43669 +.. date: 2021-03-30-14-19-39 +.. nonce: lWMUYx +.. section: Build + +Implement :pep:`644`. Python now requires OpenSSL 1.1.1 or newer. + +.. + +.. bpo: 35306 +.. date: 2021-04-22-21-37-41 +.. nonce: 10kSR- +.. section: Windows + +Adds additional arguments to :func:`os.startfile` function. + +.. + +.. bpo: 43538 +.. date: 2021-04-22-20-39-49 +.. nonce: F0Cg6X +.. section: Windows + +Avoid raising errors from :meth:`pathlib.Path.exists()` when passed an +invalid filename. + +.. + +.. bpo: 38822 +.. date: 2021-04-22-19-49-20 +.. nonce: jgdPmq +.. section: Windows + +Fixed :func:`os.stat` failing on inaccessible directories with a trailing +slash, rather than falling back to the parent directory's metadata. This +implicitly affected :func:`os.path.exists` and :func:`os.path.isdir`. + +.. + +.. bpo: 26227 +.. date: 2021-04-21-23-37-34 +.. nonce: QMY_eA +.. section: Windows + +Fixed decoding of host names in :func:`socket.gethostbyaddr` and +:func:`socket.gethostbyname_ex`. + +.. + +.. bpo: 40432 +.. date: 2021-04-20-23-07-22 +.. nonce: 9OFpoq +.. section: Windows + +Updated pegen regeneration script on Windows to find and use Python 3.8 or +higher. Prior to this, pegen regeneration already required 3.8 or higher, +but the script may have used lower versions of Python. + +.. + +.. bpo: 43745 +.. date: 2021-04-06-12-27-33 +.. nonce: rdKNda +.. section: Windows + +Actually updates Windows release to OpenSSL 1.1.1k. Earlier releases were +mislabelled and actually included 1.1.1i again. + +.. + +.. bpo: 43652 +.. date: 2021-04-03-18-54-31 +.. nonce: gNmfVN +.. section: Windows + +Update Tcl and Tk to 8.6.11 in Windows installer. + +.. + +.. bpo: 43492 +.. date: 2021-03-15-11-34-33 +.. nonce: AsYnVX +.. section: Windows + +Upgrade Windows installer to use SQLite 3.35.5. + +.. + +.. bpo: 30555 +.. date: 2017-12-16-12-23-51 +.. nonce: 3ybjly +.. section: Windows + +Fix ``WindowsConsoleIO`` errors in the presence of fd redirection. Patch by +Segev Finer. + +.. + +.. bpo: 42119 +.. date: 2021-05-02-21-03-27 +.. nonce: Y7BSX_ +.. section: macOS + +Fix check for macOS SDK paths when building Python. Narrow search to match +contents of SDKs, namely only files in ``/System/Library``, +``/System/IOSSupport``, and ``/usr`` other than ``/usr/local``. Previously, +anything under ``/System`` was assumed to be in an SDK which causes problems +with the new file system layout in 10.15+ where user file systems may appear +to be mounted under ``/System``. Paths in ``/Library`` were also +incorrectly treated as SDK locations. + +.. + +.. bpo: 43568 +.. date: 2021-05-02-19-50-52 +.. nonce: AeLNBd +.. section: macOS + +Drop support for MACOSX_DEPLOYMENT_TARGET < 10.3 + +.. + +.. bpo: 44009 +.. date: 2021-05-02-03-45-30 +.. nonce: uvhmlh +.. section: macOS + +Provide "python3.x-intel64" executable to allow reliably forcing macOS +universal2 framework builds to run under Rosetta 2 Intel-64 emulation on +Apple Silicon Macs. This can be useful for testing or when universal2 +wheels are not yet available. + +.. + +.. bpo: 43851 +.. date: 2021-04-15-01-20-45 +.. nonce: sDI60Y +.. section: macOS + +Build SQLite with ``SQLITE_OMIT_AUTOINIT`` on macOS. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 43492 +.. date: 2021-03-15-11-32-23 +.. nonce: 1ZRcV9 +.. section: macOS + +Update macOS installer to use SQLite 3.35.4. + +.. + +.. bpo: 42235 +.. date: 2020-11-01-17-37-16 +.. nonce: A97_BN +.. section: macOS + +``Mac/BuildScript/build-installer.py`` will now use "--enable-optimizations" +and ``--with-lto`` when building on macOS 10.15 or later. + +.. + +.. bpo: 37903 +.. date: 2021-05-02-20-25-53 +.. nonce: VQ6VTU +.. section: IDLE + +Add mouse actions to the shell sidebar. Left click and optional drag +selects one or more lines, as with the editor line number sidebar. Right +click after selecting raises a context menu with 'copy with prompts'. This +zips together prompts from the sidebar with lines from the selected text. + +.. + +.. bpo: 43981 +.. date: 2021-04-30-17-59-56 +.. nonce: 3EFl1H +.. section: IDLE + +Fix reference leak in test_squeezer. Patch by Pablo Galindo + +.. + +.. bpo: 37892 +.. date: 2021-04-29-02-40-41 +.. nonce: bgW2fk +.. section: IDLE + +Indent IDLE Shell input with spaces instead of tabs + +.. + +.. bpo: 43655 +.. date: 2021-04-04-20-52-07 +.. nonce: HSyaKH +.. section: IDLE + +IDLE dialog windows are now recognized as dialogs by window managers on +macOS and X Window. + +.. + +.. bpo: 37903 +.. date: 2019-08-24-23-49-36 +.. nonce: 4xjast +.. section: IDLE + +IDLE's shell now shows prompts in a separate side-bar. + +.. + +.. bpo: 43916 +.. date: 2021-04-29-17-35-48 +.. nonce: wvWt23 +.. section: C API + +Add a new :c:data:`Py_TPFLAGS_DISALLOW_INSTANTIATION` type flag to disallow +creating type instances. Patch by Victor Stinner. + +.. + +.. bpo: 43774 +.. date: 2021-04-29-10-17-21 +.. nonce: 5MGfgN +.. section: C API + +Remove the now unused ``PYMALLOC_DEBUG`` macro. Debug hooks on memory +allocators are now installed by default if Python is built in debug mode (if +``Py_DEBUG`` macro is defined). Moreover, they can now be used on Python +build in release mode (ex: using ``PYTHONMALLOC=debug`` environment +variable). + +.. + +.. bpo: 43962 +.. date: 2021-04-28-13-13-07 +.. nonce: 9Jzs5X +.. section: C API + +_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and +always increments id_refcount. Previously, calling +_xxsubinterpreters.get_current() could create an id_refcount inconsistency +when a _xxsubinterpreters.InterpreterID object was deallocated. Patch by +Victor Stinner. + +.. + +.. bpo: 28254 +.. date: 2021-04-28-12-33-44 +.. nonce: a2561e +.. section: C API + +Add new C-API functions to control the state of the garbage collector: +:c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, +:c:func:`PyGC_IsEnabled()`, corresponding to the functions in the :mod:`gc` +module. + +.. + +.. bpo: 43908 +.. date: 2021-04-22-10-46-40 +.. nonce: Co3YhZ +.. section: C API + +Introduce :const:`Py_TPFLAGS_IMMUTABLETYPE` flag for immutable type objects, +and modify :c:func:`PyType_Ready` to set it for static types. Patch by +Erlend E. Aasland. + +.. + +.. bpo: 43795 +.. date: 2021-04-20-15-06-29 +.. nonce: y0IP4c +.. section: C API + +:c:func:`PyMem_Calloc` is now available in the limited C API +(``Py_LIMITED_API``). + +.. + +.. bpo: 43868 +.. date: 2021-04-16-18-15-56 +.. nonce: twQ7KH +.. section: C API + +:c:func:`PyOS_ReadlineFunctionPointer` is no longer exported by limited C +API headers and by ``python3.dll`` on Windows. Like any function that takes +``FILE*``, it is not part of the stable ABI. + +.. + +.. bpo: 43795 +.. date: 2021-04-09-18-19-07 +.. nonce: l0yobT +.. section: C API + +Stable ABI and limited API definitions are generated from a central manifest +(:pep:`652`). + +.. + +.. bpo: 43753 +.. date: 2021-04-06-20-52-44 +.. nonce: xUsHp1 +.. section: C API + +Add the :c:func:`Py_Is(x, y) ` function to test if the *x* object is +the *y* object, the same as ``x is y`` in Python. Add also the +:c:func:`Py_IsNone`, :c:func:`Py_IsTrue`, :c:func:`Py_IsFalse` functions to +test if an object is, respectively, the ``None`` singleton, the ``True`` +singleton or the ``False`` singleton. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/3.10.0b2.rst b/Misc/NEWS.d/3.10.0b2.rst new file mode 100644 index 00000000000000..bda05d49605d3f --- /dev/null +++ b/Misc/NEWS.d/3.10.0b2.rst @@ -0,0 +1,524 @@ +.. bpo: 44022 +.. date: 2021-05-05-17-37-04 +.. nonce: bS3XJ9 +.. release date: 2021-05-31 +.. section: Security + +mod:`http.client` now avoids infinitely reading potential HTTP headers after +a ``100 Continue`` status response from the server. + +.. + +.. bpo: 43667 +.. date: 2021-05-27-17-34-29 +.. nonce: ND9jP3 +.. section: Core and Builtins + +Improve Unicode support in non-UTF locales on Oracle Solaris. This issue +does not affect other Solaris systems. + +.. + +.. bpo: 44232 +.. date: 2021-05-25-18-20-10 +.. nonce: DMcCCf +.. section: Core and Builtins + +Fix a regression in :func:`type` when a metaclass raises an exception. The C +function :c:func:`type_new` must properly report the exception when a +metaclass constructor raises an exception and the winner class is not the +metaclass. Patch by Victor Stinner. + +.. + +.. bpo: 44201 +.. date: 2021-05-21-21-16-03 +.. nonce: bGaSjt +.. section: Core and Builtins + +Avoid side effects of checking for specialized syntax errors in the REPL +that was causing it to ask for extra tokens after a syntax error had been +detected. Patch by Pablo Galindo + +.. + +.. bpo: 44184 +.. date: 2021-05-21-01-42-45 +.. nonce: 9qOptC +.. section: Core and Builtins + +Fix a crash at Python exit when a deallocator function removes the last +strong reference to a heap type. Patch by Victor Stinner. + +.. + +.. bpo: 44180 +.. date: 2021-05-19-20-33-36 +.. nonce: mQVaAs +.. section: Core and Builtins + +The parser doesn't report generic syntax errors that happen in a position +further away that the one it reached in the first pass. Patch by Pablo +Galindo + +.. + +.. bpo: 44168 +.. date: 2021-05-18-11-27-02 +.. nonce: mgB-rt +.. section: Core and Builtins + +Fix error message in the parser involving keyword arguments with invalid +expressions. Patch by Pablo Galindo + +.. + +.. bpo: 44143 +.. date: 2021-05-15-17-30-57 +.. nonce: 7UTS6H +.. section: Core and Builtins + +Fixed a crash in the parser that manifest when raising tokenizer errors when +an existing exception was present. Patch by Pablo Galindo. + +.. + +.. bpo: 44114 +.. date: 2021-05-12-14-26-16 +.. nonce: p-WfAE +.. section: Core and Builtins + +Fix incorrect dictkeys_reversed and dictitems_reversed function signatures +in C code, which broke webassembly builds. + +.. + +.. bpo: 43149 +.. date: 2021-05-08-17-18-37 +.. nonce: Kp5FxD +.. section: Core and Builtins + +Corrent the syntax error message regarding multiple exception types to not +refer to "exception groups". Patch by Pablo Galindo + +.. + +.. bpo: 44056 +.. date: 2021-05-06-12-43-04 +.. nonce: 4LWcJW +.. section: Core and Builtins + +Syntax errors when default ``except`` is not the last ``except`` are +reported with the correct location. Patch by Mark Shannon. + +.. + +.. bpo: 43822 +.. date: 2021-05-04-01-01-04 +.. nonce: 9VeCg0 +.. section: Core and Builtins + +The parser will prioritize tokenizer errors over custom syntax errors when +raising exceptions. Patch by Pablo Galindo. + +.. + +.. bpo: 28146 +.. date: 2021-01-13-19-34-41 +.. nonce: AZBBkH +.. section: Core and Builtins + +Fix a confusing error message in :func:`str.format`. + +.. + +.. bpo: 44254 +.. date: 2021-05-29-01-05-43 +.. nonce: f06xDm +.. section: Library + +On Mac, give turtledemo button text a color that works on both light or dark +background. Programmers cannot control the latter. + +.. + +.. bpo: 38693 +.. date: 2021-05-26-14-50-06 +.. nonce: NkMacJ +.. section: Library + +Prefer f-strings to ``.format`` in importlib.resources. + +.. + +.. bpo: 33693 +.. date: 2021-05-26-13-34-37 +.. nonce: 3okzdo +.. section: Library + +Importlib.metadata now prefers f-strings to .format. + +.. + +.. bpo: 44241 +.. date: 2021-05-26-13-15-51 +.. nonce: TBqej8 +.. section: Library + +Incorporate minor tweaks from importlib_metadata 4.1: SimplePath protocol, +support for Metadata 2.2. + +.. + +.. bpo: 44210 +.. date: 2021-05-21-21-23-43 +.. nonce: 5afQ3K +.. section: Library + +Make importlib.metadata._meta.PackageMetadata public. + +.. + +.. bpo: 43643 +.. date: 2021-05-21-12-12-35 +.. nonce: GWnmcF +.. section: Library + +Declare readers.MultiplexedPath.name as a property per the spec. + +.. + +.. bpo: 33433 +.. date: 2021-05-16-17-48-24 +.. nonce: MyzO71 +.. section: Library + +For IPv4 mapped IPv6 addresses (:rfc:`4291` Section 2.5.5.2), the +:mod:`ipaddress.IPv6Address.is_private` check is deferred to the mapped IPv4 +address. This solves a bug where public mapped IPv4 addresses were +considered private by the IPv6 check. + +.. + +.. bpo: 44145 +.. date: 2021-05-16-00-00-38 +.. nonce: ko5SJ7 +.. section: Library + +:mod:`hmac` computations were not releasing the GIL while calling the +OpenSSL ``HMAC_Update`` C API (a new feature in 3.9). This unintentionally +prevented parallel computation as other :mod:`hashlib` algorithms support. + +.. + +.. bpo: 37788 +.. date: 2021-05-13-19-07-28 +.. nonce: adeFcf +.. section: Library + +Fix a reference leak when a Thread object is never joined. + +.. + +.. bpo: 38908 +.. date: 2021-05-12-16-43-21 +.. nonce: nM2_rO +.. section: Library + +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:`runtime_checkable`. Previously, these checks +passed silently. Patch provided by Yurii Karabas. + +.. + +.. bpo: 44098 +.. date: 2021-05-10-17-45-00 +.. nonce: _MoxuZ +.. section: Library + +``typing.ParamSpec`` will no longer be found in the ``__parameters__`` of +most :mod:`typing` generics except in valid use locations specified by +:pep:`612`. This prevents incorrect usage like ``typing.List[P][int]``. This +change means incorrect usage which may have passed silently in 3.10 beta 1 +and earlier will now error. + +.. + +.. bpo: 44089 +.. date: 2021-05-09-22-52-34 +.. nonce: IoANsN +.. section: Library + +Allow subclassing ``csv.Error`` in 3.10 (it was allowed in 3.9 and earlier +but was disallowed in early versions of 3.10). + +.. + +.. bpo: 44059 +.. date: 2021-05-06-16-01-55 +.. nonce: GF5r6O +.. section: Library + +Register the SerenityOS Browser in the :mod:`webbrowser` module. + +.. + +.. bpo: 36515 +.. date: 2021-05-05-11-44-49 +.. nonce: uOSa3q +.. section: Library + +The :mod:`hashlib` module no longer does unaligned memory accesses when +compiled for ARM platforms. + +.. + +.. bpo: 44018 +.. date: 2021-05-03-10-07-43 +.. nonce: VDyW8f +.. section: Library + +random.seed() no longer mutates bytearray inputs. + +.. + +.. bpo: 38352 +.. date: 2021-05-02-13-54-25 +.. nonce: N9MlhV +.. section: Library + +Add ``IO``, ``BinaryIO``, ``TextIO``, ``Match``, and ``Pattern`` to +``typing.__all__``. Patch by Jelle Zijlstra. + +.. + +.. bpo: 43972 +.. date: 2021-04-30-16-58-24 +.. nonce: Y2r9lg +.. section: Library + +When :class:`http.server.SimpleHTTPRequestHandler` sends a ``301 (Moved +Permanently)`` for a directory path not ending with `/`, add a +``Content-Length: 0`` header. This improves the behavior for certain +clients. + +.. + +.. bpo: 28528 +.. date: 2021-04-29-00-48-00 +.. nonce: JLAVWj +.. section: Library + +Fix a bug in :mod:`pdb` where :meth:`~pdb.Pdb.checkline` raises +:exc:`AttributeError` if it is called after :meth:`~pdb.Pdb.reset`. + +.. + +.. bpo: 43650 +.. date: 2021-03-29-00-23-30 +.. nonce: v01tic +.. section: Library + +Fix :exc:`MemoryError` in :func:`shutil.unpack_archive` which fails inside +:func:`shutil._unpack_zipfile` on large files. Patch by Igor Bolshakov. + +.. + +.. bpo: 41730 +.. date: 2020-09-10-07-23-24 +.. nonce: DyKFi9 +.. section: Library + +``DeprecationWarning`` is now raised when importing :mod:`tkinter.tix`, +which has been deprecated in documentation since Python 3.6. + +.. + +.. bpo: 42392 +.. date: 2021-05-26-11-16-33 +.. nonce: oxRx6E +.. section: Documentation + +Document the deprecation and removal of the ``loop`` parameter for many +functions and classes in :mod:`asyncio`. + +.. + +.. bpo: 44195 +.. date: 2021-05-23-09-11-28 +.. nonce: 1bqkOs +.. section: Documentation + +Corrected references to ``TraversableResources`` in docs. There is no +``TraversableReader``. + +.. + +.. bpo: 41963 +.. date: 2021-05-17-20-03-47 +.. nonce: eUz9_o +.. section: Documentation + +Document that ``ConfigParser`` strips off comments when reading +configuration files. + +.. + +.. bpo: 44072 +.. date: 2021-05-08-09-48-05 +.. nonce: fb2x5I +.. section: Documentation + +Correct where in the numeric ABC hierarchy ``**`` support is added, i.e., in +numbers.Complex, not numbers.Integral. + +.. + +.. bpo: 43558 +.. date: 2021-05-07-12-27-09 +.. nonce: UGhA8R +.. section: Documentation + +Add the remark to :mod:`dataclasses` documentation that the :meth:`__init__` +of any base class has to be called in :meth:`__post_init__`, along with a +code example. + +.. + +.. bpo: 44025 +.. date: 2021-05-03-22-08-08 +.. nonce: gcB7iP +.. section: Documentation + +Clarify when '_' in match statements is a keyword, and when not. + +.. + +.. bpo: 31904 +.. date: 2021-05-07-15-46-04 +.. nonce: 8dk3la +.. section: Tests + +Ignore error string case in test_py_compile ``test_file_not_exists()``. + +.. + +.. bpo: 42083 +.. date: 2021-05-04-18-10-57 +.. nonce: EMS2TK +.. section: Tests + +Add test to check that ``PyStructSequence_NewType`` accepts a +``PyStructSequence_Desc`` with ``doc`` field set to ``NULL``. + +.. + +.. bpo: 35753 +.. date: 2020-10-25-19-20-26 +.. nonce: 2LT-hO +.. section: Tests + +Fix crash in doctest when doctest parses modules that include unwrappable +functions by skipping those functions. + +.. + +.. bpo: 41282 +.. date: 2021-05-24-03-31-17 +.. nonce: L8nP44 +.. section: Build + +Fix broken ``make install`` that caused standard library extension modules +to be unnecessarily and incorrectly rebuilt during the install phase of +cpython. + +.. + +.. bpo: 42686 +.. date: 2021-01-01-21-21-03 +.. nonce: G_f-TC +.. section: Windows + +Build :mod:`sqlite3` with math functions enabled. Patch by Erlend E. +Aasland. + +.. + +.. bpo: 43109 +.. date: 2021-05-24-21-15-41 +.. nonce: npKJ9c +.. section: macOS + +Allow --with-lto configure option to work with Apple-supplied Xcode or +Command Line Tools. + +.. + +.. bpo: 41611 +.. date: 2021-05-27-18-22-46 +.. nonce: jOKpfc +.. section: IDLE + +Avoid uncaught exceptions in ``AutoCompleteWindow.winconfig_event()``. + +.. + +.. bpo: 41611 +.. date: 2021-05-27-13-39-43 +.. nonce: liNQqj +.. section: IDLE + +Fix IDLE sometimes freezing upon tab-completion on macOS. + +.. + +.. bpo: 44010 +.. date: 2021-05-09-09-02-09 +.. nonce: TaLe9x +.. section: IDLE + +Highlight the new :ref:`match ` statement's :ref:`soft keywords +`: :keyword:`match`, :keyword:`case `, and :keyword:`_ +`. However, this highlighting is not perfect and will be +incorrect in some rare cases, including some ``_``-s in ``case`` patterns. + +.. + +.. bpo: 44026 +.. date: 2021-05-05-09-45-24 +.. nonce: m2Z0zR +.. section: IDLE + +Include interpreter's typo fix suggestions in message line for NameErrors +and AttributeErrors. Patch by E. Paine. + +.. + +.. bpo: 44074 +.. date: 2021-05-08-13-57-00 +.. nonce: F09kCK +.. section: Tools/Demos + +Make patchcheck automatically detect the correct base branch name +(previously it was hardcoded to 'master') + +.. + +.. bpo: 43795 +.. date: 2021-05-19-15-09-47 +.. nonce: WAHRxt +.. section: C API + +The undocumented function :c:func:`Py_FrozenMain` is removed from the +Limited API. + +.. + +.. bpo: 43795 +.. date: 2021-05-05-19-04-50 +.. nonce: 9Ojj73 +.. section: C API + +:c:func:`PyCodec_Unregister` is now properly exported as a function in the +Windows Stable ABI DLL. diff --git a/Misc/NEWS.d/3.10.0b3.rst b/Misc/NEWS.d/3.10.0b3.rst new file mode 100644 index 00000000000000..5f399ad5aa8716 --- /dev/null +++ b/Misc/NEWS.d/3.10.0b3.rst @@ -0,0 +1,346 @@ +.. bpo: 44409 +.. date: 2021-06-13-23-12-18 +.. nonce: eW4LS- +.. release date: 2021-06-17 +.. section: Core and Builtins + +Fix error location information for tokenizer errors raised on initialization +of the tokenizer. Patch by Pablo Galindo. + +.. + +.. bpo: 44396 +.. date: 2021-06-11-18-17-42 +.. nonce: Z9EKim +.. section: Core and Builtins + +Fix a possible crash in the tokenizer when raising syntax errors for +unclosed strings. Patch by Pablo Galindo. + +.. + +.. bpo: 44349 +.. date: 2021-06-08-22-49-06 +.. nonce: xgEgeA +.. section: Core and Builtins + +Fix an edge case when displaying text from files with encoding in syntax +errors. Patch by Pablo Galindo. + +.. + +.. bpo: 44335 +.. date: 2021-06-08-01-13-47 +.. nonce: GQTTkl +.. section: Core and Builtins + +Fix a regression when identifying incorrect characters in syntax errors. +Patch by Pablo Galindo + +.. + +.. bpo: 44304 +.. date: 2021-06-05-02-34-57 +.. nonce: _MAoPc +.. section: Core and Builtins + +Fix a crash in the :mod:`sqlite3` module that happened when the garbage +collector clears :class:`sqlite.Statement` objects. Patch by Pablo Galindo + +.. + +.. bpo: 44305 +.. date: 2021-06-03-22-51-50 +.. nonce: 66dVDG +.. section: Core and Builtins + +Improve error message for ``try`` blocks without ``except`` or ``finally`` +blocks. Patch by Pablo Galindo. + +.. + +.. bpo: 43833 +.. date: 2021-04-18-18-07-33 +.. nonce: oChkCi +.. section: Core and Builtins + +Emit a deprecation warning if the numeric literal is immediately followed by +one of keywords: and, else, for, if, in, is, or. Raise a syntax error with +more informative message if it is immediately followed by other keyword or +identifier. + +.. + +.. bpo: 11105 +.. date: 2020-06-02-13-21-14 +.. nonce: wceryW +.. section: Core and Builtins + +When compiling :class:`ast.AST` objects with recursive references through +:func:`compile`, the interpreter doesn't crash anymore instead it raises a +:exc:`RecursionError`. + +.. + +.. bpo: 42972 +.. date: 2021-06-15-13-51-25 +.. nonce: UnyYo1 +.. section: Library + +The _thread.RLock type now fully implement the GC protocol: add a traverse +function and the :const:`Py_TPFLAGS_HAVE_GC` flag. Patch by Victor Stinner. + +.. + +.. bpo: 44422 +.. date: 2021-06-14-23-28-17 +.. nonce: BlWOgv +.. section: Library + +The :func:`threading.enumerate` function now uses a reentrant lock to +prevent a hang on reentrant call. Patch by Victor Stinner. + +.. + +.. bpo: 44389 +.. date: 2021-06-12-22-58-20 +.. nonce: WTRnoC +.. section: Library + +Fix deprecation of :data:`ssl.OP_NO_TLSv1_3` + +.. + +.. bpo: 44362 +.. date: 2021-06-10-20-07-32 +.. nonce: oVOMfd +.. section: Library + +Improve :mod:`ssl` module's deprecation messages, error reporting, and +documentation for deprecations. + +.. + +.. bpo: 44342 +.. date: 2021-06-10-15-06-47 +.. nonce: qqkGlj +.. section: Library + +[Enum] Change pickling from by-value to by-name. + +.. + +.. bpo: 44356 +.. date: 2021-06-10-08-35-38 +.. nonce: 6oDFhO +.. section: Library + +[Enum] Allow multiple data-type mixins if they are all the same. + +.. + +.. bpo: 44351 +.. date: 2021-06-10-07-26-12 +.. nonce: rvyf2v +.. section: Library + +Restore back :func:`parse_makefile` in :mod:`distutils.sysconfig` because it +behaves differently than the similar implementation in :mod:`sysconfig`. + +.. + +.. bpo: 44242 +.. date: 2021-06-07-10-26-14 +.. nonce: MKeMCQ +.. section: Library + +Remove missing flag check from Enum creation and move into a ``verify`` +decorator. + +.. + +.. bpo: 44246 +.. date: 2021-05-31-11-34-56 +.. nonce: yHAkF0 +.. section: Library + +In ``importlib.metadata``, restore compatibility in the result from +``Distribution.entry_points`` (``EntryPoints``) to honor expectations in +older implementations and issuing deprecation warnings for these cases: A. +``EntryPoints`` objects are once again mutable, allowing for ``sort()`` +and other list-based mutation operations. Avoid deprecation warnings by +casting to a mutable sequence (e.g. ``list(dist.entry_points).sort()``). +B. ``EntryPoints`` results once again allow for access by index. To avoid +deprecation warnings, cast the result to a Sequence first (e.g. +``tuple(dist.entry_points)[0]``). + +.. + +.. bpo: 44246 +.. date: 2021-05-31-11-28-03 +.. nonce: nhmt-v +.. section: Library + +In importlib.metadata.entry_points, de-duplication of distributions no +longer requires loading the full metadata for PathDistribution objects, +improving entry point loading performance by ~10x. + +.. + +.. bpo: 43853 +.. date: 2021-04-15-12-02-17 +.. nonce: XXCVAp +.. section: Library + +Improved string handling for :mod:`sqlite3` user-defined functions and +aggregates: + +* It is now possible to pass strings with embedded null characters to UDFs +* Conversion failures now correctly raise :exc:`MemoryError` + +Patch by Erlend E. Aasland. + +.. + +.. bpo: 43318 +.. date: 2021-02-25-08-32-06 +.. nonce: bZJw6V +.. section: Library + +Fix a bug where :mod:`pdb` does not always echo cleared breakpoints. + +.. + +.. bpo: 37022 +.. date: 2020-01-25-12-58-20 +.. nonce: FUZI25 +.. section: Library + +:mod:`pdb` now displays exceptions from ``repr()`` with its ``p`` and ``pp`` +commands. + +.. + +.. bpo: 44392 +.. date: 2021-06-16-18-09-49 +.. nonce: 6RF1Sc +.. section: Documentation + +Added a new section in the C API documentation for types used in type +hinting. Documented ``Py_GenericAlias`` and ``Py_GenericAliasType``. + +.. + +.. bpo: 38291 +.. date: 2021-06-14-09-20-37 +.. nonce: VMYa_Q +.. section: Documentation + +Mark ``typing.io`` and ``typing.re`` as deprecated since Python 3.8 in the +documentation. They were never properly supported by type checkers. + +.. + +.. bpo: 44322 +.. date: 2021-06-06-14-12-00 +.. nonce: K0PHfE +.. section: Documentation + +Document that SyntaxError args have a details tuple and that details are +adjusted for errors in f-string field replacement expressions. + +.. + +.. bpo: 44363 +.. date: 2021-06-10-11-19-43 +.. nonce: -K9jD0 +.. section: Tests + +Account for address sanitizer in test_capi. test_capi now passes when run +GCC address sanitizer. + +.. + +.. bpo: 43921 +.. date: 2021-06-03-03-29-34 +.. nonce: nwH1FS +.. section: Tests + +Fix test_ssl.test_wrong_cert_tls13(): use ``suppress_ragged_eofs=False``, +since ``read()`` can raise :exc:`ssl.SSLEOFError` on Windows. Patch by +Victor Stinner. + +.. + +.. bpo: 43921 +.. date: 2021-06-02-17-41-42 +.. nonce: xP7yZ4 +.. section: Tests + +Fix test_pha_required_nocert() of test_ssl: catch two more EOF cases (when +the ``recv()`` method returns an empty string). Patch by Victor Stinner. + +.. + +.. bpo: 44381 +.. date: 2021-06-10-18-08-44 +.. nonce: Xpc1iX +.. section: Build + +The Windows build now accepts :envvar:`EnableControlFlowGuard` set to +``guard`` to enable CFG. + +.. + +.. bpo: 40128 +.. date: 2021-06-11-17-43-39 +.. nonce: 7vDN3U +.. section: IDLE + +Mostly fix completions on macOS when not using tcl/tk 8.6.11 (as with 3.9). +The added update_idletask call should be harmless and possibly helpful +otherwise. + +.. + +.. bpo: 33962 +.. date: 2021-06-10-00-50-02 +.. nonce: ikAUNg +.. section: IDLE + +Move the indent space setting from the Font tab to the new Windows tab. +Patch by Mark Roseman and Terry Jan Reedy. + +.. + +.. bpo: 40468 +.. date: 2021-06-08-03-04-51 +.. nonce: tUCGUb +.. section: IDLE + +Split the settings dialog General tab into Windows and Shell/ED tabs. Move +help sources, which extend the Help menu, to the Extensions tab. Make space +for new options and shorten the dialog. The latter makes the dialog better +fit small screens. + +.. + +.. bpo: 43795 +.. date: 2021-06-15-16-28-18 +.. nonce: fy0AXK +.. section: C API + +The list in :ref:`stable-abi-list` now shows the public name +:c:struct:`PyFrameObject` rather than ``_frame``. The non-existing entry +``_node`` no longer appears in the list. + +.. + +.. bpo: 44378 +.. date: 2021-06-10-15-22-31 +.. nonce: jGYakF +.. section: C API + +:c:func:`Py_IS_TYPE` no longer uses :c:func:`Py_TYPE` to avoid a compiler +warning: no longer cast ``const PyObject*`` to ``PyObject*``. Patch by +Victor Stinner. diff --git a/Misc/NEWS.d/3.10.0b4.rst b/Misc/NEWS.d/3.10.0b4.rst new file mode 100644 index 00000000000000..417bd36ab4ba1e --- /dev/null +++ b/Misc/NEWS.d/3.10.0b4.rst @@ -0,0 +1,437 @@ +.. bpo: 41180 +.. date: 2021-06-29-23-40-22 +.. nonce: uTWHv_ +.. release date: 2021-07-10 +.. section: Security + +Add auditing events to the :mod:`marshal` module, and stop raising +``code.__init__`` events for every unmarshalled code object. Directly +instantiated code objects will continue to raise an event, and audit event +handlers should inspect or collect the raw marshal data. This reduces a +significant performance overhead when loading from ``.pyc`` files. + +.. + +.. bpo: 44562 +.. date: 2021-07-04-23-38-51 +.. nonce: QdeRQo +.. section: Core and Builtins + +Remove uses of :c:func:`PyObject_GC_Del` in error path when initializing +:class:`types.GenericAlias`. + +.. + +.. bpo: 41486 +.. date: 2021-07-04-17-41-47 +.. nonce: DiM24a +.. section: Core and Builtins + +Fix a memory consumption and copying performance regression in earlier 3.10 +beta releases if someone used an output buffer larger than 4GiB with +zlib.decompress on input data that expands that large. + +.. + +.. bpo: 44553 +.. date: 2021-07-02-22-54-41 +.. nonce: l9YqGg +.. section: Core and Builtins + +Implement GC methods for ``types.Union`` to break reference cycles and +prevent memory leaks. + +.. + +.. bpo: 44523 +.. date: 2021-06-29-11-49-29 +.. nonce: 67-ZIP +.. section: Core and Builtins + +Remove the pass-through for :func:`hash` of :class:`weakref.proxy` objects +to prevent unintended consequences when the original referred object dies +while the proxy is part of a hashable object. Patch by Pablo Galindo. + +.. + +.. bpo: 44483 +.. date: 2021-06-22-19-08-19 +.. nonce: eq2f7T +.. section: Core and Builtins + +Fix a crash in ``types.Union`` objects when creating a union of an object +with bad ``__module__`` field. + +.. + +.. bpo: 44297 +.. date: 2021-06-19-12-41-13 +.. nonce: F53vHj +.. section: Core and Builtins + +Make sure that the line number is set when entering a comprehension scope. +Ensures that backtraces inclusing generator expressions show the correct +line number. + +.. + +.. bpo: 44456 +.. date: 2021-06-18-22-08-25 +.. nonce: L0Rhko +.. section: Core and Builtins + +Improve the syntax error when mixing positional and keyword patterns. Patch +by Pablo Galindo. + +.. + +.. bpo: 44368 +.. date: 2021-06-09-22-56-59 +.. nonce: vgT0Cx +.. section: Core and Builtins + +Improve syntax errors for invalid "as" targets. Patch by Pablo Galindo + +.. + +.. bpo: 44317 +.. date: 2021-06-06-00-29-14 +.. nonce: xPPhcZ +.. section: Core and Builtins + +Improve tokenizer error with improved locations. Patch by Pablo Galindo. + +.. + +.. bpo: 43667 +.. date: 2021-05-27-17-34-29 +.. nonce: ND9jP3 +.. section: Core and Builtins + +Improve Unicode support in non-UTF locales on Oracle Solaris. This issue +does not affect other Solaris systems. + +.. + +.. bpo: 44558 +.. date: 2021-07-04-21-16-53 +.. nonce: cm7Slv +.. section: Library + +Make the implementation consistency of :func:`~operator.indexOf` between C +and Python versions. Patch by Dong-hee Na. + +.. + +.. bpo: 34798 +.. date: 2021-06-30-13-29-49 +.. nonce: t7FCa0 +.. section: Library + +Break up paragraph about :class:`pprint.PrettyPrinter` construction +parameters to make it easier to read. + +.. + +.. bpo: 44516 +.. date: 2021-06-26-12-27-14 +.. nonce: BVyX_y +.. section: Library + +Update vendored pip to 21.1.3 + +.. + +.. bpo: 44468 +.. date: 2021-06-23-19-02-00 +.. nonce: -klV5- +.. section: Library + +:func:`typing.get_type_hints` now finds annotations in classes and base +classes with unexpected ``__module__``. Previously, it skipped those MRO +elements. + +.. + +.. bpo: 43977 +.. date: 2021-06-22-16-45-48 +.. nonce: bamAGF +.. section: Library + +Set the proper :const:`Py_TPFLAGS_MAPPING` and :const:`Py_TPFLAGS_SEQUENCE` +flags for subclasses created before a parent has been registered as a +:class:`collections.abc.Mapping` or :class:`collections.abc.Sequence`. + +.. + +.. bpo: 44482 +.. date: 2021-06-22-08-43-04 +.. nonce: U9GznK +.. section: Library + +Fix very unlikely resource leak in :mod:`glob` in alternate Python +implementations. + +.. + +.. bpo: 44466 +.. date: 2021-06-21-12-43-04 +.. nonce: NSm6mv +.. section: Library + +The :mod:`faulthandler` module now detects if a fatal error occurs during a +garbage collector collection. Patch by Victor Stinner. + +.. + +.. bpo: 44404 +.. date: 2021-06-20-19-01-11 +.. nonce: McfrYB +.. section: Library + +:mod:`tkinter`'s ``after()`` method now supports callables without the +``__name__`` attribute. + +.. + +.. bpo: 44458 +.. date: 2021-06-20-07-14-46 +.. nonce: myqCQ0 +.. section: Library + +``BUFFER_BLOCK_SIZE`` is now declared static, to avoid linking collisions +when bz2, lmza or zlib are statically linked. + +.. + +.. bpo: 44464 +.. date: 2021-06-19-21-52-27 +.. nonce: U2oa-a +.. section: Library + +Remove exception for flake8 in deprecated importlib.metadata interfaces. +Sync with importlib_metadata 4.6. + +.. + +.. bpo: 44446 +.. date: 2021-06-17-22-39-34 +.. nonce: qwdRic +.. section: Library + +Take into account that ``lineno`` might be ``None`` in +:class:`traceback.FrameSummary`. + +.. + +.. bpo: 44439 +.. date: 2021-06-17-15-01-51 +.. nonce: 1S7QhT +.. section: Library + +Fix in :meth:`bz2.BZ2File.write` / :meth:`lzma.LZMAFile.write` methods, when +the input data is an object that supports the buffer protocol, the file +length may be wrong. + +.. + +.. bpo: 44434 +.. date: 2021-06-16-16-52-14 +.. nonce: SQS4Pg +.. section: Library + +_thread.start_new_thread() no longer calls PyThread_exit_thread() explicitly +at the thread exit, the call was redundant. On Linux with the glibc, +pthread_exit() aborts the whole process if dlopen() fails to open +libgcc_s.so file (ex: EMFILE error). Patch by Victor Stinner. + +.. + +.. bpo: 44395 +.. date: 2021-06-12-10-08-14 +.. nonce: PcW6Sx +.. section: Library + +Fix :meth:`~email.message.MIMEPart.as_string` to pass unixfrom properly. +Patch by Dong-hee Na. + +.. + +.. bpo: 34266 +.. date: 2021-06-10-21-53-46 +.. nonce: k3fxnm +.. section: Library + +Handle exceptions from parsing the arg of :mod:`pdb`'s run/restart command. + +.. + +.. bpo: 44077 +.. date: 2021-05-13-19-44-38 +.. nonce: 04b2a4 +.. section: Library + +It's now possible to receive the type of service (ToS), a.k.a. +differentiated services (DS), a.k.a. differenciated services code point +(DSCP) and excplicit congestion notification (ECN) IP header fields with +``socket.IP_RECVTOS``. + +.. + +.. bpo: 43024 +.. date: 2021-01-25-21-24-55 +.. nonce: vAUrIi +.. section: Library + +Improve the help signature of :func:`traceback.print_exception`, +:func:`traceback.format_exception` and +:func:`traceback.format_exception_only`. + +.. + +.. bpo: 30256 +.. date: 2019-09-25-13-54-41 +.. nonce: wBkzox +.. section: Library + +Pass multiprocessing BaseProxy argument ``manager_owned`` through AutoProxy. + +.. + +.. bpo: 44558 +.. date: 2021-07-03-18-25-17 +.. nonce: 0pTknl +.. section: Documentation + +Match the docstring and python implementation of :func:`~operator.countOf` +to the behavior of its c implementation. + +.. + +.. bpo: 38062 +.. date: 2021-06-28-12-13-48 +.. nonce: 9Ehp9O +.. section: Documentation + +Clarify that atexit uses equality comparisons internally. + +.. + +.. bpo: 40620 +.. date: 2021-06-26-17-41-06 +.. nonce: PAYDrB +.. section: Documentation + +Convert examples in tutorial controlflow.rst section 4.3 to be +interpreter-demo style. + +.. + +.. bpo: 13814 +.. date: 2021-06-21-15-46-32 +.. nonce: LDcslu +.. section: Documentation + +In the Design FAQ, answer "Why don't generators support the with statement?" + +.. + +.. bpo: 41621 +.. date: 2020-08-24-13-35-04 +.. nonce: nqaw9G +.. section: Documentation + +Document that :class:`collections.defaultdict` parameter ``default_factory`` +defaults to None and is positional-only. + +.. + +.. bpo: 44287 +.. date: 2021-06-21-17-53-41 +.. nonce: YON57s +.. section: Tests + +Fix asyncio test_popen() of test_windows_utils by using a longer timeout. +Use military grade battle-tested :data:`test.support.SHORT_TIMEOUT` timeout +rather than a hardcoded timeout of 10 seconds: it's 30 seconds by default, +but it is made longer on slow buildbots. Patch by Victor Stinner. + +.. + +.. bpo: 44451 +.. date: 2021-06-18-15-19-35 +.. nonce: aj5pqE +.. section: Tests + +Reset ``DeprecationWarning`` filters in +``test.test_importlib.test_metadata_api.APITests.test_entry_points_by_index`` +to avoid ``StopIteration`` error if ``DeprecationWarnings`` are ignored. + +.. + +.. bpo: 30256 +.. date: 2019-09-25-18-10-10 +.. nonce: A5i76Q +.. section: Tests + +Add test for nested queues when using ``multiprocessing`` shared objects +``AutoProxy[Queue]`` inside ``ListProxy`` and ``DictProxy`` + +.. + +.. bpo: 44535 +.. date: 2021-06-30-02-32-46 +.. nonce: M9iN4- +.. section: Build + +Enable building using a Visual Studio 2022 install on Windows. + +.. + +.. bpo: 43298 +.. date: 2021-06-19-11-50-03 +.. nonce: 9ircMb +.. section: Build + +Improved error message when building without a Windows SDK installed. + +.. + +.. bpo: 44582 +.. date: 2021-07-07-21-07-18 +.. nonce: 4Mm6Hh +.. section: Windows + +Accelerate speed of :mod:`mimetypes` initialization using a native +implementation of the registry scan. + +.. + +.. bpo: 41299 +.. date: 2021-06-06-16-36-13 +.. nonce: Rg-vb_ +.. section: Windows + +Fix 16ms jitter when using timeouts in :mod:`threading`, such as with +:meth:`threading.Lock.acquire` or :meth:`threading.Condition.wait`. + +.. + +.. bpo: 44441 +.. date: 2021-06-23-12-12-04 +.. nonce: 3p14JB +.. section: C API + +:c:func:`Py_RunMain` now resets :c:data:`PyImport_Inittab` to its initial +value at exit. It must be possible to call :c:func:`PyImport_AppendInittab` +or :c:func:`PyImport_ExtendInittab` at each Python initialization. Patch by +Victor Stinner. + +.. + +.. bpo: 40939 +.. date: 2021-06-22-17-00-06 +.. nonce: CGB0I5 +.. section: C API + +Removed documentation for the removed ``PyParser_*`` C API. diff --git a/Misc/NEWS.d/3.10.0rc1.rst b/Misc/NEWS.d/3.10.0rc1.rst new file mode 100644 index 00000000000000..67f31b81622ace --- /dev/null +++ b/Misc/NEWS.d/3.10.0rc1.rst @@ -0,0 +1,645 @@ +.. bpo: 44600 +.. date: 2021-07-25-20-04-54 +.. nonce: 0WMldg +.. release date: 2021-08-02 +.. section: Security + +Fix incorrect line numbers while tracing some failed patterns in :ref:`match +` statements. Patch by Charles Burkland. + +.. + +.. bpo: 44792 +.. date: 2021-07-31-12-12-57 +.. nonce: mOReTW +.. section: Core and Builtins + +Improve syntax errors for if expressions. Patch by Miguel Brito + +.. + +.. bpo: 34013 +.. date: 2021-07-27-11-14-22 +.. nonce: SjLFe- +.. section: Core and Builtins + +Generalize the invalid legacy statement custom error message (like the one +generated when "print" is called without parentheses) to include more +generic expressions. Patch by Pablo Galindo + +.. + +.. bpo: 44732 +.. date: 2021-07-26-15-27-03 +.. nonce: IxObt3 +.. section: Core and Builtins + +Rename ``types.Union`` to ``types.UnionType``. + +.. + +.. bpo: 44698 +.. date: 2021-07-21-15-26-56 +.. nonce: DA4_0o +.. section: Core and Builtins + +Fix undefined behaviour in complex object exponentiation. + +.. + +.. bpo: 44653 +.. date: 2021-07-19-20-49-06 +.. nonce: WcqGyI +.. section: Core and Builtins + +Support :mod:`typing` types in parameter substitution in the union type. + +.. + +.. bpo: 44676 +.. date: 2021-07-19-19-53-46 +.. nonce: WgIMvh +.. section: Core and Builtins + +Add ability to serialise ``types.Union`` objects. Patch provided by Yurii +Karabas. + +.. + +.. bpo: 44633 +.. date: 2021-07-17-21-04-04 +.. nonce: 5-zKeI +.. section: Core and Builtins + +Parameter substitution of the union type with wrong types now raises +``TypeError`` instead of returning ``NotImplemented``. + +.. + +.. bpo: 44662 +.. date: 2021-07-17-13-41-58 +.. nonce: q22kWR +.. section: Core and Builtins + +Add ``__module__`` to ``types.Union``. This also fixes ``types.Union`` +issues with ``typing.Annotated``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 44655 +.. date: 2021-07-16-21-35-14 +.. nonce: 95I7M6 +.. section: Core and Builtins + +Include the name of the type in unset __slots__ attribute errors. Patch by +Pablo Galindo + +.. + +.. bpo: 44655 +.. date: 2021-07-16-20-25-37 +.. nonce: I3wRjL +.. section: Core and Builtins + +Don't include a missing attribute with the same name as the failing one when +offering suggestions for missing attributes. Patch by Pablo Galindo + +.. + +.. bpo: 44646 +.. date: 2021-07-16-09-59-13 +.. nonce: Yb6s05 +.. section: Core and Builtins + +Fix the hash of the union type: it no longer depends on the order of +arguments. + +.. + +.. bpo: 44636 +.. date: 2021-07-16-09-36-12 +.. nonce: ZWebi8 +.. section: Core and Builtins + +Collapse union of equal types. E.g. the result of ``int | int`` is now +``int``. Fix comparison of the union type with non-hashable objects. E.g. +``int | str == {}`` no longer raises a TypeError. + +.. + +.. bpo: 44635 +.. date: 2021-07-14-13-54-07 +.. nonce: 7ZMAdB +.. section: Core and Builtins + +Convert ``None`` to ``type(None)`` in the union type constructor. + +.. + +.. bpo: 44589 +.. date: 2021-07-13-23-19-41 +.. nonce: 59OH8T +.. section: Core and Builtins + +Mapping patterns in ``match`` statements with two or more equal literal keys +will now raise a :exc:`SyntaxError` at compile-time. + +.. + +.. bpo: 44606 +.. date: 2021-07-13-20-22-12 +.. nonce: S3Bv2w +.. section: Core and Builtins + +Fix ``__instancecheck__`` and ``__subclasscheck__`` for the union type. + +.. + +.. bpo: 42073 +.. date: 2021-07-13-17-47-32 +.. nonce: 9wopiC +.. section: Core and Builtins + +The ``@classmethod`` decorator can now wrap other classmethod-like +descriptors. + +.. + +.. bpo: 44490 +.. date: 2021-07-06-22-22-15 +.. nonce: BJxPbZ +.. section: Core and Builtins + +:mod:`typing` now searches for type parameters in ``types.Union`` objects. +``get_type_hints`` will also properly resolve annotations with nested +``types.Union`` objects. Patch provided by Yurii Karabas. + +.. + +.. bpo: 44490 +.. date: 2021-07-01-11-59-34 +.. nonce: xY80VR +.. section: Core and Builtins + +Add ``__parameters__`` attribute and ``__getitem__`` operator to +``types.Union``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 44472 +.. date: 2021-06-21-11-19-54 +.. nonce: Vvm1yn +.. section: Core and Builtins + +Fix ltrace functionality when exceptions are raised. Patch by Pablo Galindo + +.. + +.. bpo: 44806 +.. date: 2021-08-02-14-37-32 +.. nonce: wOW_Qn +.. section: Library + +Non-protocol subclasses of :class:`typing.Protocol` ignore now the +``__init__`` method inherited from protocol base classes. + +.. + +.. bpo: 44793 +.. date: 2021-07-31-20-28-20 +.. nonce: woaQSg +.. section: Library + +Fix checking the number of arguments when subscribe a generic type with +``ParamSpec`` parameter. + +.. + +.. bpo: 44784 +.. date: 2021-07-31-08-45-31 +.. nonce: fIMIDS +.. section: Library + +In importlib.metadata tests, override warnings behavior under expected +DeprecationWarnings (importlib_metadata 4.6.3). + +.. + +.. bpo: 44667 +.. date: 2021-07-30-23-27-30 +.. nonce: tu0Xrv +.. section: Library + +The :func:`tokenize.tokenize` doesn't incorrectly generate a ``NEWLINE`` +token if the source doesn't end with a new line character but the last line +is a comment, as the function is already generating a ``NL`` token. Patch by +Pablo Galindo + +.. + +.. bpo: 44752 +.. date: 2021-07-27-22-11-29 +.. nonce: _bvbrZ +.. section: Library + +:mod:`rcompleter` does not call :func:`getattr` on :class:`property` objects +to avoid the side-effect of evaluating the corresponding method. + +.. + +.. bpo: 44720 +.. date: 2021-07-24-02-17-59 +.. nonce: shU5Qm +.. section: Library + +``weakref.proxy`` objects referencing non-iterators now raise ``TypeError`` +rather than dereferencing the null ``tp_iternext`` slot and crashing. + +.. + +.. bpo: 44704 +.. date: 2021-07-21-23-16-30 +.. nonce: iqHLxQ +.. section: Library + +The implementation of ``collections.abc.Set._hash()`` now matches that of +``frozenset.__hash__()``. + +.. + +.. bpo: 44666 +.. date: 2021-07-21-10-43-22 +.. nonce: CEThkv +.. section: Library + +Fixed issue in :func:`compileall.compile_file` when ``sys.stdout`` is +redirected. Patch by Stefan Hölzl. + +.. + +.. bpo: 42854 +.. date: 2021-07-20-21-51-35 +.. nonce: ThuDMI +.. section: Library + +Fixed a bug in the :mod:`_ssl` module that was throwing :exc:`OverflowError` +when using :meth:`_ssl._SSLSocket.write` and :meth:`_ssl._SSLSocket.read` +for a big value of the ``len`` parameter. Patch by Pablo Galindo + +.. + +.. bpo: 44353 +.. date: 2021-07-19-22-43-15 +.. nonce: HF81_Q +.. section: Library + +Refactor ``typing.NewType`` from function into callable class. Patch +provided by Yurii Karabas. + +.. + +.. bpo: 44524 +.. date: 2021-07-19-14-04-42 +.. nonce: Nbf2JC +.. section: Library + +Add missing ``__name__`` and ``__qualname__`` attributes to ``typing`` +module classes. Patch provided by Yurii Karabas. + +.. + +.. bpo: 40897 +.. date: 2021-07-16-13-40-31 +.. nonce: aveAre +.. section: Library + +Give priority to using the current class constructor in +:func:`inspect.signature`. Patch by Weipeng Hong. + +.. + +.. bpo: 44648 +.. date: 2021-07-15-16-51-32 +.. nonce: 2o49TB +.. section: Library + +Fixed wrong error being thrown by :func:`inspect.getsource` when examining a +class in the interactive session. Instead of :exc:`TypeError`, it should be +:exc:`OSError` with appropriate error message. + +.. + +.. bpo: 44608 +.. date: 2021-07-13-09-01-33 +.. nonce: R3IcM1 +.. section: Library + +Fix memory leak in :func:`_tkinter._flatten` if it is called with a sequence +or set, but not list or tuple. + +.. + +.. bpo: 44559 +.. date: 2021-07-12-10-43-31 +.. nonce: YunVKY +.. section: Library + +[Enum] module reverted to 3.9; 3.10 changes pushed until 3.11 + +.. + +.. bpo: 41928 +.. date: 2021-07-09-07-14-37 +.. nonce: Q1jMrr +.. section: Library + +Update :func:`shutil.copyfile` to raise :exc:`FileNotFoundError` instead of +confusing :exc:`IsADirectoryError` when a path ending with a +:const:`os.path.sep` does not exist; :func:`shutil.copy` and +:func:`shutil.copy2` are also affected. + +.. + +.. bpo: 44566 +.. date: 2021-07-05-18-13-25 +.. nonce: o51Bd1 +.. section: Library + +handle StopIteration subclass raised from @contextlib.contextmanager +generator + +.. + +.. bpo: 41249 +.. date: 2021-07-04-11-33-34 +.. nonce: sHdwBE +.. section: Library + +Fixes ``TypedDict`` to work with ``typing.get_type_hints()`` and postponed +evaluation of annotations across modules. + +.. + +.. bpo: 44461 +.. date: 2021-06-29-21-17-17 +.. nonce: acqRnV +.. section: Library + +Fix bug with :mod:`pdb`'s handling of import error due to a package which +does not have a ``__main__`` module + +.. + +.. bpo: 43625 +.. date: 2021-06-29-07-27-08 +.. nonce: ZlAxhp +.. section: Library + +Fix a bug in the detection of CSV file headers by +:meth:`csv.Sniffer.has_header` and improve documentation of same. + +.. + +.. bpo: 42892 +.. date: 2021-06-24-19-16-20 +.. nonce: qvRNhI +.. section: Library + +Fixed an exception thrown while parsing a malformed multipart email by +:class:`email.message.EmailMessage`. + +.. + +.. bpo: 27827 +.. date: 2021-06-12-21-25-35 +.. nonce: TMWh1i +.. section: Library + +:meth:`pathlib.PureWindowsPath.is_reserved` now identifies a greater range +of reserved filenames, including those with trailing spaces or colons. + +.. + +.. bpo: 38741 +.. date: 2019-11-12-18-59-33 +.. nonce: W7IYkq +.. section: Library + +:mod:`configparser`: using ']' inside a section header will no longer cut +the section name short at the ']' + +.. + +.. bpo: 27513 +.. date: 2019-06-03-23-53-25 +.. nonce: qITN7d +.. section: Library + +:func:`email.utils.getaddresses` now accepts :class:`email.header.Header` +objects along with string values. Patch by Zackery Spytz. + +.. + +.. bpo: 29298 +.. date: 2017-09-20-14-43-03 +.. nonce: _78CSN +.. section: Library + +Fix ``TypeError`` when required subparsers without ``dest`` do not receive +arguments. Patch by Anthony Sottile. + +.. + +.. bpo: 44740 +.. date: 2021-07-26-23-48-31 +.. nonce: zMFGMV +.. section: Documentation + +Replaced occurences of uppercase "Web" and "Internet" with lowercase +versions per the 2016 revised Associated Press Style Book. + +.. + +.. bpo: 44693 +.. date: 2021-07-25-23-04-15 +.. nonce: JuCbNq +.. section: Documentation + +Update the definition of __future__ in the glossary by replacing the +confusing word "pseudo-module" with a more accurate description. + +.. + +.. bpo: 35183 +.. date: 2021-07-22-08-28-03 +.. nonce: p9BWTB +.. section: Documentation + +Add typical examples to os.path.splitext docs + +.. + +.. bpo: 30511 +.. date: 2021-07-20-21-03-18 +.. nonce: eMFkRi +.. section: Documentation + +Clarify that :func:`shutil.make_archive` is not thread-safe due to reliance +on changing the current working directory. + +.. + +.. bpo: 44561 +.. date: 2021-07-18-22-43-14 +.. nonce: T7HpWm +.. section: Documentation + +Update of three expired hyperlinks in Doc/distributing/index.rst: "Project +structure", "Building and packaging the project", and "Uploading the project +to the Python Packaging Index". + +.. + +.. bpo: 44613 +.. date: 2021-07-12-11-39-20 +.. nonce: DIXNzc +.. section: Documentation + +importlib.metadata is no longer provisional. + +.. + +.. bpo: 44544 +.. date: 2021-07-02-14-02-29 +.. nonce: _5_aCz +.. section: Documentation + +List all kwargs for :func:`textwrap.wrap`, :func:`textwrap.fill`, and +:func:`textwrap.shorten`. Now, there are nav links to attributes of +:class:`TextWrap`, which makes navigation much easier while minimizing +duplication in the documentation. + +.. + +.. bpo: 44453 +.. date: 2021-06-18-06-44-45 +.. nonce: 3PIkj2 +.. section: Documentation + +Fix documentation for the return type of :func:`sysconfig.get_path`. + +.. + +.. bpo: 44734 +.. date: 2021-07-24-20-09-15 +.. nonce: KKsNOV +.. section: Tests + +Fixed floating point precision issue in turtle tests. + +.. + +.. bpo: 44708 +.. date: 2021-07-22-16-38-39 +.. nonce: SYNaac +.. section: Tests + +Regression tests, when run with -w, are now re-running only the affected +test methods instead of re-running the entire test file. + +.. + +.. bpo: 44647 +.. date: 2021-07-16-14-02-33 +.. nonce: 5LzqIy +.. section: Tests + +Added a permanent Unicode-valued environment variable to regression tests to +ensure they handle this use case in the future. If your test environment +breaks because of that, report a bug to us, and temporarily set +PYTHONREGRTEST_UNICODE_GUARD=0 in your test environment. + +.. + +.. bpo: 44515 +.. date: 2021-06-26-18-37-36 +.. nonce: e9fO6f +.. section: Tests + +Adjust recently added contextlib tests to avoid assuming the use of a +refcounted GC + +.. + +.. bpo: 44572 +.. date: 2021-07-13-15-32-49 +.. nonce: gXvhDc +.. section: Windows + +Avoid consuming standard input in the :mod:`platform` module + +.. + +.. bpo: 40263 +.. date: 2020-04-13-15-20-28 +.. nonce: 1KKEbu +.. section: Windows + +This is a follow-on bug from https://bugs.python.org/issue26903. Once that +is applied we run into an off-by-one assertion problem. The assert was not +correct. + +.. + +.. bpo: 41972 +.. date: 2021-07-12-15-42-02 +.. nonce: yUjE8j +.. section: macOS + +The framework build's user header path in sysconfig is changed to add a +'pythonX.Y' component to match distutils's behavior. + +.. + +.. bpo: 34932 +.. date: 2021-03-29-21-11-23 +.. nonce: f3Hdyd +.. section: macOS + +Add socket.TCP_KEEPALIVE support for macOS. Patch by Shane Harvey. + +.. + +.. bpo: 44756 +.. date: 2021-07-28-00-51-55 +.. nonce: pvAajB +.. section: Tools/Demos + +In the Makefile for documentation (:file:`Doc/Makefile`), the ``build`` rule +is dependent on the ``venv`` rule. Therefore, ``html``, ``latex``, and other +build-dependent rules are also now dependent on ``venv``. The ``venv`` rule +only performs an action if ``$(VENVDIR)`` does not exist. +:file:`Doc/README.rst` was updated; most users now only need to type ``make +html``. + +.. + +.. bpo: 41103 +.. date: 2021-07-29-16-04-28 +.. nonce: hiKKcF +.. section: C API + +Reverts removal of the old buffer protocol because they are part of stable +ABI. + +.. + +.. bpo: 42747 +.. date: 2021-07-20-16-21-06 +.. nonce: rRxjUY +.. section: C API + +The ``Py_TPFLAGS_HAVE_VERSION_TAG`` type flag now does nothing. The +``Py_TPFLAGS_HAVE_AM_SEND`` flag (which was added in 3.10) is removed. Both +were unnecessary because it is not possible to have type objects with the +relevant fields missing. diff --git a/Misc/NEWS.d/3.10.0rc2.rst b/Misc/NEWS.d/3.10.0rc2.rst new file mode 100644 index 00000000000000..92e2e7b3b5108d --- /dev/null +++ b/Misc/NEWS.d/3.10.0rc2.rst @@ -0,0 +1,685 @@ +.. bpo: 42278 +.. date: 2021-08-29-12-39-44 +.. nonce: jvmQz_ +.. release date: 2021-09-07 +.. section: Security + +Replaced usage of :func:`tempfile.mktemp` with +:class:`~tempfile.TemporaryDirectory` to avoid a potential race condition. + +.. + +.. bpo: 44394 +.. date: 2021-06-29-02-45-53 +.. nonce: A220N1 +.. section: Security + +Update the vendored copy of libexpat to 2.4.1 (from 2.2.8) to get the fix +for the CVE-2013-0340 "Billion Laughs" vulnerability. This copy is most used +on Windows and macOS. + +.. + +.. bpo: 43124 +.. date: 2021-05-08-11-50-46 +.. nonce: 2CTM6M +.. section: Security + +Made the internal ``putcmd`` function in :mod:`smtplib` sanitize input for +presence of ``\r`` and ``\n`` characters to avoid (unlikely) command +injection. + +.. + +.. bpo: 45123 +.. date: 2021-09-06-21-52-45 +.. nonce: 8Eh9iI +.. section: Core and Builtins + +Fix PyAiter_Check to only check for the __anext__ presence (not for +__aiter__). Rename PyAiter_Check to PyAIter_Check, PyObject_GetAiter -> +PyObject_GetAIter. + +.. + +.. bpo: 45018 +.. date: 2021-08-26-18-44-03 +.. nonce: pu8H9L +.. section: Core and Builtins + +Fixed pickling of range iterators that iterated for over 2**32 times. + +.. + +.. bpo: 45000 +.. date: 2021-08-25-23-17-32 +.. nonce: XjmyLl +.. section: Core and Builtins + +A :exc:`SyntaxError` is now raised when trying to delete :const:`__debug__`. +Patch by Dong-hee Na. + +.. + +.. bpo: 44963 +.. date: 2021-08-25-23-07-10 +.. nonce: 5EET8y +.. section: Core and Builtins + +Implement ``send()`` and ``throw()`` methods for ``anext_awaitable`` +objects. Patch by Pablo Galindo. + +.. + +.. bpo: 44962 +.. date: 2021-08-23-19-55-08 +.. nonce: J00ftt +.. section: Core and Builtins + +Fix a race in WeakKeyDictionary, WeakValueDictionary and WeakSet when two +threads attempt to commit the last pending removal. This fixes +asyncio.create_task and fixes a data loss in asyncio.run where +shutdown_asyncgens is not run + +.. + +.. bpo: 44954 +.. date: 2021-08-19-14-43-24 +.. nonce: dLn3lg +.. section: Core and Builtins + +Fixed a corner case bug where the result of ``float.fromhex('0x.8p-1074')`` +was rounded the wrong way. + +.. + +.. bpo: 44947 +.. date: 2021-08-18-19-09-28 +.. nonce: mcvGdS +.. section: Core and Builtins + +Refine the syntax error for trailing commas in import statements. Patch by +Pablo Galindo. + +.. + +.. bpo: 44698 +.. date: 2021-08-15-10-39-06 +.. nonce: lITKNc +.. section: Core and Builtins + +Restore behaviour of complex exponentiation with integer-valued exponent of +type :class:`float` or :class:`complex`. + +.. + +.. bpo: 44885 +.. date: 2021-08-11-15-39-57 +.. nonce: i4noUO +.. section: Core and Builtins + +Correct the ast locations of f-strings with format specs and repeated +expressions. Patch by Pablo Galindo + +.. + +.. bpo: 44872 +.. date: 2021-08-09-16-16-03 +.. nonce: OKRlhK +.. section: Core and Builtins + +Use new trashcan macros (Py_TRASHCAN_BEGIN/END) in frameobject.c instead of +the old ones (Py_TRASHCAN_SAFE_BEGIN/END). + +.. + +.. bpo: 33930 +.. date: 2021-08-09-14-29-52 +.. nonce: --5LQ- +.. section: Core and Builtins + +Fix segmentation fault with deep recursion when cleaning method objects. +Patch by Augusto Goulart and Pablo Galindo. + +.. + +.. bpo: 25782 +.. date: 2021-08-07-21-39-19 +.. nonce: B22lMx +.. section: Core and Builtins + +Fix bug where ``PyErr_SetObject`` hangs when the current exception has a +cycle in its context chain. + +.. + +.. bpo: 44856 +.. date: 2021-08-07-01-26-12 +.. nonce: 9rk3li +.. section: Core and Builtins + +Fix reference leaks in the error paths of ``update_bases()`` and +``__build_class__``. Patch by Pablo Galindo. + +.. + +.. bpo: 44838 +.. date: 2021-08-05-17-42-03 +.. nonce: r_Lkj_ +.. section: Core and Builtins + +Fixed a bug that was causing the parser to raise an incorrect custom +:exc:`SyntaxError` for invalid 'if' expressions. Patch by Pablo Galindo. + +.. + +.. bpo: 44584 +.. date: 2021-07-08-12-18-56 +.. nonce: qKnSqV +.. section: Core and Builtins + +The threading debug (:envvar:`PYTHONTHREADDEBUG` environment variable) is +deprecated in Python 3.10 and will be removed in Python 3.12. This feature +requires a debug build of Python. Patch by Victor Stinner. + +.. + +.. bpo: 39091 +.. date: 2019-12-21-14-18-32 +.. nonce: dOexgQ +.. section: Core and Builtins + +Fix crash when using passing a non-exception to a generator's ``throw()`` +method. Patch by Noah Oxer + +.. + +.. bpo: 45081 +.. date: 2021-09-02-12-42-25 +.. nonce: tOjJ1k +.. section: Library + +Fix issue when dataclasses that inherit from ``typing.Protocol`` subclasses +have wrong ``__init__``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 41620 +.. date: 2021-08-29-14-49-22 +.. nonce: WJ6PFL +.. section: Library + +:meth:`~unittest.TestCase.run` now always return a +:class:`~unittest.TestResult` instance. Previously it returned ``None`` if +the test class or method was decorated with a skipping decorator. + +.. + +.. bpo: 43913 +.. date: 2021-08-27-23-40-51 +.. nonce: Uo1Gt5 +.. section: Library + +Fix bugs in cleaning up classes and modules in :mod:`unittest`: + +* Functions registered with :func:`~unittest.addModuleCleanup` were not called unless the user defines ``tearDownModule()`` in their test module. +* Functions registered with :meth:`~unittest.TestCase.addClassCleanup` were not called if ``tearDownClass`` is set to ``None``. +* Buffering in :class:`~unittest.TestResult` did not work with functions registered with ``addClassCleanup()`` and ``addModuleCleanup()``. +* Errors in functions registered with ``addClassCleanup()`` and ``addModuleCleanup()`` were not handled correctly in buffered and debug modes. +* Errors in ``setUpModule()`` and functions registered with ``addModuleCleanup()`` were reported in wrong order. +* And several lesser bugs. + +.. + +.. bpo: 45030 +.. date: 2021-08-27-19-01-23 +.. nonce: tAmBbY +.. section: Library + +Fix integer overflow in pickling and copying the range iterator. + +.. + +.. bpo: 45001 +.. date: 2021-08-26-16-25-48 +.. nonce: tn_dKp +.. section: Library + +Made email date parsing more robust against malformed input, namely a +whitespace-only ``Date:`` header. Patch by Wouter Bolsterlee. + +.. + +.. bpo: 44449 +.. date: 2021-08-20-11-30-52 +.. nonce: 1r2-lS +.. section: Library + +Fix a crash in the signal handler of the :mod:`faulthandler` module: no +longer modify the reference count of frame objects. Patch by Victor Stinner. + +.. + +.. bpo: 44955 +.. date: 2021-08-19-15-03-54 +.. nonce: 1mxFQS +.. section: Library + +Method :meth:`~unittest.TestResult.stopTestRun` is now always called in pair +with method :meth:`~unittest.TestResult.startTestRun` for +:class:`~unittest.TestResult` objects implicitly created in +:meth:`~unittest.TestCase.run`. Previously it was not called for test +methods and classes decorated with a skipping decorator. + +.. + +.. bpo: 44935 +.. date: 2021-08-17-16-01-44 +.. nonce: roUl0G +.. section: Library + +:mod:`subprocess` on Solaris now also uses :func:`os.posix_spawn()` for +better performance. + +.. + +.. bpo: 44911 +.. date: 2021-08-14-00-55-16 +.. nonce: uk3hYk +.. section: Library + +:class:`~unittest.IsolatedAsyncioTestCase` will no longer throw an exception +while cancelling leaked tasks. Patch by Bar Harel. + +.. + +.. bpo: 44524 +.. date: 2021-08-10-16-57-10 +.. nonce: dk9QX4 +.. section: Library + +Make exception message more useful when subclass from typing special form +alias. Patch provided by Yurii Karabas. + +.. + +.. bpo: 38956 +.. date: 2021-08-09-13-17-10 +.. nonce: owWLNv +.. section: Library + +:class:`argparse.BooleanOptionalAction`'s default value is no longer printed +twice when used with :class:`argparse.ArgumentDefaultsHelpFormatter`. + +.. + +.. bpo: 44860 +.. date: 2021-08-07-22-51-32 +.. nonce: PTvRrU +.. section: Library + +Fix the ``posix_user`` scheme in :mod:`sysconfig` to not depend on +:data:`sys.platlibdir`. + +.. + +.. bpo: 44581 +.. date: 2021-08-06-19-15-52 +.. nonce: oFDBTB +.. section: Library + +Upgrade bundled pip to 21.2.3 and setuptools to 57.4.0 + +.. + +.. bpo: 44849 +.. date: 2021-08-06-13-00-28 +.. nonce: O78F_f +.. section: Library + +Fix the :func:`os.set_inheritable` function on FreeBSD 14 for file +descriptor opened with the :data:`~os.O_PATH` flag: ignore the +:data:`~errno.EBADF` error on ``ioctl()``, fallback on the ``fcntl()`` +implementation. Patch by Victor Stinner. + +.. + +.. bpo: 44605 +.. date: 2021-08-06-09-43-50 +.. nonce: q4YSBZ +.. section: Library + +The @functools.total_ordering() decorator now works with metaclasses. + +.. + +.. bpo: 44524 +.. date: 2021-08-05-18-20-17 +.. nonce: 9T1tfe +.. section: Library + +Fixed an issue wherein the ``__name__`` and ``__qualname__`` attributes of +subscribed specialforms could be ``None``. + +.. + +.. bpo: 44822 +.. date: 2021-08-04-12-29-00 +.. nonce: zePNXA +.. section: Library + +:mod:`sqlite3` user-defined functions and aggregators returning +:class:`strings ` with embedded NUL characters are no longer truncated. +Patch by Erlend E. Aasland. + +.. + +.. bpo: 44801 +.. date: 2021-08-03-20-37-45 +.. nonce: i49Aug +.. section: Library + +Ensure that the :class:`~typing.ParamSpec` variable in Callable can only be +substituted with a parameters expression (a list of types, an ellipsis, +ParamSpec or Concatenate). + +.. + +.. bpo: 27334 +.. date: 2021-05-18-00-17-21 +.. nonce: 32EJZi +.. section: Library + +The :mod:`sqlite3` context manager now performs a rollback (thus releasing +the database lock) if commit failed. Patch by Luca Citi and Erlend E. +Aasland. + +.. + +.. bpo: 41402 +.. date: 2020-07-26-18-17-30 +.. nonce: YRkVkp +.. section: Library + +Fix :meth:`email.message.EmailMessage.set_content` when called with binary +data and ``7bit`` content transfer encoding. + +.. + +.. bpo: 32695 +.. date: 2020-07-13-23-46-59 +.. nonce: tTqqXe +.. section: Library + +The *compresslevel* and *preset* keyword arguments of :func:`tarfile.open` +are now both documented and tested. + +.. + +.. bpo: 34990 +.. date: 2020-04-24-20-39-38 +.. nonce: 3SmL9M +.. section: Library + +Fixed a Y2k38 bug in the compileall module where it would fail to compile +files with a modification time after the year 2038. + +.. + +.. bpo: 38840 +.. date: 2020-01-16-23-41-16 +.. nonce: VzzYZz +.. section: Library + +Fix ``test___all__`` on platforms lacking a shared memory implementation. + +.. + +.. bpo: 26228 +.. date: 2019-02-26-09-31-59 +.. nonce: wyrHKc +.. section: Library + +pty.spawn no longer hangs on FreeBSD, macOS, and Solaris. + +.. + +.. bpo: 33349 +.. date: 2018-04-24-14-25-07 +.. nonce: Y_0LIr +.. section: Library + +lib2to3 now recognizes async generators everywhere. + +.. + +.. bpo: 44957 +.. date: 2021-08-19-15-53-08 +.. nonce: imqrh3 +.. section: Documentation + +Promote PEP 604 union syntax by using it where possible. Also, mention ``X | +Y`` more prominently in section about ``Union`` and mention ``X | None`` at +all in section about ``Optional``. + +.. + +.. bpo: 44903 +.. date: 2021-08-13-19-08-03 +.. nonce: aJuvQF +.. section: Documentation + +Removed the othergui.rst file, any references to it, and the list of GUI +frameworks in the FAQ. In their place I've added links to the Python Wiki +`page on GUI frameworks `. + +.. + +.. bpo: 33479 +.. date: 2021-08-11-18-02-06 +.. nonce: rCe4c5 +.. section: Documentation + +Tkinter documentation has been greatly expanded with new "Architecture" and +"Threading model" sections. + +.. + +.. bpo: 36700 +.. date: 2021-08-09-19-58-45 +.. nonce: WPNW5f +.. section: Documentation + +:mod:`base64` RFC references were updated to point to :rfc:`4648`; a section +was added to point users to the new "security considerations" section of the +RFC. + +.. + +.. bpo: 44756 +.. date: 2021-08-06-19-36-21 +.. nonce: 1Ngzon +.. section: Documentation + +Reverted automated virtual environment creation on ``make html`` when +building documentation. It turned out to be disruptive for downstream +distributors. + +.. + +.. bpo: 42958 +.. date: 2021-07-15-11-19-03 +.. nonce: gC5IHM +.. section: Documentation + +Updated the docstring and docs of :func:`filecmp.cmp` to be more accurate +and less confusing especially in respect to *shallow* arg. + +.. + +.. bpo: 43066 +.. date: 2021-06-24-14-37-16 +.. nonce: Ti7ahX +.. section: Documentation + +Added a warning to :mod:`zipfile` docs: filename arg with a leading slash +may cause archive to be un-openable on Windows systems. + +.. + +.. bpo: 39452 +.. date: 2021-06-23-15-21-36 +.. nonce: o_I-6d +.. section: Documentation + +Rewrote ``Doc/library/__main__.rst``. Broadened scope of the document to +explicitly discuss and differentiate between ``__main__.py`` in packages +versus the ``__name__ == '__main__'`` expression (and the idioms that +surround it). + +.. + +.. bpo: 27752 +.. date: 2021-06-18-18-04-53 +.. nonce: NEByNk +.. section: Documentation + +Documentation of csv.Dialect is more descriptive. + +.. + +.. bpo: 41576 +.. date: 2020-08-21-22-59-37 +.. nonce: 7a6CQR +.. section: Documentation + +document BaseException in favor of bare except + +.. + +.. bpo: 39498 +.. date: 2020-01-30-05-18-48 +.. nonce: Nu3sFL +.. section: Documentation + +Add a "Security Considerations" index which links to standard library +modules that have explicitly documented security considerations. + +.. + +.. bpo: 33479 +.. date: 2018-05-19-15-59-29 +.. nonce: 4cLlxo +.. section: Documentation + +Remove the unqualified claim that tkinter is threadsafe. It has not been +true for several years and likely never was. An explanation of what is true +may be added later, after more discussion, and possibly after patching +_tkinter.c, + +.. + +.. bpo: 45052 +.. date: 2021-09-06-19-00-29 +.. nonce: yrOK3J +.. section: Tests + +``WithProcessesTestSharedMemory.test_shared_memory_basics`` test was +ignored, because ``self.assertEqual(sms.size, sms2.size)`` line was failing. +It is now removed and test is unskipped. + +The main motivation for this line to be removed from the test is that the +``size`` of ``SharedMemory`` is not ever guaranteed to be the same. It is +decided by the platform. + +.. + +.. bpo: 45042 +.. date: 2021-08-30-11-54-14 +.. nonce: QMz3X8 +.. section: Tests + +Fixes that test classes decorated with +``@hashlib_helper.requires_hashdigest`` were skipped all the time. + +.. + +.. bpo: 45011 +.. date: 2021-08-26-14-20-44 +.. nonce: mQZdXU +.. section: Tests + +Made tests relying on the :mod:`_asyncio` C extension module optional to +allow running on alternative Python implementations. Patch by Serhiy +Storchaka. + +.. + +.. bpo: 44949 +.. date: 2021-08-18-18-30-12 +.. nonce: VE5ENv +.. section: Tests + +Fix auto history tests of test_readline: sometimes, the newline character is +not written at the end, so don't expect it in the output. + +.. + +.. bpo: 44891 +.. date: 2021-08-13-12-11-06 +.. nonce: T9_mBT +.. section: Tests + +Tests were added to clarify :func:`id` is preserved when ``obj * 1`` is used +on :class:`str` and :class:`bytes` objects. Patch by Nikita Sobolev. + +.. + +.. bpo: 44852 +.. date: 2021-08-06-18-36-04 +.. nonce: sUL8YX +.. section: Tests + +Add ability to wholesale silence DeprecationWarnings while running the +regression test suite. + +.. + +.. bpo: 40928 +.. date: 2021-08-06-00-07-15 +.. nonce: aIwb6G +.. section: Tests + +Notify users running test_decimal regression tests on macOS of potential +harmless "malloc can't allocate region" messages spewed by test_decimal. + +.. + +.. bpo: 45007 +.. date: 2021-08-27-23-50-02 +.. nonce: NIBlVG +.. section: Windows + +Update to OpenSSL 1.1.1l in Windows build + +.. + +.. bpo: 45007 +.. date: 2021-08-30-00-04-10 +.. nonce: pixqUB +.. section: macOS + +Update macOS installer builds to use OpenSSL 1.1.1l. + +.. + +.. bpo: 44689 +.. date: 2021-07-20-22-27-01 +.. nonce: mmT_xH +.. section: macOS + +:meth:`ctypes.util.find_library` now works correctly on macOS 11 Big Sur +even if Python is built on an older version of macOS. Previously, when +built on older macOS systems, ``find_library`` was not able to find macOS +system libraries when running on Big Sur due to changes in how system +libraries are stored. diff --git a/Misc/NEWS.d/3.10.1.rst b/Misc/NEWS.d/3.10.1.rst new file mode 100644 index 00000000000000..0f8938ab6154d8 --- /dev/null +++ b/Misc/NEWS.d/3.10.1.rst @@ -0,0 +1,1530 @@ +.. bpo: 42268 +.. date: 2021-11-26-22-31-22 +.. nonce: 3wl-09 +.. release date: 2021-12-06 +.. section: Core and Builtins + +Fail the configure step if the selected compiler doesn't support memory +sanitizer. Patch by Pablo Galindo + +.. + +.. bpo: 45727 +.. date: 2021-11-24-18-24-49 +.. nonce: _xVbbo +.. section: Core and Builtins + +Refine the custom syntax error that suggests that a comma may be missing to +trigger only when the expressions are detected between parentheses or +brackets. Patch by Pablo Galindo + +.. + +.. bpo: 45614 +.. date: 2021-11-23-12-06-41 +.. nonce: fIekgI +.. section: Core and Builtins + +Fix :mod:`traceback` display for exceptions with invalid module name. + +.. + +.. bpo: 45848 +.. date: 2021-11-19-22-57-42 +.. nonce: HgVBJ5 +.. section: Core and Builtins + +Allow the parser to obtain error lines directly from encoded files. Patch by +Pablo Galindo + +.. + +.. bpo: 45826 +.. date: 2021-11-17-08-05-27 +.. nonce: OERoTm +.. section: Core and Builtins + +Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This +occurs internally in ``unittest.TestCase.assertRaises()``. + +.. + +.. bpo: 45822 +.. date: 2021-11-16-19-41-04 +.. nonce: OT6ueS +.. section: Core and Builtins + +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo + +.. + +.. bpo: 45820 +.. date: 2021-11-16-19-00-27 +.. nonce: 2X6Psr +.. section: Core and Builtins + +Fix a segfault when the parser fails without reading any input. Patch by +Pablo Galindo + +.. + +.. bpo: 42540 +.. date: 2021-11-15-12-08-27 +.. nonce: V2w107 +.. section: Core and Builtins + +Fix crash when :func:`os.fork` is called with an active non-default memory +allocator. + +.. + +.. bpo: 45738 +.. date: 2021-11-14-00-14-45 +.. nonce: e0cgKd +.. section: Core and Builtins + +Fix computation of error location for invalid continuation characters in the +parser. Patch by Pablo Galindo. + +.. + +.. bpo: 45773 +.. date: 2021-11-09-13-01-35 +.. nonce: POU8A4 +.. section: Core and Builtins + +Fix a compiler hang when attempting to optimize certain jump patterns. + +.. + +.. bpo: 45716 +.. date: 2021-11-04-20-19-07 +.. nonce: 5C0pA1 +.. section: Core and Builtins + +Improve the :exc:`SyntaxError` message when using ``True``, ``None`` or +``False`` as keywords in a function call. Patch by Pablo Galindo. + +.. + +.. bpo: 45688 +.. date: 2021-11-02-09-27-46 +.. nonce: v5Der1 +.. section: Core and Builtins + +:data:`sys.stdlib_module_names` now contains the macOS-specific module +:mod:`_scproxy`. + +.. + +.. bpo: 30570 +.. date: 2021-10-19-01-04-08 +.. nonce: _G30Ms +.. section: Core and Builtins + +Fixed a crash in ``issubclass()`` from infinite recursion when searching +pathological ``__bases__`` tuples. + +.. + +.. bpo: 45521 +.. date: 2021-10-18-22-40-33 +.. nonce: GdMiuW +.. section: Core and Builtins + +Fix a bug in the obmalloc radix tree code. On 64-bit machines, the bug +causes the tree to hold 46-bits of virtual addresses, rather than the +intended 48-bits. + +.. + +.. bpo: 45494 +.. date: 2021-10-16-17-27-48 +.. nonce: vMt1g4 +.. section: Core and Builtins + +Fix parser crash when reporting errors involving invalid continuation +characters. Patch by Pablo Galindo. + +.. + +.. bpo: 45408 +.. date: 2021-10-07-21-26-44 +.. nonce: qUqzcd +.. section: Core and Builtins + +Fix a crash in the parser when reporting tokenizer errors that occur at the +same time unclosed parentheses are detected. Patch by Pablo Galindo. + +.. + +.. bpo: 45385 +.. date: 2021-10-06-21-20-11 +.. nonce: CTUT8s +.. section: Core and Builtins + +Fix reference leak from descr_check. Patch by Dong-hee Na. + +.. + +.. bpo: 45167 +.. date: 2021-09-14-09-23-59 +.. nonce: CPSSoV +.. section: Core and Builtins + +Fix deepcopying of :class:`types.GenericAlias` objects. + +.. + +.. bpo: 44219 +.. date: 2021-09-09-10-32-33 +.. nonce: WiYyjz +.. section: Core and Builtins + +Release the GIL while performing ``isatty`` system calls on arbitrary file +descriptors. In particular, this affects :func:`os.isatty`, +:func:`os.device_encoding` and :class:`io.TextIOWrapper`. By extension, +:func:`io.open` in text mode is also affected. This change solves a deadlock +in :func:`os.isatty`. Patch by Vincent Michel in :issue:`44219`. + +.. + +.. bpo: 44959 +.. date: 2021-09-08-08-29-41 +.. nonce: OSwwPf +.. section: Core and Builtins + +Added fallback to extension modules with '.sl' suffix on HP-UX + +.. + +.. bpo: 44050 +.. date: 2021-09-08-00-30-09 +.. nonce: mFI15u +.. section: Core and Builtins + +Extensions that indicate they use global state (by setting ``m_size`` to -1) +can again be used in multiple interpreters. This reverts to behavior of +Python 3.8. + +.. + +.. bpo: 45121 +.. date: 2021-09-07-17-10-16 +.. nonce: iG-Hsf +.. section: Core and Builtins + +Fix issue where ``Protocol.__init__`` raises ``RecursionError`` when it's +called directly or via ``super()``. Patch provided by Yurii Karabas. + +.. + +.. bpo: 45083 +.. date: 2021-09-01-23-55-49 +.. nonce: cLi9G3 +.. section: Core and Builtins + +When the interpreter renders an exception, its name now has a complete +qualname. Previously only the class name was concatenated to the module +name, which sometimes resulted in an incorrect full name being displayed. + +(This issue impacted only the C code exception rendering, the +:mod:`traceback` module was using qualname already). + +.. + +.. bpo: 45056 +.. date: 2021-09-01-16-55-43 +.. nonce: 7AK2d9 +.. section: Core and Builtins + +Compiler now removes trailing unused constants from co_consts. + +.. + +.. bpo: 27946 +.. date: 2021-12-04-20-08-42 +.. nonce: -Vuarf +.. section: Library + +Fix possible crash when getting an attribute of +class:`xml.etree.ElementTree.Element` simultaneously with replacing the +``attrib`` dict. + +.. + +.. bpo: 37658 +.. date: 2021-11-28-15-30-34 +.. nonce: 8Hno7d +.. section: Library + +Fix issue when on certain conditions ``asyncio.wait_for()`` may allow a +coroutine to complete successfully, but fail to return the result, +potentially causing memory leaks or other issues. + +.. + +.. bpo: 44649 +.. date: 2021-11-21-20-50-42 +.. nonce: E8M936 +.. section: Library + +Handle dataclass(slots=True) with a field that has default a default value, +but for which init=False. + +.. + +.. bpo: 45803 +.. date: 2021-11-20-17-04-25 +.. nonce: wSgFOy +.. section: Library + +Added missing kw_only parameter to dataclasses.make_dataclass(). + +.. + +.. bpo: 45831 +.. date: 2021-11-17-19-25-37 +.. nonce: 9-TojK +.. section: Library + +:mod:`faulthandler` can now write ASCII-only strings (like filenames and +function names) with a single write() syscall when dumping a traceback. It +reduces the risk of getting an unreadable dump when two threads or two +processes dump a traceback to the same file (like stderr) at the same time. +Patch by Victor Stinner. + +.. + +.. bpo: 41735 +.. date: 2021-11-16-18-13-49 +.. nonce: D72UY1 +.. section: Library + +Fix thread lock in ``zlib.Decompress.flush()`` method before +``PyObject_GetBuffer``. + +.. + +.. bpo: 45235 +.. date: 2021-11-11-13-03-17 +.. nonce: 8ZbkHa +.. section: Library + +Reverted an argparse bugfix that caused regression in the handling of +default arguments for subparsers. This prevented leaf level arguments from +taking precedence over root level arguments. + +.. + +.. bpo: 45765 +.. date: 2021-11-09-09-04-19 +.. nonce: JVobxK +.. section: Library + +In importlib.metadata, fix distribution discovery for an empty path. + +.. + +.. bpo: 45757 +.. date: 2021-11-08-23-22-14 +.. nonce: MHZHt3 +.. section: Library + +Fix bug where :mod:`dis` produced an incorrect oparg when +:opcode:`EXTENDED_ARG` is followed by an opcode that does not use its +argument. + +.. + +.. bpo: 45644 +.. date: 2021-11-06-17-47-46 +.. nonce: ZMqHD_ +.. section: Library + +In-place JSON file formatting using ``python3 -m json.tool infile infile`` +now works correctly, previously it left the file empty. Patch by Chris +Wesseling. + +.. + +.. bpo: 45679 +.. date: 2021-10-30-21-11-37 +.. nonce: Dq8Cpu +.. section: Library + +Fix caching of multi-value :data:`typing.Literal`. ``Literal[True, 2]`` is +no longer equal to ``Literal[1, 2]``. + +.. + +.. bpo: 45664 +.. date: 2021-10-28-23-40-54 +.. nonce: 7dqtxQ +.. section: Library + +Fix :func:`types.resolve_bases` and :func:`types.new_class` for +:class:`types.GenericAlias` instance as a base. + +.. + +.. bpo: 45663 +.. date: 2021-10-28-23-11-59 +.. nonce: J90N5R +.. section: Library + +Fix :func:`dataclasses.is_dataclass` for dataclasses which are subclasses of +:class:`types.GenericAlias`. + +.. + +.. bpo: 45662 +.. date: 2021-10-28-22-58-14 +.. nonce: sJd7Ir +.. section: Library + +Fix the repr of :data:`dataclasses.InitVar` with a type alias to the +built-in class, e.g. ``InitVar[list[int]]``. + +.. + +.. bpo: 45438 +.. date: 2021-10-27-10-05-39 +.. nonce: Xz5lGU +.. section: Library + +Fix typing.Signature string representation for generic builtin types. + +.. + +.. bpo: 45574 +.. date: 2021-10-22-23-06-33 +.. nonce: svqA84 +.. section: Library + +Fix warning about ``print_escape`` being unused. + +.. + +.. bpo: 45581 +.. date: 2021-10-22-21-57-02 +.. nonce: rlH6ay +.. section: Library + +:meth:`sqlite3.connect` now correctly raises :exc:`MemoryError` if the +underlying SQLite API signals memory error. Patch by Erlend E. Aasland. + +.. + +.. bpo: 45557 +.. date: 2021-10-21-16-18-51 +.. nonce: 4MQt4r +.. section: Library + +pprint.pprint() now handles underscore_numbers correctly. Previously it was +always setting it to False. + +.. + +.. bpo: 45515 +.. date: 2021-10-18-14-52-48 +.. nonce: aXdvm_ +.. section: Library + +Add references to :mod:`zoneinfo` in the :mod:`datetime` documentation, +mostly replacing outdated references to ``dateutil.tz``. Change by Paul +Ganssle. + +.. + +.. bpo: 45475 +.. date: 2021-10-18-10-46-47 +.. nonce: sb9KDF +.. section: Library + +Reverted optimization of iterating :class:`gzip.GzipFile`, +:class:`bz2.BZ2File`, and :class:`lzma.LZMAFile` (see bpo-43787) because it +caused regression when user iterate them without having reference of them. +Patch by Inada Naoki. + +.. + +.. bpo: 45428 +.. date: 2021-10-14-18-04-17 +.. nonce: mM2War +.. section: Library + +Fix a regression in py_compile when reading filenames from standard input. + +.. + +.. bpo: 45467 +.. date: 2021-10-14-13-31-19 +.. nonce: Q7Ma6A +.. section: Library + +Fix incremental decoder and stream reader in the "raw-unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45461 +.. date: 2021-10-14-00-19-02 +.. nonce: 4LB_tJ +.. section: Library + +Fix incremental decoder and stream reader in the "unicode-escape" codec. +Previously they failed if the escape sequence was split. + +.. + +.. bpo: 45239 +.. date: 2021-10-13-17-52-48 +.. nonce: 7li1_0 +.. section: Library + +Fixed :func:`email.utils.parsedate_tz` crashing with +:exc:`UnboundLocalError` on certain invalid input instead of returning +``None``. Patch by Ben Hoyt. + +.. + +.. bpo: 45249 +.. date: 2021-10-10-16-14-33 +.. nonce: xqLliz +.. section: Library + +Fix the behaviour of :func:`traceback.print_exc` when displaying the caret +when the ``end_offset`` in the exception is set to 0. Patch by Pablo Galindo + +.. + +.. bpo: 45416 +.. date: 2021-10-10-09-42-34 +.. nonce: n35O0_ +.. section: Library + +Fix use of :class:`asyncio.Condition` with explicit :class:`asyncio.Lock` +objects, which was a regression due to removal of explicit loop arguments. +Patch by Joongi Kim. + +.. + +.. bpo: 45419 +.. date: 2021-10-09-20-53-13 +.. nonce: CauCgt +.. section: Library + +Correct interfaces on DegenerateFiles.Path. + +.. + +.. bpo: 44904 +.. date: 2021-10-09-18-42-27 +.. nonce: RlW5h8 +.. section: Library + +Fix bug in the :mod:`doctest` module that caused it to fail if a docstring +included an example with a ``classmethod`` ``property``. Patch by Alex +Waygood. + +.. + +.. bpo: 45406 +.. date: 2021-10-08-19-24-48 +.. nonce: Qh_Mz4 +.. section: Library + +Make :func:`inspect.getmodule` catch ``FileNotFoundError`` raised by +:'func:`inspect.getabsfile`, and return ``None`` to indicate that the module +could not be determined. + +.. + +.. bpo: 45262 +.. date: 2021-10-07-14-04-10 +.. nonce: HqF71Z +.. section: Library + +Prevent use-after-free in asyncio. Make sure the cached running loop holder +gets cleared on dealloc to prevent use-after-free in get_running_loop + +.. + +.. bpo: 45386 +.. date: 2021-10-07-00-05-05 +.. nonce: q9ORpA +.. section: Library + +Make :mod:`xmlrpc.client` more robust to C runtimes where the underlying C +``strftime`` function results in a ``ValueError`` when testing for year +formatting options. + +.. + +.. bpo: 45371 +.. date: 2021-10-05-11-03-48 +.. nonce: NOwcDJ +.. section: Library + +Fix clang rpath issue in :mod:`distutils`. The UnixCCompiler now uses +correct clang option to add a runtime library directory (rpath) to a shared +library. + +.. + +.. bpo: 20028 +.. date: 2021-10-03-21-14-37 +.. nonce: zBA4RK +.. section: Library + +Improve error message of :class:`csv.Dialect` when initializing. Patch by +Vajrasky Kok and Dong-hee Na. + +.. + +.. bpo: 45343 +.. date: 2021-10-01-23-07-02 +.. nonce: ixmctD +.. section: Library + +Update bundled pip to 21.2.4 and setuptools to 58.1.0 + +.. + +.. bpo: 45329 +.. date: 2021-10-01-13-09-53 +.. nonce: 9iMYaO +.. section: Library + +Fix freed memory access in :class:`pyexpat.xmlparser` when building it with +an installed expat library <= 2.2.0. + +.. + +.. bpo: 41710 +.. date: 2021-09-30-23-00-18 +.. nonce: svuloZ +.. section: Library + +On Unix, if the ``sem_clockwait()`` function is available in the C library +(glibc 2.30 and newer), the :meth:`threading.Lock.acquire` method now uses +the monotonic clock (:data:`time.CLOCK_MONOTONIC`) for the timeout, rather +than using the system clock (:data:`time.CLOCK_REALTIME`), to not be +affected by system clock changes. Patch by Victor Stinner. + +.. + +.. bpo: 45328 +.. date: 2021-09-30-08-22-44 +.. nonce: 8Z-Q0B +.. section: Library + +Fixed :class:`http.client.HTTPConnection` to work properly in OSs that don't +support the ``TCP_NODELAY`` socket option. + +.. + +.. bpo: 1596321 +.. date: 2021-09-24-17-20-23 +.. nonce: 3nhPUk +.. section: Library + +Fix the :func:`threading._shutdown` function when the :mod:`threading` +module was imported first from a thread different than the main thread: no +longer log an error at Python exit. + +.. + +.. bpo: 45274 +.. date: 2021-09-23-22-17-26 +.. nonce: gPpa4E +.. section: Library + +Fix a race condition in the :meth:`Thread.join() ` +method of the :mod:`threading` module. If the function is interrupted by a +signal and the signal handler raises an exception, make sure that the thread +remains in a consistent state to prevent a deadlock. Patch by Victor +Stinner. + +.. + +.. bpo: 45238 +.. date: 2021-09-18-16-56-33 +.. nonce: Hng_9V +.. section: Library + +Fix :meth:`unittest.IsolatedAsyncioTestCase.debug`: it runs now asynchronous +methods and callbacks. + +.. + +.. bpo: 36674 +.. date: 2021-09-18-13-14-57 +.. nonce: a2k5Zb +.. section: Library + +:meth:`unittest.TestCase.debug` raises now a :class:`unittest.SkipTest` if +the class or the test method are decorated with the skipping decorator. + +.. + +.. bpo: 45235 +.. date: 2021-09-17-16-55-37 +.. nonce: sXnmPA +.. section: Library + +Fix an issue where argparse would not preserve values in a provided +namespace when using a subparser with defaults. + +.. + +.. bpo: 45183 +.. date: 2021-09-17-15-58-53 +.. nonce: Vv_vch +.. section: Library + +Have zipimport.zipimporter.find_spec() not raise an exception when the +underlying zip file has been deleted and the internal cache has been reset +via invalidate_cache(). + +.. + +.. bpo: 45234 +.. date: 2021-09-17-11-20-55 +.. nonce: qUcTVt +.. section: Library + +Fixed a regression in :func:`~shutil.copyfile`, :func:`~shutil.copy`, +:func:`~shutil.copy2` raising :exc:`FileNotFoundError` when source is a +directory, which should raise :exc:`IsADirectoryError` + +.. + +.. bpo: 45228 +.. date: 2021-09-17-09-59-33 +.. nonce: WV1dcT +.. section: Library + +Fix stack buffer overflow in parsing J1939 network address. + +.. + +.. bpo: 45192 +.. date: 2021-09-14-15-52-47 +.. nonce: DjA-BI +.. section: Library + +Fix the ``tempfile._infer_return_type`` function so that the ``dir`` +argument of the :mod:`tempfile` functions accepts an object implementing the +``os.PathLike`` protocol. + +Patch by Kyungmin Lee. + +.. + +.. bpo: 42135 +.. date: 2021-09-13-19-32-58 +.. nonce: 1ZAHqR +.. section: Library + +Fix typo: ``importlib.find_loader`` is really slated for removal in Python +3.12 not 3.10, like the others in GH-25169. + +Patch by Hugo van Kemenade. + +.. + +.. bpo: 45160 +.. date: 2021-09-11-14-47-05 +.. nonce: VzMXbW +.. section: Library + +When tracing a tkinter variable used by a ttk OptionMenu, callbacks are no +longer made twice. + +.. + +.. bpo: 35474 +.. date: 2021-09-11-10-45-12 +.. nonce: tEY3SD +.. section: Library + +Calling :func:`mimetypes.guess_all_extensions` with ``strict=False`` no +longer affects the result of the following call with ``strict=True``. Also, +mutating the returned list no longer affects the global state. + +.. + +.. bpo: 45166 +.. date: 2021-09-10-21-35-53 +.. nonce: UHipXF +.. section: Library + +:func:`typing.get_type_hints` now works with :data:`~typing.Final` wrapped +in :class:`~typing.ForwardRef`. + +.. + +.. bpo: 20499 +.. date: 2021-09-08-01-19-31 +.. nonce: tSxx8Y +.. section: Library + +Improve the speed and accuracy of statistics.pvariance(). + +.. + +.. bpo: 24444 +.. date: 2021-08-30-00-19-23 +.. nonce: Ki4bgz +.. section: Library + +Fixed an error raised in :mod:`argparse` help display when help for an +option is set to 1+ blank spaces or when *choices* arg is an empty +container. + +.. + +.. bpo: 45021 +.. date: 2021-08-28-13-00-12 +.. nonce: rReeaj +.. section: Library + +Fix a potential deadlock at shutdown of forked children when using +:mod:`concurrent.futures` module + +.. + +.. bpo: 39039 +.. date: 2021-08-18-10-36-14 +.. nonce: A63LYh +.. section: Library + +tarfile.open raises :exc:`~tarfile.ReadError` when a zlib error occurs +during file extraction. + +.. + +.. bpo: 44594 +.. date: 2021-07-12-10-32-48 +.. nonce: eEa5zi +.. section: Library + +Fix an edge case of :class:`ExitStack` and :class:`AsyncExitStack` exception +chaining. They will now match ``with`` block behavior when ``__context__`` +is explicitly set to ``None`` when the exception is in flight. + +.. + +.. bpo: 44295 +.. date: 2021-06-02-16-39-42 +.. nonce: erg01m +.. section: Library + +Ensure deprecation warning from :func:`assertDictContainsSubset` points at +calling code - by Anthony Sottile. + +.. + +.. bpo: 43498 +.. date: 2021-04-20-14-14-16 +.. nonce: L_Hq-8 +.. section: Library + +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +when adjusting the process count of :class:`ProcessPoolExecutor`. + +.. + +.. bpo: 45640 +.. date: 2021-11-18-16-44-12 +.. nonce: lSpc2A +.. section: Documentation + +Properly marked-up grammar tokens in the documentation are now clickable and +take you to the definition of a given piece of grammar. Patch by Arthur +Milchior. + +.. + +.. bpo: 45788 +.. date: 2021-11-18-00-07-40 +.. nonce: qibUoB +.. section: Documentation + +Link doc for sys.prefix to sysconfig doc on installation paths. + +.. + +.. bpo: 45772 +.. date: 2021-11-09-13-10-55 +.. nonce: EdrM3t +.. section: Documentation + +``socket.socket`` documentation is corrected to a class from a function. + +.. + +.. bpo: 45392 +.. date: 2021-11-06-10-54-17 +.. nonce: JZnVOz +.. section: Documentation + +Update the docstring of the :class:`type` built-in to remove a redundant +line and to mention keyword arguments for the constructor. + +.. + +.. bpo: 45726 +.. date: 2021-11-05-12-15-24 +.. nonce: GwRr7e +.. section: Documentation + +Improve documentation for :func:`functools.singledispatch` and +:class:`functools.singledispatchmethod`. + +.. + +.. bpo: 45680 +.. date: 2021-11-03-14-51-03 +.. nonce: 9_NTFU +.. section: Documentation + +Amend the docs on ``GenericAlias`` objects to clarify that non-container +classes can also implement ``__class_getitem__``. Patch contributed by Alex +Waygood. + +.. + +.. bpo: 45655 +.. date: 2021-10-28-19-22-55 +.. nonce: aPYGaS +.. section: Documentation + +Add a new "relevant PEPs" section to the top of the documentation for the +``typing`` module. Patch by Alex Waygood. + +.. + +.. bpo: 45604 +.. date: 2021-10-26-10-00-45 +.. nonce: Dm-YhV +.. section: Documentation + +Add ``level`` argument to ``multiprocessing.log_to_stderr`` function docs. + +.. + +.. bpo: 45250 +.. date: 2021-10-22-12-09-18 +.. nonce: Iit5-Y +.. section: Documentation + +Update the documentation to note that CPython does not consistently require +iterators to define ``__iter__``. + +.. + +.. bpo: 45464 +.. date: 2021-10-20-16-26-53 +.. nonce: mOISBs +.. section: Documentation + +Mention in the documentation of :ref:`Built-in Exceptions +` that inheriting from multiple exception types in a +single subclass is not recommended due to possible memory layout +incompatibility. + +.. + +.. bpo: 45449 +.. date: 2021-10-19-01-41-40 +.. nonce: fjHZJc +.. section: Documentation + +Add note about :pep:`585` in :mod:`collections.abc`. + +.. + +.. bpo: 45516 +.. date: 2021-10-18-20-12-18 +.. nonce: EJh4K8 +.. section: Documentation + +Add protocol description to the :class:`importlib.abc.Traversable` +documentation. + +.. + +.. bpo: 20692 +.. date: 2021-10-13-00-42-54 +.. nonce: K5rGtP +.. section: Documentation + +Add Programming FAQ entry explaining that int literal attribute access +requires either a space after or parentheses around the literal. + +.. + +.. bpo: 45216 +.. date: 2021-09-18-13-45-19 +.. nonce: o56nyt +.. section: Documentation + +Remove extra documentation listing methods in ``difflib``. It was rendering +twice in pydoc and was outdated in some places. + +.. + +.. bpo: 45024 +.. date: 2021-09-08-17-20-19 +.. nonce: dkNPNi +.. section: Documentation + +:mod:`collections.abc` documentation has been expanded to explicitly cover +how instance and subclass checks work, with additional doctest examples and +an exhaustive list of ABCs which test membership purely by presence of the +right :term:`special method`\s. Patch by Raymond Hettinger. + +.. + +.. bpo: 25381 +.. date: 2021-06-21-17-51-51 +.. nonce: 7Kn-_H +.. section: Documentation + +In the extending chapter of the extending doc, update a paragraph about the +global variables containing exception information. + +.. + +.. bpo: 43905 +.. date: 2021-05-24-05-00-12 +.. nonce: tBIndE +.. section: Documentation + +Expanded :func:`~dataclasses.astuple` and :func:`~dataclasses.asdict` docs, +warning about deepcopy being applied and providing a workaround. + +.. + +.. bpo: 19460 +.. date: 2021-11-28-15-25-02 +.. nonce: lr0aWs +.. section: Tests + +Add new Test for :class:`email.mime.nonmultipart.MIMENonMultipart`. + +.. + +.. bpo: 45835 +.. date: 2021-11-17-14-28-08 +.. nonce: Mgyhjx +.. section: Tests + +Fix race condition in test_queue tests with multiple "feeder" threads. + +.. + +.. bpo: 45678 +.. date: 2021-11-04-20-03-32 +.. nonce: 1xNMjN +.. section: Tests + +Add tests for scenarios in which :class:`functools.singledispatchmethod` is +stacked on top of a method that has already been wrapped by two other +decorators. Patch by Alex Waygood. + +.. + +.. bpo: 45578 +.. date: 2021-10-30-19-00-25 +.. nonce: bvu6X2 +.. section: Tests + +Add tests for :func:`dis.distb` + +.. + +.. bpo: 45678 +.. date: 2021-10-30-13-12-20 +.. nonce: bKrYeS +.. section: Tests + +Add tests to ensure that ``functools.singledispatchmethod`` correctly wraps +the attributes of the target function. + +.. + +.. bpo: 45577 +.. date: 2021-10-22-19-44-13 +.. nonce: dSaNvK +.. section: Tests + +Add subtests for all ``pickle`` protocols in ``test_zoneinfo``. + +.. + +.. bpo: 45566 +.. date: 2021-10-22-12-05-21 +.. nonce: 2gQ3ZB +.. section: Tests + +Fix ``test_frozen_pickle`` in ``test_dataclasses`` to check all ``pickle`` +versions. + +.. + +.. bpo: 43592 +.. date: 2021-10-21-17-22-26 +.. nonce: kHRsra +.. section: Tests + +:mod:`test.libregrtest` now raises the soft resource limit for the maximum +number of file descriptors when the default is too low for our test suite as +was often the case on macOS. + +.. + +.. bpo: 39679 +.. date: 2021-10-18-16-18-41 +.. nonce: F18qcE +.. section: Tests + +Add more test cases for `@functools.singledispatchmethod` when combined with +`@classmethod` or `@staticmethod`. + +.. + +.. bpo: 45400 +.. date: 2021-10-07-13-11-45 +.. nonce: h3iT7V +.. section: Tests + +Fix test_name_error_suggestions_do_not_trigger_for_too_many_locals() of +test_exceptions if a directory name contains "a1" (like "Python-3.11.0a1"): +use a stricter regular expression. Patch by Victor Stinner. + +.. + +.. bpo: 40173 +.. date: 2021-09-30-16-54-39 +.. nonce: J_slCw +.. section: Tests + +Fix :func:`test.support.import_helper.import_fresh_module`. + +.. + +.. bpo: 45280 +.. date: 2021-09-25-11-05-31 +.. nonce: 3MA6lC +.. section: Tests + +Add a test case for empty :class:`typing.NamedTuple`. + +.. + +.. bpo: 45269 +.. date: 2021-09-24-10-41-49 +.. nonce: 8jKEr8 +.. section: Tests + +Cover case when invalid ``markers`` type is supplied to ``c_make_encoder``. + +.. + +.. bpo: 45128 +.. date: 2021-09-16-17-22-35 +.. nonce: Jz6fl2 +.. section: Tests + +Fix ``test_multiprocessing_fork`` failure due to ``test_logging`` and +``sys.modules`` manipulation. + +.. + +.. bpo: 45209 +.. date: 2021-09-15-23-32-39 +.. nonce: 55ntL5 +.. section: Tests + +Fix ``UserWarning: resource_tracker`` warning in +``_test_multiprocessing._TestSharedMemory.test_shared_memory_cleaned_after_process_termination`` + +.. + +.. bpo: 45195 +.. date: 2021-09-14-13-16-18 +.. nonce: EyQR1G +.. section: Tests + +Fix test_readline.test_nonascii(): sometimes, the newline character is not +written at the end, so don't expect it in the output. Patch by Victor +Stinner. + +.. + +.. bpo: 45156 +.. date: 2021-09-13-00-28-17 +.. nonce: 8oomV3 +.. section: Tests + +Fixes infinite loop on :func:`unittest.mock.seal` of mocks created by +:func:`~unittest.create_autospec`. + +.. + +.. bpo: 45125 +.. date: 2021-09-11-22-08-18 +.. nonce: FVSzs2 +.. section: Tests + +Improves pickling tests and docs of ``SharedMemory`` and ``SharableList`` +objects. + +.. + +.. bpo: 44860 +.. date: 2021-09-08-13-01-37 +.. nonce: qXd0kx +.. section: Tests + +Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: +``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. + +.. + +.. bpo: 25130 +.. date: 2021-08-27-22-37-19 +.. nonce: ig4oJe +.. section: Tests + +Add calls of :func:`gc.collect` in tests to support PyPy. + +.. + +.. bpo: 44035 +.. date: 2021-12-06-09-31-27 +.. nonce: BiO4XC +.. section: Build + +CI now verifies that autoconf files have been regenerated with a current and +unpatched autoconf package. + +.. + +.. bpo: 33393 +.. date: 2021-11-25-20-26-06 +.. nonce: 24YNtM +.. section: Build + +Update ``config.guess`` to 2021-06-03 and ``config.sub`` to 2021-08-14. +``Makefile`` now has an ``update-config`` target to make updating more +convenient. + +.. + +.. bpo: 45866 +.. date: 2021-11-25-13-53-36 +.. nonce: ZH1W8N +.. section: Build + +``make regen-all`` now produces the same output when run from a directory +other than the source tree: when building Python out of the source tree. +pegen now strips directory of the "generated by pygen from " +header Patch by Victor Stinner. + +.. + +.. bpo: 41498 +.. date: 2021-11-25-09-15-04 +.. nonce: qAk5eo +.. section: Build + +Python now compiles on platforms without ``sigset_t``. Several functions in +:mod:`signal` are not available when ``sigset_t`` is missing. + +Based on patch by Roman Yurchak for pyodide. + +.. + +.. bpo: 45881 +.. date: 2021-11-24-17-14-06 +.. nonce: GTXXLk +.. section: Build + +``setup.py`` now uses ``CC`` from environment first to discover multiarch +and cross compile paths. + +.. + +.. bpo: 43158 +.. date: 2021-11-01-12-51-46 +.. nonce: fghS6w +.. section: Build + +``setup.py`` now uses values from configure script to build the ``_uuid`` +extension module. Configure now detects util-linux's ``libuuid``, too. + +.. + +.. bpo: 45571 +.. date: 2021-10-22-15-28-29 +.. nonce: yY8NsJ +.. section: Build + +``Modules/Setup`` now use ``PY_CFLAGS_NODIST`` instead of ``PY_CFLAGS`` to +compile shared modules. + +.. + +.. bpo: 45561 +.. date: 2021-10-21-14-38-30 +.. nonce: PVqhZE +.. section: Build + +Run smelly.py tool from $(srcdir). + +.. + +.. bpo: 45532 +.. date: 2021-10-20-16-07-39 +.. nonce: kyhvis +.. section: Build + +Update :data:`sys.version` to use ``main`` as fallback information. Patch by +Jeong YunWon. + +.. + +.. bpo: 45536 +.. date: 2021-10-20-12-42-39 +.. nonce: oQNYHB +.. section: Build + +The ``configure`` script now checks whether OpenSSL headers and libraries +provide required APIs. Most common APIs are verified. The check detects +outdated or missing OpenSSL. Failures do not stop configure. + +.. + +.. bpo: 45221 +.. date: 2021-10-18-10-25-56 +.. nonce: rnulhf +.. section: Build + +Fixed regression in handling of ``LDFLAGS`` and ``CPPFLAGS`` options where +:meth:`argparse.parse_known_args` could interpret an option as one of the +built-in command line argument, for example ``-h`` for help. + +.. + +.. bpo: 45405 +.. date: 2021-10-11-16-27-38 +.. nonce: iSfdW5 +.. section: Build + +Prevent ``internal configure error`` when running ``configure`` with recent +versions of non-Apple clang. Patch by David Bohman. + +.. + +.. bpo: 45220 +.. date: 2021-09-16-18-00-43 +.. nonce: TgbkvW +.. section: Build + +Avoid building with the Windows 11 SDK previews automatically. This may be +overridden by setting the ``DefaultWindowsSDKVersion`` environment variable +before building. + +.. + +.. bpo: 45067 +.. date: 2021-09-09-16-45-26 +.. nonce: mFmY92 +.. section: Build + +The ncurses function extended_color_content was introduced in 2017 + +(https://invisible-island.net/ncurses/NEWS.html#index-t20170401). The + +ncurses-devel package in CentOS 7 had a older version ncurses resulted in +compilation error. For compiling ncurses with extended color support, we +verify the version of the ncurses library >= 20170401. + +.. + +.. bpo: 45901 +.. date: 2021-11-26-18-17-41 +.. nonce: c5IBqM +.. section: Windows + +When installed through the Microsoft Store and set as the default app for +:file:`*.py` files, command line arguments will now be passed to Python when +invoking a script without explicitly launching Python (that is, ``script.py +args`` rather than ``python script.py args``). + +.. + +.. bpo: 45616 +.. date: 2021-11-23-11-44-42 +.. nonce: K52PLZ +.. section: Windows + +Fix Python Launcher's ability to distinguish between versions 3.1 and 3.10 +when either one is explicitly requested. Previously, 3.1 would be used if +3.10 was requested but not installed, and 3.10 would be used if 3.1 was +requested but 3.10 was installed. + +.. + +.. bpo: 45732 +.. date: 2021-11-08-21-53-11 +.. nonce: idl5kx +.. section: Windows + +Updates bundled Tcl/Tk to 8.6.12. + +.. + +.. bpo: 45720 +.. date: 2021-11-05-01-05-46 +.. nonce: 47Nc5I +.. section: Windows + +Internal reference to :file:`shlwapi.dll` was dropped to help improve +startup time. This DLL will no longer be loaded at the start of every Python +process. + +.. + +.. bpo: 43652 +.. date: 2021-11-04-00-41-50 +.. nonce: RnqV7I +.. section: Windows + +Update Tcl/Tk to 8.6.11, actually this time. The previous update incorrectly +included 8.6.10. + +.. + +.. bpo: 45337 +.. date: 2021-09-30-23-17-27 +.. nonce: qg7U_h +.. section: Windows + +venv now warns when the created environment may need to be accessed at a +different path, due to redirections, links or junctions. It also now +correctly installs or upgrades components when the alternate path is +required. + +.. + +.. bpo: 45732 +.. date: 2021-12-05-23-52-03 +.. nonce: -BWrnh +.. section: macOS + +Update python.org macOS installer to use Tcl/Tk 8.6.12. + +.. + +.. bpo: 44828 +.. date: 2021-10-25-02-02-21 +.. nonce: XBdXlJ +.. section: macOS + +Avoid tkinter file dialog failure on macOS 12 Monterey when using the Tk +8.6.11 provided by python.org macOS installers. Patch by Marc Culler of the +Tk project. + +.. + +.. bpo: 34602 +.. date: 2021-08-27-16-55-10 +.. nonce: ZjHsYJ +.. section: macOS + +When building CPython on macOS with ``./configure +--with-undefined-behavior-sanitizer --with-pydebug``, the stack size is now +quadrupled to allow for the entire test suite to pass. + +.. + +.. bpo: 45495 +.. date: 2021-10-16-17-20-32 +.. nonce: ST8RFt +.. section: IDLE + +Add context keywords 'case' and 'match' to completions list. + +.. + +.. bpo: 45296 +.. date: 2021-09-27-01-21-59 +.. nonce: 9H8rdY +.. section: IDLE + +On Windows, change exit/quit message to suggest Ctrl-D, which works, instead +of , which does not work in IDLE. + +.. + +.. bpo: 45193 +.. date: 2021-09-15-03-20-06 +.. nonce: G61_GV +.. section: IDLE + +Make completion boxes appear on Ubuntu again. + +.. + +.. bpo: 44786 +.. date: 2021-09-14-11-44-26 +.. nonce: DU0LC0 +.. section: Tools/Demos + +Fix a warning in regular expression in the c-analyzer script. + +.. + +.. bpo: 39026 +.. date: 2021-11-09-15-42-11 +.. nonce: sUnYWn +.. section: C API + +Fix Python.h to build C extensions with Xcode: remove a relative include +from ``Include/cpython/pystate.h``. + +.. + +.. bpo: 45307 +.. date: 2021-09-28-12-00-55 +.. nonce: 3ETFfX +.. section: C API + +Restore the private C API function :func:`_PyImport_FindExtensionObject`. It +will be removed in Python 3.11. + +.. + +.. bpo: 44687 +.. date: 2021-09-19-17-18-25 +.. nonce: 3fqDRC +.. section: C API + +:meth:`BufferedReader.peek` no longer raises :exc:`ValueError` when the +entire file has already been buffered. + +.. + +.. bpo: 44751 +.. date: 2021-07-27-17-29-12 +.. nonce: 4qmbDG +.. section: C API + +Remove ``crypt.h`` include from the public ``Python.h`` header. diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index 56d0d33decc0c2..97bdef6c93213f 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -2234,7 +2234,7 @@ Cook. .. section: Library Lax cookie parsing in http.cookies could be a security issue when combined -with non-standard cookie handling in some Web browsers. Reported by Sergey +with non-standard cookie handling in some web browsers. Reported by Sergey Bobrov. .. @@ -2648,7 +2648,7 @@ module. .. nonce: THJSYB .. section: Library -Changed FeedParser feed() to avoid O(N**2) behavior when parsing long line. +Changed FeedParser feed() to avoid O(N\ :sup:`2`) behavior when parsing long line. Original patch by Raymond Hettinger. .. diff --git a/Misc/NEWS.d/3.6.4rc1.rst b/Misc/NEWS.d/3.6.4rc1.rst index 36dfadda0fe1b3..dc9ab7ad56de89 100644 --- a/Misc/NEWS.d/3.6.4rc1.rst +++ b/Misc/NEWS.d/3.6.4rc1.rst @@ -22,7 +22,7 @@ Setting sys.tracebacklimit to 0 or less now suppresses printing tracebacks. Setting sys.tracebacklimit to None now causes using the default limit. Setting sys.tracebacklimit to an integer larger than LONG_MAX now means using the limit LONG_MAX rather than the default limit. -Fixed integer overflows in the case of more than 2**31 traceback items on +Fixed integer overflows in the case of more than ``2**31`` traceback items on Windows. Fixed output errors handling. diff --git a/Misc/NEWS.d/3.7.0a3.rst b/Misc/NEWS.d/3.7.0a3.rst index 8ef7a5118a1f55..067720efa516e0 100644 --- a/Misc/NEWS.d/3.7.0a3.rst +++ b/Misc/NEWS.d/3.7.0a3.rst @@ -100,7 +100,7 @@ Setting sys.tracebacklimit to 0 or less now suppresses printing tracebacks. Setting sys.tracebacklimit to None now causes using the default limit. Setting sys.tracebacklimit to an integer larger than LONG_MAX now means using the limit LONG_MAX rather than the default limit. -Fixed integer overflows in the case of more than 2**31 traceback items on +Fixed integer overflows in the case of more than ``2**31`` traceback items on Windows. Fixed output errors handling. diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 89811c12a7948e..5cd3fa32105c27 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -3355,7 +3355,7 @@ if the ``PATH`` environment variable is not set. On Windows, fix multiprocessing.Connection for very large read: fix _winapi.PeekNamedPipe() and _winapi.ReadFile() for read larger than INT_MAX -(usually 2^31-1). +(usually ``2**31-1``). .. diff --git a/Misc/NEWS.d/3.8.0b1.rst b/Misc/NEWS.d/3.8.0b1.rst index 5400c07795292a..5285770de13186 100644 --- a/Misc/NEWS.d/3.8.0b1.rst +++ b/Misc/NEWS.d/3.8.0b1.rst @@ -568,7 +568,7 @@ Make :func:`asyncio.create_subprocess_exec` accept path-like arguments. .. section: Library Change default *max_workers* of ``ThreadPoolExecutor`` from ``cpu_count() * -5`` to ``min(32, cpu_count() + 4))``. Previous value was unreasonably large +5`` to ``min(32, cpu_count() + 4)``. Previous value was unreasonably large on many cores machines. .. diff --git a/Misc/NEWS.d/3.9.0a1.rst b/Misc/NEWS.d/3.9.0a1.rst index fe9fc58e3979ae..a9b6694c133f19 100644 --- a/Misc/NEWS.d/3.9.0a1.rst +++ b/Misc/NEWS.d/3.9.0a1.rst @@ -213,7 +213,7 @@ objects. Patch by Dong-hee Na and Inada Naoki. .. section: Core and Builtins :class:`bytearray`, :class:`~array.array` and :class:`~mmap.mmap` objects -allow now to export more than 2**31 buffers at a time. +allow now to export more than ``2**31`` buffers at a time. .. @@ -279,7 +279,7 @@ visited by ``tp_traverse()`` are valid. .. nonce: Xgc6F_ .. section: Core and Builtins -Remove unecessary intersection and update set operation in dictview with +Remove unnecessary intersection and update set operation in dictview with empty set. (Contributed by Dong-hee Na in :issue:`38210`.) .. @@ -868,7 +868,7 @@ Fix the :c:func:`PySys_Audit` call in :class:`mmap.mmap`. .. nonce: WJkgKV .. section: Core and Builtins -Remove an unnecssary Py_XINCREF in classobject.c. +Remove an unnecessary Py_XINCREF in classobject.c. .. @@ -1224,7 +1224,7 @@ Anthony Sottile. .. nonce: cyq5nr .. section: Library -Now :func:`~logging.config.fileConfig` correcty sets the .name of handlers +Now :func:`~logging.config.fileConfig` correctly sets the .name of handlers loaded. .. @@ -1637,7 +1637,7 @@ Preserve subclassing in inspect.Signature.from_callable. .. nonce: nHAbuJ .. section: Library -Names of hashing algorithms frome OpenSSL are now normalized to follow +Names of hashing algorithms from OpenSSL are now normalized to follow Python's naming conventions. For example OpenSSL uses sha3-512 instead of sha3_512 or blake2b512 instead of blake2b. @@ -2403,7 +2403,7 @@ Fixed comparisons of :class:`datetime.timedelta` and .. nonce: 7UV5d0 .. section: Library -Syncronize ``importlib.metadata`` with `importlib_metadata 0.19 +Synchronize ``importlib.metadata`` with `importlib_metadata 0.19 `_, improving handling of EGG-INFO files and fixing a crash when entry point names contained colons. @@ -3002,7 +3002,7 @@ on platforms with 16-bit :c:type:`wchar_t` (for example, Windows and AIX). In a subinterpreter, spawning a daemon thread now raises an exception. Daemon threads were never supported in subinterpreters. Previously, the -subinterpreter finalization crashed with a Pyton fatal error if a daemon +subinterpreter finalization crashed with a Python fatal error if a daemon thread was still running. .. @@ -3065,7 +3065,7 @@ internal tasks weak set is changed by another thread during iteration. .. section: Library :class:`_pyio.IOBase` destructor now does nothing if getting the ``closed`` -attribute fails to better mimick :class:`_io.IOBase` finalizer. +attribute fails to better mimic :class:`_io.IOBase` finalizer. .. @@ -4038,7 +4038,7 @@ crypto policies. Use PKCS#8 format with AES256 encryption instead. .. nonce: _x-9uH .. section: Tests -test.support now has a helper function to check for availibility of a hash +test.support now has a helper function to check for availability of a hash digest function. Several tests are refactored avoid MD5 and use SHA256 instead. Other tests are marked to use MD5 and skipped when MD5 is disabled. diff --git a/Misc/NEWS.d/3.9.0a3.rst b/Misc/NEWS.d/3.9.0a3.rst index 6c71d7e839d05f..77ccc7453c2157 100644 --- a/Misc/NEWS.d/3.9.0a3.rst +++ b/Misc/NEWS.d/3.9.0a3.rst @@ -178,7 +178,7 @@ last iteration of asynchronous for loops. Patch by Pablo Galindo. .. nonce: WG9alt .. section: Core and Builtins -Fix incorrent line execution reporting in trace functions when tracing +Fix incorrect line execution reporting in trace functions when tracing exception handlers with name binding. Patch by Pablo Galindo. .. @@ -685,7 +685,7 @@ but not required. Patch by Juergen Gmach. .. section: Library Fixed __subclasshook__ of :class:`os.PathLike` to return a correct result -upon inheritence. Patch by Bar Harel. +upon inheritance. Patch by Bar Harel. .. diff --git a/Misc/NEWS.d/3.9.0a5.rst b/Misc/NEWS.d/3.9.0a5.rst index 355a3fc22350cb..49a118ad7e4308 100644 --- a/Misc/NEWS.d/3.9.0a5.rst +++ b/Misc/NEWS.d/3.9.0a5.rst @@ -175,7 +175,7 @@ convention. Patch by Dong-hee Na. .. nonce: FE9S21 .. section: Core and Builtins -Chaged list overallocation strategy. It no longer overallocates if the new +Changed list overallocation strategy. It no longer overallocates if the new size is closer to overallocated size than to the old size and adds padding. .. diff --git a/Misc/NEWS.d/next/Build/2021-03-30-14-19-39.bpo-43669.lWMUYx.rst b/Misc/NEWS.d/next/Build/2021-03-30-14-19-39.bpo-43669.lWMUYx.rst deleted file mode 100644 index 48c74813daa903..00000000000000 --- a/Misc/NEWS.d/next/Build/2021-03-30-14-19-39.bpo-43669.lWMUYx.rst +++ /dev/null @@ -1 +0,0 @@ -Implement :pep:`644`. Python now requires OpenSSL 1.1.1 or newer. diff --git a/Misc/NEWS.d/next/Build/2021-03-31-19-50-01.bpo-43567.vd0a-p.rst b/Misc/NEWS.d/next/Build/2021-03-31-19-50-01.bpo-43567.vd0a-p.rst deleted file mode 100644 index 062662f6bceaf9..00000000000000 --- a/Misc/NEWS.d/next/Build/2021-03-31-19-50-01.bpo-43567.vd0a-p.rst +++ /dev/null @@ -1 +0,0 @@ -Improved generated code refresh (AST/tokens/opcodes/keywords) on Windows. diff --git a/Misc/NEWS.d/next/Library/2021-04-17-19-31-17.bpo-42333.cgbtZO.rst b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst similarity index 61% rename from Misc/NEWS.d/next/Library/2021-04-17-19-31-17.bpo-42333.cgbtZO.rst rename to Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst index da2df1f614c101..d3e25f77c73366 100644 --- a/Misc/NEWS.d/next/Library/2021-04-17-19-31-17.bpo-42333.cgbtZO.rst +++ b/Misc/NEWS.d/next/Build/2021-12-20-07-10-41.bpo-46106.5qcv3L.rst @@ -1 +1,2 @@ -Port ``_ssl`` extension module to multiphase initialization. +Updated OpenSSL to 1.1.1m in Windows builds, macOS installer builds, and CI. +Patch by Kumar Aditya. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Build/2022-01-05-02-58-10.bpo-46263.xiv8NU.rst b/Misc/NEWS.d/next/Build/2022-01-05-02-58-10.bpo-46263.xiv8NU.rst new file mode 100644 index 00000000000000..3a575ed7f556b8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-01-05-02-58-10.bpo-46263.xiv8NU.rst @@ -0,0 +1 @@ +``configure`` no longer sets ``MULTIARCH`` on FreeBSD platforms. diff --git a/Misc/NEWS.d/next/C API/2021-04-06-20-52-44.bpo-43753.xUsHp1.rst b/Misc/NEWS.d/next/C API/2021-04-06-20-52-44.bpo-43753.xUsHp1.rst deleted file mode 100644 index f0eac4cf8e7374..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-06-20-52-44.bpo-43753.xUsHp1.rst +++ /dev/null @@ -1,6 +0,0 @@ -Add the :c:func:`Py_Is(x, y) ` function to test if the *x* object is the -*y* object, the same as ``x is y`` in Python. Add also the :c:func:`Py_IsNone`, -:c:func:`Py_IsTrue`, :c:func:`Py_IsFalse` functions to test if an object is, -respectively, the ``None`` singleton, the ``True`` singleton or the ``False`` -singleton. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-04-09-18-19-07.bpo-43795.l0yobT.rst b/Misc/NEWS.d/next/C API/2021-04-09-18-19-07.bpo-43795.l0yobT.rst deleted file mode 100644 index 5153c336777187..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-09-18-19-07.bpo-43795.l0yobT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Stable ABI and limited API definitions are generated from a central manifest -(:pep:`652`). diff --git a/Misc/NEWS.d/next/C API/2021-04-16-18-15-56.bpo-43868.twQ7KH.rst b/Misc/NEWS.d/next/C API/2021-04-16-18-15-56.bpo-43868.twQ7KH.rst deleted file mode 100644 index 50888b8b37ab84..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-16-18-15-56.bpo-43868.twQ7KH.rst +++ /dev/null @@ -1,3 +0,0 @@ -:c:func:`PyOS_ReadlineFunctionPointer` is no longer exported by limited C API -headers and by ``python3.dll`` on Windows. Like any function that takes -``FILE*``, it is not part of the stable ABI. diff --git a/Misc/NEWS.d/next/C API/2021-04-20-15-06-29.bpo-43795.y0IP4c.rst b/Misc/NEWS.d/next/C API/2021-04-20-15-06-29.bpo-43795.y0IP4c.rst deleted file mode 100644 index 1dee6e2d69a1b4..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-20-15-06-29.bpo-43795.y0IP4c.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyMem_Calloc` is now available in the limited C API -(``Py_LIMITED_API``). diff --git a/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst b/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst deleted file mode 100644 index 0413c20a1b6b22..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Introduce :const:`Py_TPFLAGS_IMMUTABLETYPE` flag for immutable type objects, and -modify :c:func:`PyType_Ready` to set it for static types. Patch by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/C API/2021-04-28-12-33-44.bpo-28254.a2561e.rst b/Misc/NEWS.d/next/C API/2021-04-28-12-33-44.bpo-28254.a2561e.rst deleted file mode 100644 index 015acc9803d474..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-28-12-33-44.bpo-28254.a2561e.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add new C-API functions to control the state of the garbage collector: -:c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, :c:func:`PyGC_IsEnabled()`, -corresponding to the functions in the :mod:`gc` module. diff --git a/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst b/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst deleted file mode 100644 index 32164162f90ad0..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst +++ /dev/null @@ -1,5 +0,0 @@ -_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and -always increments id_refcount. Previously, calling -_xxsubinterpreters.get_current() could create an id_refcount inconsistency -when a _xxsubinterpreters.InterpreterID object was deallocated. Patch by -Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-04-29-10-17-21.bpo-43774.5MGfgN.rst b/Misc/NEWS.d/next/C API/2021-04-29-10-17-21.bpo-43774.5MGfgN.rst deleted file mode 100644 index 9664b552717bbb..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-29-10-17-21.bpo-43774.5MGfgN.rst +++ /dev/null @@ -1,5 +0,0 @@ -Remove the now unused ``PYMALLOC_DEBUG`` macro. Debug hooks on memory -allocators are now installed by default if Python is built in debug mode (if -``Py_DEBUG`` macro is defined). Moreover, they can now be used on Python -build in release mode (ex: using ``PYTHONMALLOC=debug`` environment -variable). diff --git a/Misc/NEWS.d/next/C API/2021-04-29-17-35-48.bpo-43916.wvWt23.rst b/Misc/NEWS.d/next/C API/2021-04-29-17-35-48.bpo-43916.wvWt23.rst deleted file mode 100644 index 0cec8103645e34..00000000000000 --- a/Misc/NEWS.d/next/C API/2021-04-29-17-35-48.bpo-43916.wvWt23.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a new :c:data:`Py_TPFLAGS_DISALLOW_INSTANTIATION` type flag to disallow -creating type instances. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst new file mode 100644 index 00000000000000..61906584a16a38 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-01-05-10-16-16.bpo-46236.pcmVQw.rst @@ -0,0 +1 @@ +Fix a bug in :c:func:`PyFunction_GetAnnotations` that caused it to return a ``tuple`` instead of a ``dict``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-27-20-20-07.bpo-38530.ZyoDNn.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-27-20-20-07.bpo-38530.ZyoDNn.rst deleted file mode 100644 index 0bd2fa65448826..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-10-27-20-20-07.bpo-38530.ZyoDNn.rst +++ /dev/null @@ -1,3 +0,0 @@ -When printing :exc:`AttributeError`, :c:func:`PyErr_Display` will offer -suggestions of similar attribute names in the object that the exception was -raised from. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-12-12-14-28-31.bpo-42609.Qcd54b.rst b/Misc/NEWS.d/next/Core and Builtins/2020-12-12-14-28-31.bpo-42609.Qcd54b.rst deleted file mode 100644 index d2b0c641b2ecca..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-12-12-14-28-31.bpo-42609.Qcd54b.rst +++ /dev/null @@ -1,3 +0,0 @@ -Prevented crashes in the AST validator and optimizer when compiling some -absurdly long expressions like ``"+0"*1000000``. :exc:`RecursionError` is -now raised instead. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-03-31-16-32-57.bpo-43682.VSF3vg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-03-31-16-32-57.bpo-43682.VSF3vg.rst deleted file mode 100644 index 1ad949389a1f64..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-03-31-16-32-57.bpo-43682.VSF3vg.rst +++ /dev/null @@ -1,2 +0,0 @@ -Static methods (:func:`@staticmethod `) are now callable as -regular functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-03-31-20-35-11.bpo-43105.PBVmHm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-03-31-20-35-11.bpo-43105.PBVmHm.rst deleted file mode 100644 index dd4c18661ec0b8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-03-31-20-35-11.bpo-43105.PBVmHm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Importlib now resolves relative paths when creating module spec objects from -file locations. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-01-12-30-30.bpo-43683.AjxOx2.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-01-12-30-30.bpo-43683.AjxOx2.rst deleted file mode 100644 index 6e29998a49912e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-01-12-30-30.bpo-43683.AjxOx2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add GEN_START opcode. Marks start of generator, including async, or coroutine and handles -sending values to a newly created generator or coroutine. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-05-17-38-08.bpo-42128.1uVeGK.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-05-17-38-08.bpo-42128.1uVeGK.rst deleted file mode 100644 index b87c97cc08d254..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-05-17-38-08.bpo-42128.1uVeGK.rst +++ /dev/null @@ -1 +0,0 @@ -:data:`~object.__match_args__` is no longer allowed to be a list. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-07-18-00-05.bpo-43751.8fHsqQ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-07-18-00-05.bpo-43751.8fHsqQ.rst deleted file mode 100644 index 75951ae794d106..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-07-18-00-05.bpo-43751.8fHsqQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a bug where ``anext(ait, default)`` would erroneously return None. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-08-01-06-22.bpo-43682.eUn4p5.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-08-01-06-22.bpo-43682.eUn4p5.rst deleted file mode 100644 index ab5873edbd70f4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-08-01-06-22.bpo-43682.eUn4p5.rst +++ /dev/null @@ -1,5 +0,0 @@ -Static methods (:func:`@staticmethod `) and class methods -(:func:`@classmethod `) now inherit the method attributes -(``__module__``, ``__name__``, ``__qualname__``, ``__doc__``, -``__annotations__``) and have a new ``__wrapped__`` attribute. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-08-12-20-29.bpo-43760.tBIsD8.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-08-12-20-29.bpo-43760.tBIsD8.rst deleted file mode 100644 index e6612103d807e0..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-08-12-20-29.bpo-43760.tBIsD8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Move the flag for checking whether tracing is enabled to the C stack, from the heap. -Should speed up dispatch in the interpreter. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-09-19-12-48.bpo-43797.HfRqNP.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-09-19-12-48.bpo-43797.HfRqNP.rst deleted file mode 100644 index 2c10bb6ddc8c38..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-09-19-12-48.bpo-43797.HfRqNP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve ``SyntaxError`` error messages for invalid comparisons. Patch by -Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-10-00-01-43.bpo-43798.p_nJFM.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-10-00-01-43.bpo-43798.p_nJFM.rst deleted file mode 100644 index f6ab5dd410f284..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-10-00-01-43.bpo-43798.p_nJFM.rst +++ /dev/null @@ -1 +0,0 @@ -:class:`ast.alias` nodes now include source location metadata attributes e.g. lineno, col_offset. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-13-02-32-18.bpo-43822.lej0OO.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-13-02-32-18.bpo-43822.lej0OO.rst deleted file mode 100644 index f0e1c2f35a1868..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-13-02-32-18.bpo-43822.lej0OO.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve syntax errors in the parser for missing commas between expressions. -Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-13-03-06-09.bpo-43823.xpuHBi.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-13-03-06-09.bpo-43823.xpuHBi.rst deleted file mode 100644 index 96cf8eee16b7e9..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-13-03-06-09.bpo-43823.xpuHBi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve syntax errors for invalid dictionary literals. Patch by Pablo -Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-14-03-53-06.bpo-38530.rNI_G1.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-14-03-53-06.bpo-38530.rNI_G1.rst deleted file mode 100644 index ca175e7bebd9e5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-14-03-53-06.bpo-38530.rNI_G1.rst +++ /dev/null @@ -1,3 +0,0 @@ -When printing :exc:`NameError` raised by the interpreter, -:c:func:`PyErr_Display` will offer suggestions of similar variable names in -the function that the exception was raised from. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-14-13-53-08.bpo-43846.2jO97c.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-14-13-53-08.bpo-43846.2jO97c.rst deleted file mode 100644 index 220690cd813743..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-14-13-53-08.bpo-43846.2jO97c.rst +++ /dev/null @@ -1 +0,0 @@ -Data stack usage is much reduced for large literal and call expressions. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-15-10-19-59.bpo-41323.nsvpSg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-15-10-19-59.bpo-41323.nsvpSg.rst deleted file mode 100644 index b14299e77ebd5f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-15-10-19-59.bpo-41323.nsvpSg.rst +++ /dev/null @@ -1,2 +0,0 @@ -Constant tuple folding in bytecode optimizer now reuses tuple in constant -table. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-16-01-26-57.bpo-43859.QfqjFL.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-16-01-26-57.bpo-43859.QfqjFL.rst deleted file mode 100644 index c91f85b4338abb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-16-01-26-57.bpo-43859.QfqjFL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve the error message for :exc:`IndentationError` exceptions. Patch by -Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-20-20-10-46.bpo-43475.oV8Mbs.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-20-20-10-46.bpo-43475.oV8Mbs.rst deleted file mode 100644 index 73ed0222ba3b0c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-20-20-10-46.bpo-43475.oV8Mbs.rst +++ /dev/null @@ -1,3 +0,0 @@ -Hashes of NaN values now depend on object identity. Formerly, they always -hashed to 0 even though NaN values are not equal to one another. Having the -same hash for unequal values caused pile-ups in hash tables. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-20-22-17-47.bpo-38605.9eeCNZ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-20-22-17-47.bpo-38605.9eeCNZ.rst deleted file mode 100644 index d289424fda3954..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-20-22-17-47.bpo-38605.9eeCNZ.rst +++ /dev/null @@ -1,5 +0,0 @@ -Revert making ``from __future__ import annotations`` the default. This follows -the Steering Council decision to postpone PEP 563 changes to at least Python -3.11. See the original email for more information regarding the decision: -https://mail.python.org/archives/list/python-dev@python.org/thread/CLVXXPQ2T2LQ5MP2Y53VVQFCXYWQJHKZ/. -Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-22-19-09-58.bpo-43914.0Ik1AM.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-22-19-09-58.bpo-43914.0Ik1AM.rst deleted file mode 100644 index ce6747cb1d5d7e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-22-19-09-58.bpo-43914.0Ik1AM.rst +++ /dev/null @@ -1,3 +0,0 @@ -:exc:`SyntaxError` exceptions raised by the intepreter will highlight the -full error range of the expression that consistutes the syntax error itself, -instead of just where the problem is detected. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-22-22-48-30.bpo-42737.lsJ7pD.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-22-22-48-30.bpo-42737.lsJ7pD.rst deleted file mode 100644 index e55db436896af8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-22-22-48-30.bpo-42737.lsJ7pD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Annotations for complex targets (everything beside simple names) no longer -cause any runtime effects with ``from __future__ import annotations``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-24-16-40-23.bpo-43754.9SzHWG.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-24-16-40-23.bpo-43754.9SzHWG.rst deleted file mode 100644 index 54556fa299814c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-24-16-40-23.bpo-43754.9SzHWG.rst +++ /dev/null @@ -1,2 +0,0 @@ -When performing structural pattern matching (:pep:`634`), captured names are -now left unbound until the *entire* pattern has matched successfully. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-05-40-51.bpo-42725.WGloYm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-25-05-40-51.bpo-42725.WGloYm.rst deleted file mode 100644 index c9ea706e982668..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-05-40-51.bpo-42725.WGloYm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Usage of ``await``/``yield``/``yield from`` and named expressions within an -annotation is now forbidden when PEP 563 is activated. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-08-35-11.bpo-43892.hr5Ke2.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-25-08-35-11.bpo-43892.hr5Ke2.rst deleted file mode 100644 index 69be1b243c7be5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-08-35-11.bpo-43892.hr5Ke2.rst +++ /dev/null @@ -1,5 +0,0 @@ -Match patterns now use new dedicated AST nodes (``MatchValue``, -``MatchSingleton``, ``MatchSequence``, ``MatchStar``, ``MatchMapping``, -``MatchClass``) rather than reusing expression AST nodes. ``MatchAs`` and -``MatchOr`` are now defined as pattern nodes rather than as expression nodes. -Patch by Nick Coghlan. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-22-50-47.bpo-43901.oKjG5E.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-25-22-50-47.bpo-43901.oKjG5E.rst deleted file mode 100644 index 2ab93d1f756f6e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-25-22-50-47.bpo-43901.oKjG5E.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change class and module objects to lazy-create empty annotations dicts on -demand. The annotations dicts are stored in the object's __dict__ for -backwards compatibility. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-26-20-59-17.bpo-43908.-COW4-.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-26-20-59-17.bpo-43908.-COW4-.rst deleted file mode 100644 index 07303b99d1f95d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-26-20-59-17.bpo-43908.-COW4-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make the :class:`array.array` type immutable. Patch by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-26-21-20-41.bpo-43908.2L51nO.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-26-21-20-41.bpo-43908.2L51nO.rst deleted file mode 100644 index 1709351726f965..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-26-21-20-41.bpo-43908.2L51nO.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make :mod:`re` types immutable. Patch by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-27-10-59-10.bpo-42739.PrVkKM.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-27-10-59-10.bpo-42739.PrVkKM.rst deleted file mode 100644 index b59f3e1b6ccc5d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-27-10-59-10.bpo-42739.PrVkKM.rst +++ /dev/null @@ -1,4 +0,0 @@ -The internal representation of line number tables is changed to not use -sentinels, and an explicit length parameter is added to the out of process -API function ``PyLineTable_InitAddressRange``. This makes the handling of -line number tables more robust in some circumstances. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst deleted file mode 100644 index 1f8904338f26c8..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Importing the :mod:`_signal` module in a subinterpreter has no longer side -effects. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-11-44.bpo-43933.mvoV6O.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-11-44.bpo-43933.mvoV6O.rst deleted file mode 100644 index 8d11a8cb3dab3d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-11-44.bpo-43933.mvoV6O.rst +++ /dev/null @@ -1,3 +0,0 @@ -If the current position in a frame has no line number then set the f_lineno -attribute to None, instead of -1, to conform to PEP 626. This should not -normally be possible, but might occur in some unusual circumstances. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-49-57.bpo-43933.TueFdQ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-49-57.bpo-43933.TueFdQ.rst deleted file mode 100644 index d442f303edc076..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-13-49-57.bpo-43933.TueFdQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Set frame.f_lineno to the line number of the 'with' kweyword when executing -the call to ``__exit__``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-16-00-28.bpo-43892.WXIehI.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-29-16-00-28.bpo-43892.WXIehI.rst deleted file mode 100644 index f2a3dc90e556fd..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-16-00-28.bpo-43892.WXIehI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Restore proper validation of complex literal value patterns when parsing -:keyword:`!match` blocks. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-17-40-25.bpo-43977.FrQhge.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-29-17-40-25.bpo-43977.FrQhge.rst deleted file mode 100644 index 038d7390852baf..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-04-29-17-40-25.bpo-43977.FrQhge.rst +++ /dev/null @@ -1,2 +0,0 @@ -Use :c:member:`~PyTypeObject.tp_flags` on the class object to determine if the subject is a sequence -or mapping when pattern matching. Avoids the need to import :mod:`collections.abc` when pattern matching. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-05-02-11-59-00.bpo-43977.R0hSDo.rst b/Misc/NEWS.d/next/Core and Builtins/2021-05-02-11-59-00.bpo-43977.R0hSDo.rst deleted file mode 100644 index 95aacaf5fa2c37..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-05-02-11-59-00.bpo-43977.R0hSDo.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent classes being both a sequence and a mapping when pattern matching. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst new file mode 100644 index 00000000000000..f03dadebcf3b3b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-06-15-32-12.bpo-42918.Czpgtg.rst @@ -0,0 +1,3 @@ +Fix bug where the built-in :func:`compile` function did not always raise a +:exc:`SyntaxError` when passed multiple statements in 'single' mode. Patch by +Weipeng Hong. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst new file mode 100644 index 00000000000000..199bccf8166f06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-24-24.bpo-46004.TTEU1p.rst @@ -0,0 +1,2 @@ +Fix the :exc:`SyntaxError` location for errors involving for loops with +invalid targets. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst new file mode 100644 index 00000000000000..68e4bfa9e77b15 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-07-11-42-44.bpo-46000.v_ru3k.rst @@ -0,0 +1 @@ +Improve compatibility of the :mod:`curses` module with NetBSD curses. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst new file mode 100644 index 00000000000000..a80e66b7c6451d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-08-11-06-53.bpo-46009.cL8pH0.rst @@ -0,0 +1,5 @@ +Restore behavior from 3.9 and earlier when sending non-None to newly started +generator. In 3.9 this did not affect the state of the generator. In 3.10.0 +and 3.10.1 ``gen_func().send(0)`` is equivalent to +``gen_func().throw(TypeError(...)`` which exhausts the generator. In 3.10.2 +onward, the behavior has been reverted to that of 3.9. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst new file mode 100644 index 00000000000000..dd2f1ff4731e76 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-09-11-41-35.bpo-46025.pkEvW9.rst @@ -0,0 +1,2 @@ +Fix a crash in the :mod:`atexit` module involving functions that unregister +themselves before raising exceptions. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst new file mode 100644 index 00000000000000..7a302bcd7648b3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-11-17-40-34.bpo-46042.aqYxku.rst @@ -0,0 +1,2 @@ +Improve the location of the caret in :exc:`SyntaxError` exceptions emitted +by the symbol table. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst new file mode 100644 index 00000000000000..6ca91f03445e2a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-12-05-30-21.bpo-46054.2P-foG.rst @@ -0,0 +1,2 @@ +Fix parser error when parsing non-utf8 characters in source files. Patch by +Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst new file mode 100644 index 00000000000000..593d2855972c48 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-18-02-37-07.bpo-46110.B6hAfu.rst @@ -0,0 +1,2 @@ +Add a maximum recursion check to the PEG parser to avoid stack overflow. +Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst new file mode 100644 index 00000000000000..a2093f75c3b625 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-30-00-23-41.bpo-46085.bDuJqu.rst @@ -0,0 +1 @@ +Fix iterator cache mechanism of :class:`OrderedDict`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst new file mode 100644 index 00000000000000..3acd2b09390a8d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst @@ -0,0 +1,5 @@ +Fix a regression when a type method like ``__init__()`` is modified in a +subinterpreter. Fix a regression in ``_PyUnicode_EqualToASCIIId()`` and type +``update_slot()``. Revert the change which made the Unicode dictionary of +interned strings compatible with subinterpreters: the internal interned +dictionary is shared again by all interpreters. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-07-19-33-05.bpo-46237.9A6Hpq.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-07-19-33-05.bpo-46237.9A6Hpq.rst new file mode 100644 index 00000000000000..931a2603293c39 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-07-19-33-05.bpo-46237.9A6Hpq.rst @@ -0,0 +1,2 @@ +Fix the line number of tokenizer errors inside f-strings. Patch by Pablo +Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-07-23-32-03.bpo-46289.NnjpVc.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-07-23-32-03.bpo-46289.NnjpVc.rst new file mode 100644 index 00000000000000..816ff585f14e6d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-07-23-32-03.bpo-46289.NnjpVc.rst @@ -0,0 +1,2 @@ +ASDL declaration of ``FormattedValue`` has changed to reflect ``conversion`` +field is not optional. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-11-13-57-00.bpo-46347.Gd8M-S.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-11-13-57-00.bpo-46347.Gd8M-S.rst new file mode 100644 index 00000000000000..fc12d6ba146caa --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-11-13-57-00.bpo-46347.Gd8M-S.rst @@ -0,0 +1 @@ +Fix memory leak in PyEval_EvalCodeEx. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst new file mode 100644 index 00000000000000..4ed088f9898ebe --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-13-17-58-56.bpo-46070.q8IGth.rst @@ -0,0 +1,5 @@ +:c:func:`Py_EndInterpreter` now explicitly untracks all objects currently +tracked by the GC. Previously, if an object was used later by another +interpreter, calling :c:func:`PyObject_GC_UnTrack` on the object crashed if the +previous or the next object of the :c:type:`PyGC_Head` structure became a +dangling pointer. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-06-07-05-49.bpo-43739.L4HjiX.rst b/Misc/NEWS.d/next/Documentation/2021-04-06-07-05-49.bpo-43739.L4HjiX.rst deleted file mode 100644 index 9f8d3625e79618..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-06-07-05-49.bpo-43739.L4HjiX.rst +++ /dev/null @@ -1 +0,0 @@ -Fixing the example code in Doc/extending/extending.rst to declare and initialize the pmodule variable to be of the right type. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Documentation/2021-04-06-14-55-45.bpo-43755.1m0fGq.rst b/Misc/NEWS.d/next/Documentation/2021-04-06-14-55-45.bpo-43755.1m0fGq.rst deleted file mode 100644 index 53cba0b47d6d3b..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-06-14-55-45.bpo-43755.1m0fGq.rst +++ /dev/null @@ -1,3 +0,0 @@ -Update documentation to reflect that unparenthesized lambda expressions can -no longer be the expression part in an ``if`` clause in comprehensions and -generator expressions since Python 3.9. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-08-22-42-02.bpo-43778.MszRnY.rst b/Misc/NEWS.d/next/Documentation/2021-04-08-22-42-02.bpo-43778.MszRnY.rst deleted file mode 100644 index 86dc286f83ce9b..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-08-22-42-02.bpo-43778.MszRnY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the Sphinx glossary_search extension: create the _static/ sub-directory -if it doesn't exist. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-25-22-44-27.bpo-43938.nC660q.rst b/Misc/NEWS.d/next/Documentation/2021-04-25-22-44-27.bpo-43938.nC660q.rst deleted file mode 100644 index dcf252e21bb9e0..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-25-22-44-27.bpo-43938.nC660q.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update dataclasses documentation to express that FrozenInstanceError is -derived from AttributeError. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-27-22-22-22.bpo-43959.n2261q.rst b/Misc/NEWS.d/next/Documentation/2021-04-27-22-22-22.bpo-43959.n2261q.rst deleted file mode 100644 index ba23ffd577b3d4..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-27-22-22-22.bpo-43959.n2261q.rst +++ /dev/null @@ -1 +0,0 @@ -The documentation on the PyContextVar C-API was clarified. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-29-15-06-03.bpo-43977.K5aSl1.rst b/Misc/NEWS.d/next/Documentation/2021-04-29-15-06-03.bpo-43977.K5aSl1.rst deleted file mode 100644 index 20b5fd7ab86fa8..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-29-15-06-03.bpo-43977.K5aSl1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document the new :const:`Py_TPFLAGS_MAPPING` and -:const:`Py_TPFLAGS_SEQUENCE` type flags. diff --git a/Misc/NEWS.d/next/Documentation/2021-04-30-04-27-02.bpo-43987.1DftVa.rst b/Misc/NEWS.d/next/Documentation/2021-04-30-04-27-02.bpo-43987.1DftVa.rst deleted file mode 100644 index 158259e3ab378e..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2021-04-30-04-27-02.bpo-43987.1DftVa.rst +++ /dev/null @@ -1 +0,0 @@ -Add "Annotations Best Practices" document as a new HOWTO. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst new file mode 100644 index 00000000000000..87371e5b76bc11 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-19-02-02-32.bpo-45840.A51B2S.rst @@ -0,0 +1 @@ +Improve cross-references in the documentation for the data model. diff --git a/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst new file mode 100644 index 00000000000000..a3e16c9fdd0e68 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-11-28-22-43-21.bpo-19737.cOOubB.rst @@ -0,0 +1 @@ +Update the documentation for the :func:`globals` function. diff --git a/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst b/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst new file mode 100644 index 00000000000000..c63b2c92b37909 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-11-20-03-09.bpo-46040.qrsG0C.rst @@ -0,0 +1,2 @@ +Fix removal Python version for ``@asyncio.coroutine``, the correct value is +3.11. diff --git a/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst new file mode 100644 index 00000000000000..17f67472e2ab02 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2021-12-21-12-45-57.bpo-46120.PE0DmJ.rst @@ -0,0 +1 @@ +State that ``|`` is preferred for readability over ``Union`` in the :mod:`typing` docs. diff --git a/Misc/NEWS.d/next/IDLE/2019-08-24-23-49-36.bpo-37903.4xjast.rst b/Misc/NEWS.d/next/IDLE/2019-08-24-23-49-36.bpo-37903.4xjast.rst deleted file mode 100644 index 56b50e2e91e467..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-08-24-23-49-36.bpo-37903.4xjast.rst +++ /dev/null @@ -1 +0,0 @@ -IDLE's shell now shows prompts in a separate side-bar. diff --git a/Misc/NEWS.d/next/IDLE/2021-04-04-20-52-07.bpo-43655.HSyaKH.rst b/Misc/NEWS.d/next/IDLE/2021-04-04-20-52-07.bpo-43655.HSyaKH.rst deleted file mode 100644 index 105ec9281f0051..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-04-04-20-52-07.bpo-43655.HSyaKH.rst +++ /dev/null @@ -1,2 +0,0 @@ -IDLE dialog windows are now recognized as dialogs by window managers on -macOS and X Window. diff --git a/Misc/NEWS.d/next/IDLE/2021-04-29-02-40-41.bpo-37892.bgW2fk.rst b/Misc/NEWS.d/next/IDLE/2021-04-29-02-40-41.bpo-37892.bgW2fk.rst deleted file mode 100644 index c8bb84bb400413..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-04-29-02-40-41.bpo-37892.bgW2fk.rst +++ /dev/null @@ -1 +0,0 @@ -Indent IDLE Shell input with spaces instead of tabs diff --git a/Misc/NEWS.d/next/IDLE/2021-04-30-17-59-56.bpo-43981.3EFl1H.rst b/Misc/NEWS.d/next/IDLE/2021-04-30-17-59-56.bpo-43981.3EFl1H.rst deleted file mode 100644 index 10eb8b01d13a48..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-04-30-17-59-56.bpo-43981.3EFl1H.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reference leak in test_squeezer. Patch by Pablo Galindo \ No newline at end of file diff --git a/Misc/NEWS.d/next/IDLE/2021-05-02-20-25-53.bpo-37903.VQ6VTU.rst b/Misc/NEWS.d/next/IDLE/2021-05-02-20-25-53.bpo-37903.VQ6VTU.rst deleted file mode 100644 index 28b11e60f0fb3e..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2021-05-02-20-25-53.bpo-37903.VQ6VTU.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add mouse actions to the shell sidebar. Left click and optional drag -selects one or more lines, as with the editor line number sidebar. Right -click after selecting raises a context menu with 'copy with prompts'. This -zips together prompts from the sidebar with lines from the selected text. diff --git a/Misc/NEWS.d/next/Library/2018-08-09-23-47-10.bpo-32745.iQi9hI.rst b/Misc/NEWS.d/next/Library/2018-08-09-23-47-10.bpo-32745.iQi9hI.rst deleted file mode 100644 index e6a60fe8da140b..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-08-09-23-47-10.bpo-32745.iQi9hI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a regression in the handling of ctypes' :data:`ctypes.c_wchar_p` type: -embedded null characters would cause a :exc:`ValueError` to be raised. Patch -by Zackery Spytz. diff --git a/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst b/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst deleted file mode 100644 index 2fedb0696c3266..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst +++ /dev/null @@ -1,2 +0,0 @@ -Provide a locale.localize() function, which converts a normalized number string -into a locale format. diff --git a/Misc/NEWS.d/next/Library/2019-10-16-08-08-14.bpo-38490.QbDXEF.rst b/Misc/NEWS.d/next/Library/2019-10-16-08-08-14.bpo-38490.QbDXEF.rst deleted file mode 100644 index 82b9e33be0e304..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-10-16-08-08-14.bpo-38490.QbDXEF.rst +++ /dev/null @@ -1 +0,0 @@ -Covariance, Pearson's correlation, and simple linear regression functionality was added to statistics module. Patch by Tymoteusz Wołodźko. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-10-16-17-21-53.bpo-36076.FGeQQT.rst b/Misc/NEWS.d/next/Library/2019-10-16-17-21-53.bpo-36076.FGeQQT.rst deleted file mode 100644 index 7e9bc4e461e06f..00000000000000 --- a/Misc/NEWS.d/next/Library/2019-10-16-17-21-53.bpo-36076.FGeQQT.rst +++ /dev/null @@ -1 +0,0 @@ -Added SNI support to :func:`ssl.get_server_certificate`. diff --git a/Misc/NEWS.d/next/Library/2020-03-09-20-36-07.bpo-39899.9adF3E.rst b/Misc/NEWS.d/next/Library/2020-03-09-20-36-07.bpo-39899.9adF3E.rst deleted file mode 100644 index 5239553d51c672..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-03-09-20-36-07.bpo-39899.9adF3E.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`os.path.expanduser()` now refuses to guess Windows home directories if the basename of current user's home directory does not match their username. - -:meth:`pathlib.Path.expanduser()` and :meth:`~pathlib.Path.home()` now consistently raise :exc:`RuntimeError` exception when a home directory cannot be resolved. Previously a :exc:`KeyError` exception could be raised on Windows when the ``"USERNAME"`` environment variable was unset. diff --git a/Misc/NEWS.d/next/Library/2020-03-30-00-13-27.bpo-39906.eaR3fN.rst b/Misc/NEWS.d/next/Library/2020-03-30-00-13-27.bpo-39906.eaR3fN.rst deleted file mode 100644 index dacefb73d93dd8..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-03-30-00-13-27.bpo-39906.eaR3fN.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`pathlib.Path.stat` and :meth:`~pathlib.Path.chmod` now accept a *follow_symlinks* keyword-only argument for consistency with corresponding functions in the :mod:`os` module. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2020-05-17-14-10-24.bpo-35114.uLIHfn.rst b/Misc/NEWS.d/next/Library/2020-05-17-14-10-24.bpo-35114.uLIHfn.rst deleted file mode 100644 index e1d57f597bd466..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-05-17-14-10-24.bpo-35114.uLIHfn.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`ssl.RAND_status` now returns a boolean value (as documented) instead -of ``1`` or ``0``. diff --git a/Misc/NEWS.d/next/Library/2020-06-02-21-32-33.bpo-40849.zpeKx3.rst b/Misc/NEWS.d/next/Library/2020-06-02-21-32-33.bpo-40849.zpeKx3.rst deleted file mode 100644 index 032a65d9963b7b..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-06-02-21-32-33.bpo-40849.zpeKx3.rst +++ /dev/null @@ -1 +0,0 @@ -Expose X509_V_FLAG_PARTIAL_CHAIN ssl flag diff --git a/Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst b/Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst deleted file mode 100644 index 9b6ab994f3b6a3..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix dataclasses with ``InitVar``\s and :func:`~dataclasses.replace()`. Patch -by Claudiu Popa. diff --git a/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst b/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst deleted file mode 100644 index 9e36435a364eaf..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-09-07-11-15-15.bpo-41735.NKqGKy.rst +++ /dev/null @@ -1 +0,0 @@ -Fix thread locks in zlib module may go wrong in rare case. Patch by Ma Lin. diff --git a/Misc/NEWS.d/next/Library/2020-09-15-23-44-07.bpo-31870.nVwd38.rst b/Misc/NEWS.d/next/Library/2020-09-15-23-44-07.bpo-31870.nVwd38.rst deleted file mode 100644 index 6adf456d2d6cc9..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-09-15-23-44-07.bpo-31870.nVwd38.rst +++ /dev/null @@ -1,2 +0,0 @@ -The :func:`ssl.get_server_certificate` function now has a *timeout* -parameter. diff --git a/Misc/NEWS.d/next/Library/2020-10-16-15-34-30.bpo-41486.Mu9Iit.rst b/Misc/NEWS.d/next/Library/2020-10-16-15-34-30.bpo-41486.Mu9Iit.rst deleted file mode 100644 index 75de9f672ea5d3..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-10-16-15-34-30.bpo-41486.Mu9Iit.rst +++ /dev/null @@ -1,4 +0,0 @@ -Use a new output buffer management code for :mod:`bz2` / :mod:`lzma` / -:mod:`zlib` modules, and add ``.readall()`` function to -``_compression.DecompressReader`` class. These bring some performance -improvements. Patch by Ma Lin. diff --git a/Misc/NEWS.d/next/Library/2020-11-19-09-52-24.bpo-18369.qzvYH2.rst b/Misc/NEWS.d/next/Library/2020-11-19-09-52-24.bpo-18369.qzvYH2.rst deleted file mode 100644 index 1b97afbd2c40ff..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-11-19-09-52-24.bpo-18369.qzvYH2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Certificate and PrivateKey classes were added to the ssl module. -Certificates and keys can now be loaded from memory buffer, too. diff --git a/Misc/NEWS.d/next/Library/2020-12-06-20-21-16.bpo-39529.9Zrg43.rst b/Misc/NEWS.d/next/Library/2020-12-06-20-21-16.bpo-39529.9Zrg43.rst deleted file mode 100644 index bb1fd82c99e363..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-12-06-20-21-16.bpo-39529.9Zrg43.rst +++ /dev/null @@ -1,9 +0,0 @@ -Deprecated use of :func:`asyncio.get_event_loop` without running event loop. -Emit deprecation warning for :mod:`asyncio` functions which implicitly -create a :class:`~asyncio.Future` or :class:`~asyncio.Task` objects if there -is no running event loop and no explicit *loop* argument is passed: -:func:`~asyncio.ensure_future`, :func:`~asyncio.wrap_future`, -:func:`~asyncio.gather`, :func:`~asyncio.shield`, -:func:`~asyncio.as_completed` and constructors of :class:`~asyncio.Future`, -:class:`~asyncio.Task`, :class:`~asyncio.StreamReader`, -:class:`~asyncio.StreamReaderProtocol`. diff --git a/Misc/NEWS.d/next/Library/2021-01-08-22-32-13.bpo-42269.W5v8z4.rst b/Misc/NEWS.d/next/Library/2021-01-08-22-32-13.bpo-42269.W5v8z4.rst deleted file mode 100644 index 595f8733d0eab9..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-01-08-22-32-13.bpo-42269.W5v8z4.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add ``slots`` parameter to ``dataclasses.dataclass`` decorator to -automatically generate ``__slots__`` for class. Patch provided by Yurii -Karabas. diff --git a/Misc/NEWS.d/next/Library/2021-01-12-23-17-02.bpo-42904.-4qkTD.rst b/Misc/NEWS.d/next/Library/2021-01-12-23-17-02.bpo-42904.-4qkTD.rst deleted file mode 100644 index ef4b4e56fbebcd..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-01-12-23-17-02.bpo-42904.-4qkTD.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`typing.get_type_hints` now checks the local namespace of a class when -evaluating :pep:`563` annotations inside said class. diff --git a/Misc/NEWS.d/next/Library/2021-01-22-00-15-37.bpo-39950.NzLVaR.rst b/Misc/NEWS.d/next/Library/2021-01-22-00-15-37.bpo-39950.NzLVaR.rst deleted file mode 100644 index 33b8acf9c18fbb..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-01-22-00-15-37.bpo-39950.NzLVaR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add `pathlib.Path.hardlink_to()` method that supersedes `link_to()`. The new -method has the same argument order as `symlink_to()`. diff --git a/Misc/NEWS.d/next/Library/2021-01-31-00-23-13.bpo-43080.-fDg4Q.rst b/Misc/NEWS.d/next/Library/2021-01-31-00-23-13.bpo-43080.-fDg4Q.rst deleted file mode 100644 index aa59b901739b49..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-01-31-00-23-13.bpo-43080.-fDg4Q.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`pprint` now has support for :class:`dataclasses.dataclass`. Patch by Lewis Gaul. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-02-09-07-24-29.bpo-43176.bocNQn.rst b/Misc/NEWS.d/next/Library/2021-02-09-07-24-29.bpo-43176.bocNQn.rst deleted file mode 100644 index 016514d9c3346c..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-02-09-07-24-29.bpo-43176.bocNQn.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed processing of a dataclass that inherits from a frozen dataclass with no fields. It is now correctly detected as an error. diff --git a/Misc/NEWS.d/next/Library/2021-02-15-12-52-23.bpo-41282.SenEje.rst b/Misc/NEWS.d/next/Library/2021-02-15-12-52-23.bpo-41282.SenEje.rst deleted file mode 100644 index 95ac1831dbf2d3..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-02-15-12-52-23.bpo-41282.SenEje.rst +++ /dev/null @@ -1 +0,0 @@ -:mod:`distutils.sysconfig` has been merged to :mod:`sysconfig`. diff --git a/Misc/NEWS.d/next/Library/2021-02-16-13-18-38.bpo-41282.GK9a0l.rst b/Misc/NEWS.d/next/Library/2021-02-16-13-18-38.bpo-41282.GK9a0l.rst deleted file mode 100644 index eefebcfe1ba7c4..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-02-16-13-18-38.bpo-41282.GK9a0l.rst +++ /dev/null @@ -1,2 +0,0 @@ -Install schemes in :mod:`distutils.command.install` are now loaded from -:mod:`sysconfig`. diff --git a/Misc/NEWS.d/next/Library/2021-02-19-22-24-33.bpo-43265.MyAzCH.rst b/Misc/NEWS.d/next/Library/2021-02-19-22-24-33.bpo-43265.MyAzCH.rst deleted file mode 100644 index 3e7f34ea5649da..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-02-19-22-24-33.bpo-43265.MyAzCH.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve :meth:`sqlite3.Connection.backup` error handling. The error message -for non-existant target database names is now ``unknown database `` instead of ``SQL logic error``. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-02-25-14-43-59.bpo-43312.6dg9_2.rst b/Misc/NEWS.d/next/Library/2021-02-25-14-43-59.bpo-43312.6dg9_2.rst deleted file mode 100644 index b8def9ceee64cf..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-02-25-14-43-59.bpo-43312.6dg9_2.rst +++ /dev/null @@ -1,3 +0,0 @@ -New functions :func:`sysconfig.get_preferred_scheme` and -:func:`sysconfig.get_default_scheme` are added to query a platform for its -preferred "user", "home", and "prefix" (default) scheme names. diff --git a/Misc/NEWS.d/next/Library/2021-03-01-13-01-33.bpo-43296.p_gU6T.rst b/Misc/NEWS.d/next/Library/2021-03-01-13-01-33.bpo-43296.p_gU6T.rst deleted file mode 100644 index 741dfcd705ebd9..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-01-13-01-33.bpo-43296.p_gU6T.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve :mod:`sqlite3` error handling: ``sqlite3_value_blob()`` errors that -set ``SQLITE_NOMEM`` now raise :exc:`MemoryError`. Patch by Erlend E. -Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-03-11-00-31-41.bpo-42967.2PeQRw.rst b/Misc/NEWS.d/next/Library/2021-03-11-00-31-41.bpo-42967.2PeQRw.rst deleted file mode 100644 index f8ad3eaaedd785..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-11-00-31-41.bpo-42967.2PeQRw.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allow :class:`bytes` ``separator`` argument in ``urllib.parse.parse_qs`` and -``urllib.parse.parse_qsl`` when parsing :class:`str` query strings. Previously, -this raised a ``TypeError``. diff --git a/Misc/NEWS.d/next/Library/2021-03-13-14-02-07.bpo-8978.CRxG-O.rst b/Misc/NEWS.d/next/Library/2021-03-13-14-02-07.bpo-8978.CRxG-O.rst deleted file mode 100644 index 2da8874dc7f343..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-13-14-02-07.bpo-8978.CRxG-O.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve error message for :func:`tarfile.open` when :mod:`lzma` / :mod:`bz2` -are unavailable. Patch by Anthony Sottile. diff --git a/Misc/NEWS.d/next/Library/2021-03-16-22-37-32.bpo-43522.dhNwOu.rst b/Misc/NEWS.d/next/Library/2021-03-16-22-37-32.bpo-43522.dhNwOu.rst deleted file mode 100644 index a17e1b44637383..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-16-22-37-32.bpo-43522.dhNwOu.rst +++ /dev/null @@ -1 +0,0 @@ -Fix problem with :attr:`~ssl.SSLContext.hostname_checks_common_name`. OpenSSL does not copy hostflags from *struct SSL_CTX* to *struct SSL*. diff --git a/Misc/NEWS.d/next/Library/2021-03-17-19-06-45.bpo-43532.W2Ntnm.rst b/Misc/NEWS.d/next/Library/2021-03-17-19-06-45.bpo-43532.W2Ntnm.rst deleted file mode 100644 index 11ea5f916d173f..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-17-19-06-45.bpo-43532.W2Ntnm.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add the ability to specify keyword-only fields to dataclasses. These fields -will become keyword-only arguments to the generated __init__. diff --git a/Misc/NEWS.d/next/Library/2021-03-18-15-46-08.bpo-43534.vPE9Us.rst b/Misc/NEWS.d/next/Library/2021-03-18-15-46-08.bpo-43534.vPE9Us.rst deleted file mode 100644 index 7f2e5a46add039..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-03-18-15-46-08.bpo-43534.vPE9Us.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`turtle.textinput` and :func:`turtle.numinput` create now a transient -window working on behalf of the canvas window. diff --git a/Misc/NEWS.d/next/Library/2021-04-03-15-24-59.bpo-2135.xmDAYJ.rst b/Misc/NEWS.d/next/Library/2021-04-03-15-24-59.bpo-2135.xmDAYJ.rst deleted file mode 100644 index 33e5cf4d208b9b..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-03-15-24-59.bpo-2135.xmDAYJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate find_module() and find_loader() implementations in importlib and -zipimport. diff --git a/Misc/NEWS.d/next/Library/2021-04-03-18-03-44.bpo-43723.uBhBZS.rst b/Misc/NEWS.d/next/Library/2021-04-03-18-03-44.bpo-43723.uBhBZS.rst deleted file mode 100644 index 27cf7aa716273c..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-03-18-03-44.bpo-43723.uBhBZS.rst +++ /dev/null @@ -1,19 +0,0 @@ -The following ``threading`` methods are now deprecated and should be replaced: - -- ``currentThread`` => :func:`threading.current_thread` - -- ``activeCount`` => :func:`threading.active_count` - -- ``Condition.notifyAll`` => :meth:`threading.Condition.notify_all` - -- ``Event.isSet`` => :meth:`threading.Event.is_set` - -- ``Thread.setName`` => :attr:`threading.Thread.name` - -- ``thread.getName`` => :attr:`threading.Thread.name` - -- ``Thread.isDaemon`` => :attr:`threading.Thread.daemon` - -- ``Thread.setDaemon`` => :attr:`threading.Thread.daemon` - -Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2021-04-04-20-51-19.bpo-43655.LwGy8R.rst b/Misc/NEWS.d/next/Library/2021-04-04-20-51-19.bpo-43655.LwGy8R.rst deleted file mode 100644 index 7916d2248b231d..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-04-20-51-19.bpo-43655.LwGy8R.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`tkinter` dialog windows are now recognized as dialogs by window -managers on macOS and X Window. diff --git a/Misc/NEWS.d/next/Library/2021-04-06-21-18-29.bpo-43752.K7qmAF.rst b/Misc/NEWS.d/next/Library/2021-04-06-21-18-29.bpo-43752.K7qmAF.rst deleted file mode 100644 index ef4b9539a8055d..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-06-21-18-29.bpo-43752.K7qmAF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix :mod:`sqlite3` regression for zero-sized blobs with converters, where -``b""`` was returned instead of ``None``. The regression was introduced by -GH-24723. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-09-59-20.bpo-43764.tHjO60.rst b/Misc/NEWS.d/next/Library/2021-04-08-09-59-20.bpo-43764.tHjO60.rst deleted file mode 100644 index 838dd0200f1d6b..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-09-59-20.bpo-43764.tHjO60.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where :data:`~object.__match_args__` generation could fail for -some :mod:`dataclasses`. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-11-47-31.bpo-38659.r_HFnU.rst b/Misc/NEWS.d/next/Library/2021-04-08-11-47-31.bpo-38659.r_HFnU.rst deleted file mode 100644 index 822584be1b221c..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-11-47-31.bpo-38659.r_HFnU.rst +++ /dev/null @@ -1,4 +0,0 @@ -A ``simple_enum`` decorator is added to the ``enum`` module to convert a -normal class into an Enum. ``test_simple_enum`` added to test simple enums -against a corresponding normal Enum. Standard library modules updated to -use ``simple_enum``. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-12-25-08.bpo-43712.f8WXCX.rst b/Misc/NEWS.d/next/Library/2021-04-08-12-25-08.bpo-43712.f8WXCX.rst deleted file mode 100644 index d11df0d1027000..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-12-25-08.bpo-43712.f8WXCX.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add ``encoding`` and ``errors`` parameters to :func:`fileinput.input` and -:class:`fileinput.FileInput`. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-15-19-20.bpo-43731.nnVd3h.rst b/Misc/NEWS.d/next/Library/2021-04-08-15-19-20.bpo-43731.nnVd3h.rst deleted file mode 100644 index e5309c92fddba3..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-15-19-20.bpo-43731.nnVd3h.rst +++ /dev/null @@ -1 +0,0 @@ -Add an ``encoding`` parameter :func:`logging.fileConfig()`. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-19-32-26.bpo-47383.YI1hdL.rst b/Misc/NEWS.d/next/Library/2021-04-08-19-32-26.bpo-47383.YI1hdL.rst deleted file mode 100644 index 8b680065ea7c3d..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-19-32-26.bpo-47383.YI1hdL.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``P.args`` and ``P.kwargs`` attributes of :class:`typing.ParamSpec` are -now instances of the new classes :class:`typing.ParamSpecArgs` and -:class:`typing.ParamSpecKwargs`, which enables a more useful ``repr()``. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-20-04-46.bpo-43780.hUOgCh.rst b/Misc/NEWS.d/next/Library/2021-04-08-20-04-46.bpo-43780.hUOgCh.rst deleted file mode 100644 index 3adbe50512beda..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-20-04-46.bpo-43780.hUOgCh.rst +++ /dev/null @@ -1,3 +0,0 @@ -In ``importlib.metadata``, incorporate changes from importlib_metadata 3.10: -Add mtime-based caching during distribution discovery. Flagged use of dict -result from ``entry_points()`` as deprecated. diff --git a/Misc/NEWS.d/next/Library/2021-04-08-22-11-27.bpo-25264.b33fa0.rst b/Misc/NEWS.d/next/Library/2021-04-08-22-11-27.bpo-25264.b33fa0.rst deleted file mode 100644 index 593846ec15c5b9..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-08-22-11-27.bpo-25264.b33fa0.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`os.path.realpath` now accepts a *strict* keyword-only argument. -When set to ``True``, :exc:`OSError` is raised if a path doesn't exist -or a symlink loop is encountered. diff --git a/Misc/NEWS.d/next/Library/2021-04-09-00-16-22.bpo-43766.nYNQP0.rst b/Misc/NEWS.d/next/Library/2021-04-09-00-16-22.bpo-43766.nYNQP0.rst deleted file mode 100644 index 4f039a7cebbf65..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-09-00-16-22.bpo-43766.nYNQP0.rst +++ /dev/null @@ -1,2 +0,0 @@ -Implement :pep:`647` in the :mod:`typing` module by adding -:data:`TypeGuard`. diff --git a/Misc/NEWS.d/next/Library/2021-04-09-12-08-01.bpo-43788.YsvInM.rst b/Misc/NEWS.d/next/Library/2021-04-09-12-08-01.bpo-43788.YsvInM.rst deleted file mode 100644 index ff76256472c6ec..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-09-12-08-01.bpo-43788.YsvInM.rst +++ /dev/null @@ -1,4 +0,0 @@ -The header files for :mod:`ssl` error codes are now OpenSSL -version-specific. Exceptions will now show correct reason and library -codes. The ``make_ssl_data.py`` script has been rewritten to use OpenSSL's -text file with error codes. diff --git a/Misc/NEWS.d/next/Library/2021-04-09-14-08-03.bpo-43789.eaHlAm.rst b/Misc/NEWS.d/next/Library/2021-04-09-14-08-03.bpo-43789.eaHlAm.rst deleted file mode 100644 index 1c0852946214d2..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-09-14-08-03.bpo-43789.eaHlAm.rst +++ /dev/null @@ -1,2 +0,0 @@ -OpenSSL 3.0.0: Don't call the password callback function a second time when -first call has signaled an error condition. diff --git a/Misc/NEWS.d/next/Library/2021-04-09-14-51-58.bpo-43785.1mM5xE.rst b/Misc/NEWS.d/next/Library/2021-04-09-14-51-58.bpo-43785.1mM5xE.rst deleted file mode 100644 index b4ed5e51e22475..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-09-14-51-58.bpo-43785.1mM5xE.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve ``bz2.BZ2File`` performance by removing the RLock from BZ2File. -This makes BZ2File thread unsafe in the face of multiple simultaneous -readers or writers, just like its equivalent classes in :mod:`gzip` and -:mod:`lzma` have always been. Patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2021-04-09-16-14-22.bpo-43794.-1XPDH.rst b/Misc/NEWS.d/next/Library/2021-04-09-16-14-22.bpo-43794.-1XPDH.rst deleted file mode 100644 index 64894bdc017e53..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-09-16-14-22.bpo-43794.-1XPDH.rst +++ /dev/null @@ -1 +0,0 @@ -Add :data:`ssl.OP_IGNORE_UNEXPECTED_EOF` constants (OpenSSL 3.0.0) diff --git a/Misc/NEWS.d/next/Library/2021-04-10-03-30-36.bpo-43478.iZcBTq.rst b/Misc/NEWS.d/next/Library/2021-04-10-03-30-36.bpo-43478.iZcBTq.rst deleted file mode 100644 index 12a03d79e72e0f..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-10-03-30-36.bpo-43478.iZcBTq.rst +++ /dev/null @@ -1,6 +0,0 @@ -Mocks can no longer be used as the specs for other Mocks. As a result, an -already-mocked object cannot have an attribute mocked using ``autospec=True`` -or be the subject of a ``create_autospec(...)`` call. This can uncover bugs in -tests since these Mock-derived Mocks will always pass certain tests (e.g. -:func:`isinstance`) and builtin assert functions (e.g. assert_called_once_with) -will unconditionally pass. diff --git a/Misc/NEWS.d/next/Library/2021-04-10-11-35-50.bpo-43799.1iV4pX.rst b/Misc/NEWS.d/next/Library/2021-04-10-11-35-50.bpo-43799.1iV4pX.rst deleted file mode 100644 index bd79519015c7a9..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-10-11-35-50.bpo-43799.1iV4pX.rst +++ /dev/null @@ -1,2 +0,0 @@ -OpenSSL 3.0.0: define ``OPENSSL_API_COMPAT`` 1.1.1 to suppress deprecation -warnings. Python requires OpenSSL 1.1.1 APIs. diff --git a/Misc/NEWS.d/next/Library/2021-04-10-18-23-09.bpo-43764.Le5KJp.rst b/Misc/NEWS.d/next/Library/2021-04-10-18-23-09.bpo-43764.Le5KJp.rst deleted file mode 100644 index 555aad06e32ca6..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-10-18-23-09.bpo-43764.Le5KJp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add match_args parameter to @dataclass decorator to allow suppression of -__match_args__ generation. diff --git a/Misc/NEWS.d/next/Library/2021-04-10-19-14-49.bpo-43772.Bxq0zQ.rst b/Misc/NEWS.d/next/Library/2021-04-10-19-14-49.bpo-43772.Bxq0zQ.rst deleted file mode 100644 index 648357b3faa741..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-10-19-14-49.bpo-43772.Bxq0zQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the return value of ``TypeVar.__ror__``. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Library/2021-04-11-20-52-32.bpo-43744.uf0E68.rst b/Misc/NEWS.d/next/Library/2021-04-11-20-52-32.bpo-43744.uf0E68.rst deleted file mode 100644 index 7fd74be87664e4..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-11-20-52-32.bpo-43744.uf0E68.rst +++ /dev/null @@ -1,2 +0,0 @@ -fix issue with enum member name matching the start of a private variable -name diff --git a/Misc/NEWS.d/next/Library/2021-04-11-21-10-57.bpo-42248.pedB1E.rst b/Misc/NEWS.d/next/Library/2021-04-11-21-10-57.bpo-42248.pedB1E.rst deleted file mode 100644 index 0722d35a37a1fa..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-11-21-10-57.bpo-42248.pedB1E.rst +++ /dev/null @@ -1 +0,0 @@ -[Enum] ensure exceptions raised in ``_missing__`` are released diff --git a/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst b/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst deleted file mode 100644 index 51bc791f10d31a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-00-00-00.bpo-43776.p14y7a.rst +++ /dev/null @@ -1 +0,0 @@ -When :class:`subprocess.Popen` args are provided as a string or as :class:`pathlib.Path`, the Popen instance repr now shows the right thing. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-04-12-06-01-10.bpo-41515.YaVReb.rst b/Misc/NEWS.d/next/Library/2021-04-12-06-01-10.bpo-41515.YaVReb.rst deleted file mode 100644 index aef5c1791dfeac..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-06-01-10.bpo-41515.YaVReb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :exc:`KeyError` raised in :func:`typing.get_type_hints` due to -synthetic modules that don't appear in ``sys.modules``. diff --git a/Misc/NEWS.d/next/Library/2021-04-12-09-57-37.bpo-43680.o1zEk_.rst b/Misc/NEWS.d/next/Library/2021-04-12-09-57-37.bpo-43680.o1zEk_.rst deleted file mode 100644 index cb561ae586a98d..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-09-57-37.bpo-43680.o1zEk_.rst +++ /dev/null @@ -1,6 +0,0 @@ -The Python :func:`_pyio.open` function becomes a static method to behave as -:func:`io.open` built-in function: don't become a bound method when stored as a -class variable. It becomes possible since static methods are now callable in -Python 3.10. Moreover, :func:`_pyio.OpenWrapper` becomes a simple alias to -:func:`_pyio.open`. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-04-12-11-20-34.bpo-43680.SR0Epv.rst b/Misc/NEWS.d/next/Library/2021-04-12-11-20-34.bpo-43680.SR0Epv.rst deleted file mode 100644 index e4ddb96491b571..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-11-20-34.bpo-43680.SR0Epv.rst +++ /dev/null @@ -1,6 +0,0 @@ -Deprecate io.OpenWrapper and _pyio.OpenWrapper: use io.open and _pyio.open -instead. Until Python 3.9, _pyio.open was not a static method and -builtins.open was set to OpenWrapper to not become a bound method when set -to a class variable. _io.open is a built-in function whereas _pyio.open is a -Python function. In Python 3.10, _pyio.open() is now a static method, and -builtins.open() is now io.open(). diff --git a/Misc/NEWS.d/next/Library/2021-04-12-15-15-50.bpo-43787.wCy_Wd.rst b/Misc/NEWS.d/next/Library/2021-04-12-15-15-50.bpo-43787.wCy_Wd.rst deleted file mode 100644 index 9b8d945cbb8a8b..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-15-15-50.bpo-43787.wCy_Wd.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add ``__iter__()`` method to :class:`bz2.BZ2File`, :class:`gzip.GzipFile`, and -:class:`lzma.LZMAFile`. It makes iterating them about 2x faster. Patch by -Inada Naoki. diff --git a/Misc/NEWS.d/next/Library/2021-04-12-18-01-10.bpo-43820.YkqYW4.rst b/Misc/NEWS.d/next/Library/2021-04-12-18-01-10.bpo-43820.YkqYW4.rst deleted file mode 100644 index 2c870ac8b97de8..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-12-18-01-10.bpo-43820.YkqYW4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove an unneeded copy of the namespace passed to -dataclasses.make_dataclass(). diff --git a/Misc/NEWS.d/next/Library/2021-04-16-02-03-00.bpo-40443.Io6FHL.rst b/Misc/NEWS.d/next/Library/2021-04-16-02-03-00.bpo-40443.Io6FHL.rst deleted file mode 100644 index f5672e6bd7bf57..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-16-02-03-00.bpo-40443.Io6FHL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove unused imports: pyclbr no longer uses copy, and typing no longer uses -ast. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2021-04-16-16-46-44.bpo-43867.xT9QjF.rst b/Misc/NEWS.d/next/Library/2021-04-16-16-46-44.bpo-43867.xT9QjF.rst deleted file mode 100644 index 1ec914e5ee9d03..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-16-16-46-44.bpo-43867.xT9QjF.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :mod:`multiprocessing` ``Server`` class now explicitly catchs -:exc:`SystemExit` and closes the client connection in this case. It happens -when the ``Server.serve_client()`` method reachs the end of file (EOF). diff --git a/Misc/NEWS.d/next/Library/2021-04-17-10-49-57.bpo-41559.caIwt9.rst b/Misc/NEWS.d/next/Library/2021-04-17-10-49-57.bpo-41559.caIwt9.rst deleted file mode 100644 index 11db42350eb7ef..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-17-10-49-57.bpo-41559.caIwt9.rst +++ /dev/null @@ -1,6 +0,0 @@ -:pep:`612` is now implemented purely in Python; builtin ``types.GenericAlias`` -objects no longer include ``typing.ParamSpec`` in ``__parameters__`` -(with the exception of ``collections.abc.Callable``\ 's ``GenericAlias``). -This means previously invalid uses of ``ParamSpec`` (such as -``list[P]``) which worked in earlier versions of Python 3.10 alpha, -will now raise ``TypeError`` during substitution. diff --git a/Misc/NEWS.d/next/Library/2021-04-17-13-53-33.bpo-43880.-fC2JD.rst b/Misc/NEWS.d/next/Library/2021-04-17-13-53-33.bpo-43880.-fC2JD.rst deleted file mode 100644 index b50680afc23fd6..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-17-13-53-33.bpo-43880.-fC2JD.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`ssl` now raises DeprecationWarning for OP_NO_SSL/TLS* options, old TLS -versions, old protocols, and other features that have been deprecated since -Python 3.6, 3.7, or OpenSSL 1.1.0. diff --git a/Misc/NEWS.d/next/Library/2021-04-19-03-54-29.bpo-42854.Y4M7Tv.rst b/Misc/NEWS.d/next/Library/2021-04-19-03-54-29.bpo-42854.Y4M7Tv.rst deleted file mode 100644 index 3941fd85635f02..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-19-03-54-29.bpo-42854.Y4M7Tv.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :mod:`ssl` module now uses ``SSL_read_ex`` and ``SSL_write_ex`` -internally. The functions support reading and writing of data larger -than 2 GB. Writing zero-length data no longer fails with a protocol -violation error. diff --git a/Misc/NEWS.d/next/Library/2021-04-21-14-50-57.bpo-43284.2QZn2T.rst b/Misc/NEWS.d/next/Library/2021-04-21-14-50-57.bpo-43284.2QZn2T.rst deleted file mode 100644 index 7e41016015efed..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-21-14-50-57.bpo-43284.2QZn2T.rst +++ /dev/null @@ -1,6 +0,0 @@ -platform.win32_ver derives the windows version from -sys.getwindowsversion().platform_version which in turn derives the version -from kernel32.dll (which can be of a different version than Windows itself). -Therefore change the platform.win32_ver to determine the version using the -platform module's _syscmd_ver private function to return an accurate -version. diff --git a/Misc/NEWS.d/next/Library/2021-04-22-04-12-13.bpo-43817.FQ-XlH.rst b/Misc/NEWS.d/next/Library/2021-04-22-04-12-13.bpo-43817.FQ-XlH.rst deleted file mode 100644 index 36a6018bab2531..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-22-04-12-13.bpo-43817.FQ-XlH.rst +++ /dev/null @@ -1,11 +0,0 @@ -Add :func:`inspect.get_annotations`, which safely computes the annotations -defined on an object. It works around the quirks of accessing the -annotations from various types of objects, and makes very few assumptions -about the object passed in. :func:`inspect.get_annotations` can also -correctly un-stringize stringized annotations. - -:func:`inspect.signature`, :func:`inspect.from_callable`, and -:func:`inspect.from_function` now call :func:`inspect.get_annotations` -to retrieve annotations. This means :func:`inspect.signature` -and :func:`inspect.from_callable` can now un-stringize stringized -annotations, too. diff --git a/Misc/NEWS.d/next/Library/2021-04-22-22-39-58.bpo-43607.7IYDkG.rst b/Misc/NEWS.d/next/Library/2021-04-22-22-39-58.bpo-43607.7IYDkG.rst deleted file mode 100644 index fa62846acaa984..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-22-22-39-58.bpo-43607.7IYDkG.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`urllib` can now convert Windows paths with ``\\?\`` prefixes into URL -paths. diff --git a/Misc/NEWS.d/next/Library/2021-04-23-11-54-38.bpo-43920.cJMQ2D.rst b/Misc/NEWS.d/next/Library/2021-04-23-11-54-38.bpo-43920.cJMQ2D.rst deleted file mode 100644 index 28ff0fb3afa9d3..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-23-11-54-38.bpo-43920.cJMQ2D.rst +++ /dev/null @@ -1,2 +0,0 @@ -OpenSSL 3.0.0: :meth:`~ssl.SSLContext.load_verify_locations` now returns a -consistent error message when cadata contains no valid certificate. diff --git a/Misc/NEWS.d/next/Library/2021-04-23-17-48-55.bpo-43926.HMUlGU.rst b/Misc/NEWS.d/next/Library/2021-04-23-17-48-55.bpo-43926.HMUlGU.rst deleted file mode 100644 index 45f29a84cd599f..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-23-17-48-55.bpo-43926.HMUlGU.rst +++ /dev/null @@ -1,4 +0,0 @@ -In ``importlib.metadata``, provide a uniform interface to ``Description``, -allow for any field to be encoded with multiline values, remove continuation -lines from multiline values, and add a ``.json`` property for easy access to -the PEP 566 JSON-compatible form. Sync with ``importlib_metadata 4.0``. diff --git a/Misc/NEWS.d/next/Library/2021-04-23-20-57-20.bpo-43907.3RJEjv.rst b/Misc/NEWS.d/next/Library/2021-04-23-20-57-20.bpo-43907.3RJEjv.rst deleted file mode 100644 index 7da3a1c3f76127..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-23-20-57-20.bpo-43907.3RJEjv.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix a bug in the pure-Python pickle implementation when using protocol 5, -where bytearray instances that occur several time in the pickled object -graph would incorrectly unpickle into repeated copies of the bytearray -object. diff --git a/Misc/NEWS.d/next/Library/2021-04-24-14-23-07.bpo-43930.R7ah0m.rst b/Misc/NEWS.d/next/Library/2021-04-24-14-23-07.bpo-43930.R7ah0m.rst deleted file mode 100644 index 7dac21f3d9b197..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-24-14-23-07.bpo-43930.R7ah0m.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 21.1 and setuptools to 56.0.0 \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-04-25-13-34-13.bpo-43937.isx95l.rst b/Misc/NEWS.d/next/Library/2021-04-25-13-34-13.bpo-43937.isx95l.rst deleted file mode 100644 index cb4d90b723d1fa..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-25-13-34-13.bpo-43937.isx95l.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the :mod:`turtle` module working with non-default root window. diff --git a/Misc/NEWS.d/next/Library/2021-04-26-17-47-48.bpo-41139.ROhn1k.rst b/Misc/NEWS.d/next/Library/2021-04-26-17-47-48.bpo-41139.ROhn1k.rst deleted file mode 100644 index 5df89298919236..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-26-17-47-48.bpo-41139.ROhn1k.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate undocumented ``cgi.log()`` API. diff --git a/Misc/NEWS.d/next/Library/2021-04-26-20-52-16.bpo-43945.NgERXO.rst b/Misc/NEWS.d/next/Library/2021-04-26-20-52-16.bpo-43945.NgERXO.rst deleted file mode 100644 index c01c200caa7801..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-26-20-52-16.bpo-43945.NgERXO.rst +++ /dev/null @@ -1,2 +0,0 @@ -[Enum] Deprecate non-standard mixin format() behavior: in 3.12 the enum -member, not the member's value, will be used for format() calls. diff --git a/Misc/NEWS.d/next/Library/2021-04-26-23-39-47.bpo-42904.ejjsyR.rst b/Misc/NEWS.d/next/Library/2021-04-26-23-39-47.bpo-42904.ejjsyR.rst deleted file mode 100644 index 632941ac362676..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-26-23-39-47.bpo-42904.ejjsyR.rst +++ /dev/null @@ -1,5 +0,0 @@ -For backwards compatbility with previous minor versions of Python, -if :func:`typing.get_type_hints` receives no namespace dictionary arguments, -:func:`typing.get_type_hints` will search through the global then local -namespaces during evaluation of stringized type annotations -(string forward references) inside a class. diff --git a/Misc/NEWS.d/next/Library/2021-04-27-12-13-51.bpo-43957.6EaPD-.rst b/Misc/NEWS.d/next/Library/2021-04-27-12-13-51.bpo-43957.6EaPD-.rst deleted file mode 100644 index c6d1ddef64ca30..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-27-12-13-51.bpo-43957.6EaPD-.rst +++ /dev/null @@ -1,4 +0,0 @@ -[Enum] Deprecate ``TypeError`` when non-member is used in a containment -check; In 3.12 ``True`` or ``False`` will be returned instead, and -containment will return ``True`` if the value is either a member of that -enum or one of its members' value. diff --git a/Misc/NEWS.d/next/Library/2021-04-30-19-23-45.bpo-43993.T7_yoq.rst b/Misc/NEWS.d/next/Library/2021-04-30-19-23-45.bpo-43993.T7_yoq.rst deleted file mode 100644 index c9d2c458eee75c..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-04-30-19-23-45.bpo-43993.T7_yoq.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 21.1.1. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-05-01-01-36-51.bpo-43979.43oJ9L.rst b/Misc/NEWS.d/next/Library/2021-05-01-01-36-51.bpo-43979.43oJ9L.rst deleted file mode 100644 index d5d1caa3e56827..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-05-01-01-36-51.bpo-43979.43oJ9L.rst +++ /dev/null @@ -1,2 +0,0 @@ -Removed an unnecessary list comprehension before looping from -:func:`urllib.parse.parse_qsl`. Patch by Christoph Zwerschke and Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2021-05-01-22-59-20.bpo-43733.gJWwEQ.rst b/Misc/NEWS.d/next/Library/2021-05-01-22-59-20.bpo-43733.gJWwEQ.rst deleted file mode 100644 index 5ecd928b118347..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-05-01-22-59-20.bpo-43733.gJWwEQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Change :class:`netrc.netrc` to use UTF-8 encoding before using locale -encoding. diff --git a/Misc/NEWS.d/next/Library/2021-05-02-19-17-20.bpo-25478.AwlwdA.rst b/Misc/NEWS.d/next/Library/2021-05-02-19-17-20.bpo-25478.AwlwdA.rst deleted file mode 100644 index 81d2724726dd06..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-05-02-19-17-20.bpo-25478.AwlwdA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a *total()* method to collections.Counter() to compute the sum of the -counts. diff --git a/Misc/NEWS.d/next/Library/2021-05-03-03-03-49.bpo-44015.V5936k.rst b/Misc/NEWS.d/next/Library/2021-05-03-03-03-49.bpo-44015.V5936k.rst deleted file mode 100644 index 4c4f543fa0c2e3..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-05-03-03-03-49.bpo-44015.V5936k.rst +++ /dev/null @@ -1 +0,0 @@ -In @dataclass(), raise a TypeError if KW_ONLY is specified more than once. diff --git a/Misc/NEWS.d/next/Library/2021-07-25-08-17-55.bpo-42378.WIhUZK.rst b/Misc/NEWS.d/next/Library/2021-07-25-08-17-55.bpo-42378.WIhUZK.rst new file mode 100644 index 00000000000000..90c3961dc87d8b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-07-25-08-17-55.bpo-42378.WIhUZK.rst @@ -0,0 +1,4 @@ +Fixes the issue with log file being overwritten when +:class:`logging.FileHandler` is used in :mod:`atexit` with *filemode* set to +``'w'``. Note this will cause the message in *atexit* not being logged if +the log stream is already closed due to shutdown of logging. diff --git a/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst new file mode 100644 index 00000000000000..bfea8d4fca0e0a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-11-30-13-52-02.bpo-13236.FmJIkO.rst @@ -0,0 +1,2 @@ +:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush +now the output stream more often. diff --git a/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst new file mode 100644 index 00000000000000..e5201b0dfde2d3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-07-21-55-22.bpo-45755.bRqKGa.rst @@ -0,0 +1,3 @@ +:mod:`typing` generic aliases now reveal the class attributes of the +original generic class when passed to ``dir()``. This was the behavior up to +Python 3.6, but was changed in 3.7-3.9. diff --git a/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst new file mode 100644 index 00000000000000..6ff76f58779d2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-09-00-44-42.bpo-46018.hkTI7v.rst @@ -0,0 +1 @@ +Ensure that :func:`math.expm1` does not raise on underflow. diff --git a/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst new file mode 100644 index 00000000000000..97a553d7ba29fb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-15-45-07.bpo-46032.HmciLT.rst @@ -0,0 +1,5 @@ +The ``registry()`` method of :func:`functools.singledispatch` functions +checks now the first argument or the first parameter annotation and raises a +TypeError if it is not supported. Previously unsupported "types" were +ignored (e.g. ``typing.List[int]``) or caused an error at calling time (e.g. +``list[int]``). diff --git a/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst new file mode 100644 index 00000000000000..c68e98ff0630b1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-11-22-51-30.bpo-27718.MgQiGl.rst @@ -0,0 +1,2 @@ +Fix help for the :mod:`signal` module. Some functions (e.g. ``signal()`` and +``getsignal()``) were omitted. diff --git a/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst new file mode 100644 index 00000000000000..379dbb55c7ca80 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-14-13-18-45.bpo-26952.hjhISq.rst @@ -0,0 +1 @@ +:mod:`argparse` raises :exc:`ValueError` with clear message when trying to render usage for an empty mutually-exclusive group. Previously it raised a cryptic :exc:`IndexError`. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst new file mode 100644 index 00000000000000..145edccb2e7a54 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-14-30-36.bpo-46105.pprB1K.rst @@ -0,0 +1,2 @@ +Honor spec when generating requirement specs with urls and extras +(importlib_metadata 4.8.3). diff --git a/Misc/NEWS.d/next/Library/2021-12-17-12-06-40.bpo-20369.zzLuBz.rst b/Misc/NEWS.d/next/Library/2021-12-17-12-06-40.bpo-20369.zzLuBz.rst new file mode 100644 index 00000000000000..cc5cd0067e61fe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-17-12-06-40.bpo-20369.zzLuBz.rst @@ -0,0 +1 @@ +:func:`concurrent.futures.wait` no longer blocks forever when given duplicate Futures. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-01-03-12-59-20.bpo-46239.ySVSEy.rst b/Misc/NEWS.d/next/Library/2022-01-03-12-59-20.bpo-46239.ySVSEy.rst new file mode 100644 index 00000000000000..202febf84fd109 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-03-12-59-20.bpo-46239.ySVSEy.rst @@ -0,0 +1,2 @@ +Improve error message when importing :mod:`asyncio.windows_events` on +non-Windows. diff --git a/Misc/NEWS.d/next/Library/2022-01-06-13-38-00.bpo-46278.wILA80.rst b/Misc/NEWS.d/next/Library/2022-01-06-13-38-00.bpo-46278.wILA80.rst new file mode 100644 index 00000000000000..40849044cf1c8c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-06-13-38-00.bpo-46278.wILA80.rst @@ -0,0 +1,2 @@ +Reflect ``context`` argument in ``AbstractEventLoop.call_*()`` methods. Loop +implementations already support it. diff --git a/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst new file mode 100644 index 00000000000000..0fedc9dfb8fb1b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst @@ -0,0 +1,2 @@ +Fix possible segfault when importing the :mod:`asyncio` module from +different sub-interpreters in parallel. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2022-01-07-15-20-19.bpo-40479.EKfr3F.rst b/Misc/NEWS.d/next/Library/2022-01-07-15-20-19.bpo-40479.EKfr3F.rst new file mode 100644 index 00000000000000..af72923bbd7595 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-07-15-20-19.bpo-40479.EKfr3F.rst @@ -0,0 +1,2 @@ +Fix :mod:`hashlib` *usedforsecurity* option to work correctly with OpenSSL +3.0.0 in FIPS mode. diff --git a/Misc/NEWS.d/next/Security/2020-07-04-22-14-46.bpo-37363.NDjHNw.rst b/Misc/NEWS.d/next/Security/2020-07-04-22-14-46.bpo-37363.NDjHNw.rst deleted file mode 100644 index 539084836dc4e5..00000000000000 --- a/Misc/NEWS.d/next/Security/2020-07-04-22-14-46.bpo-37363.NDjHNw.rst +++ /dev/null @@ -1 +0,0 @@ -Add audit events to the :mod:`http.client` module. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst b/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst deleted file mode 100644 index d01c0c3073a503..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst +++ /dev/null @@ -1 +0,0 @@ -Audit hooks are now fired for frame.f_code, traceback.tb_frame, and generator code/frame attribute access. diff --git a/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst b/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst deleted file mode 100644 index 1c9f727e965fb8..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-01-31-05-28-14.bpo-43075.DoAXqO.rst +++ /dev/null @@ -1 +0,0 @@ -Fix Regular Expression Denial of Service (ReDoS) vulnerability in :class:`urllib.request.AbstractBasicAuthHandler`. The ReDoS-vulnerable regex has quadratic worst-case complexity and it allows cause a denial of service when identifying crafted invalid RFCs. This ReDoS issue is on the client side and needs remote attackers to control the HTTP server. diff --git a/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst b/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst deleted file mode 100644 index f956cde948ec57..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst +++ /dev/null @@ -1,6 +0,0 @@ -:mod:`ipaddress` module no longer accepts any leading zeros in IPv4 address -strings. Leading zeros are ambiguous and interpreted as octal notation by -some libraries. For example the legacy function :func:`socket.inet_aton` -treats leading zeros as octal notatation. glibc implementation of modern -:func:`~socket.inet_pton` does not accept any leading zeros. For a while -the :mod:`ipaddress` module used to accept ambiguous leading zeros. diff --git a/Misc/NEWS.d/next/Security/2021-04-06-18-07-48.bpo-43756.DLBNqQ.rst b/Misc/NEWS.d/next/Security/2021-04-06-18-07-48.bpo-43756.DLBNqQ.rst deleted file mode 100644 index e05fef2d5524ff..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-04-06-18-07-48.bpo-43756.DLBNqQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add new audit event ``glob.glob/2`` to incorporate the new *root_dir* and -*dir_fd* arguments added to :func:`glob.glob` and :func:`glob.iglob`. diff --git a/Misc/NEWS.d/next/Security/2021-04-07-12-57-41.bpo-43762.7lMtpT.rst b/Misc/NEWS.d/next/Security/2021-04-07-12-57-41.bpo-43762.7lMtpT.rst deleted file mode 100644 index aa392656807e11..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-04-07-12-57-41.bpo-43762.7lMtpT.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add audit events for :func:`sqlite3.connect/handle`, -:meth:`sqlite3.Connection.enable_load_extension`, and -:meth:`sqlite3.Connection.load_extension`. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Security/2021-04-18-00-56-44.bpo-43362.__5aiP.rst b/Misc/NEWS.d/next/Security/2021-04-18-00-56-44.bpo-43362.__5aiP.rst deleted file mode 100644 index 713a683bc8eb34..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-04-18-00-56-44.bpo-43362.__5aiP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix invalid free in _sha3 module. The issue was introduced in 3.10.0a1. -Python 3.9 and earlier are not affected. diff --git a/Misc/NEWS.d/next/Security/2021-04-21-22-53-31.bpo-43472.gjLBTb.rst b/Misc/NEWS.d/next/Security/2021-04-21-22-53-31.bpo-43472.gjLBTb.rst deleted file mode 100644 index e38dc169def96e..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-04-21-22-53-31.bpo-43472.gjLBTb.rst +++ /dev/null @@ -1,3 +0,0 @@ -Ensures interpreter-level audit hooks receive the -``cpython.PyInterpreterState_New`` event when called through the -``_xxsubinterpreters`` module. diff --git a/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst b/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst deleted file mode 100644 index a326d079dff4a4..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst +++ /dev/null @@ -1,6 +0,0 @@ -The presence of newline or tab characters in parts of a URL could allow -some forms of attacks. - -Following the controlling specification for URLs defined by WHATWG -:func:`urllib.parse` now removes ASCII newlines and tabs from URLs, -preventing such attacks. diff --git a/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst b/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst deleted file mode 100644 index 6a40346128e187..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst +++ /dev/null @@ -1,5 +0,0 @@ -The :mod:`ssl` module sets more secure cipher suites defaults. Ciphers -without forward secrecy and with SHA-1 MAC are disabled by default. Security -level 2 prohibits weak RSA, DH, and ECC keys with less than 112 bits of -security. :class:`~ssl.SSLContext` defaults to minimum protocol version TLS -1.2. Settings are based on Hynek Schlawack's research. diff --git a/Misc/NEWS.d/next/Security/2021-05-02-17-50-23.bpo-43434.cy7xz6.rst b/Misc/NEWS.d/next/Security/2021-05-02-17-50-23.bpo-43434.cy7xz6.rst deleted file mode 100644 index b5a3f8d7587498..00000000000000 --- a/Misc/NEWS.d/next/Security/2021-05-02-17-50-23.bpo-43434.cy7xz6.rst +++ /dev/null @@ -1,4 +0,0 @@ -Creating :class:`sqlite3.Connection` objects now also produces -``sqlite3.connect`` and ``sqlite3.connect/handle`` :ref:`auditing events -`. Previously these events were only produced by -:func:`sqlite3.connect` calls. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Tests/2021-04-09-15-10-38.bpo-43791.4KxiXK.rst b/Misc/NEWS.d/next/Tests/2021-04-09-15-10-38.bpo-43791.4KxiXK.rst deleted file mode 100644 index 964ae5abb3d880..00000000000000 --- a/Misc/NEWS.d/next/Tests/2021-04-09-15-10-38.bpo-43791.4KxiXK.rst +++ /dev/null @@ -1,2 +0,0 @@ -OpenSSL 3.0.0: Disable testing of legacy protocols TLS 1.0 and 1.1. Tests -are failing with TLSV1_ALERT_INTERNAL_ERROR. diff --git a/Misc/NEWS.d/next/Tests/2021-04-12-11-14-28.bpo-43811.vGNbnD.rst b/Misc/NEWS.d/next/Tests/2021-04-12-11-14-28.bpo-43811.vGNbnD.rst deleted file mode 100644 index d4c7066013332c..00000000000000 --- a/Misc/NEWS.d/next/Tests/2021-04-12-11-14-28.bpo-43811.vGNbnD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Tests multiple OpenSSL versions on GitHub Actions. Use ccache to speed up -testing. diff --git a/Misc/NEWS.d/next/Tests/2021-04-14-13-22-44.bpo-43843.ruIQKD.rst b/Misc/NEWS.d/next/Tests/2021-04-14-13-22-44.bpo-43843.ruIQKD.rst deleted file mode 100644 index d1085ec2395b80..00000000000000 --- a/Misc/NEWS.d/next/Tests/2021-04-14-13-22-44.bpo-43843.ruIQKD.rst +++ /dev/null @@ -1,5 +0,0 @@ -:mod:`test.libregrtest` now marks a test as ENV_CHANGED (altered the execution -environment) if a thread raises an exception but does not catch it. It sets a -hook on :func:`threading.excepthook`. Use ``--fail-env-changed`` option to mark -the test as failed. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-04-16-14-07-40.bpo-43842.w60GAH.rst b/Misc/NEWS.d/next/Tests/2021-04-16-14-07-40.bpo-43842.w60GAH.rst deleted file mode 100644 index 5b4a120eb86371..00000000000000 --- a/Misc/NEWS.d/next/Tests/2021-04-16-14-07-40.bpo-43842.w60GAH.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix a race condition in the SMTP test of test_logging. Don't close a file -descriptor (socket) from a different thread while asyncore.loop() is polling -the file descriptor. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-04-28-13-21-52.bpo-43961.gNchls.rst b/Misc/NEWS.d/next/Tests/2021-04-28-13-21-52.bpo-43961.gNchls.rst deleted file mode 100644 index e56572f5170998..00000000000000 --- a/Misc/NEWS.d/next/Tests/2021-04-28-13-21-52.bpo-43961.gNchls.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix test_logging.test_namer_rotator_inheritance() on Windows: use -:func:`os.replace` rather than :func:`os.rename`. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst new file mode 100644 index 00000000000000..6878cea0323876 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-17-14-46-19.bpo-46114.9iyZ_9.rst @@ -0,0 +1 @@ +Fix test case for OpenSSL 3.0.1 version. OpenSSL 3.0 uses ``0xMNN00PP0L``. diff --git a/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst new file mode 100644 index 00000000000000..b06436a4c84608 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-19-12-20-57.bpo-46129.I3MunH.rst @@ -0,0 +1,2 @@ +Rewrite ``asyncio.locks`` tests with +:class:`unittest.IsolatedAsyncioTestCase` usage. diff --git a/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst new file mode 100644 index 00000000000000..8ef9cd9b4a5948 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2021-12-23-13-42-15.bpo-46150.RhtADs.rst @@ -0,0 +1,2 @@ +Now ``fakename`` in ``test_pathlib.PosixPathTest.test_expanduser`` is checked +to be non-existent. diff --git a/Misc/NEWS.d/next/Tests/2022-01-06-15-45-34.bpo-46263.bJXek6.rst b/Misc/NEWS.d/next/Tests/2022-01-06-15-45-34.bpo-46263.bJXek6.rst new file mode 100644 index 00000000000000..0334af4e3cbe8c --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-01-06-15-45-34.bpo-46263.bJXek6.rst @@ -0,0 +1,2 @@ +Fix test_capi on FreeBSD 14-dev: instruct jemalloc to not fill freed memory +with junk byte. diff --git a/Misc/NEWS.d/next/Tests/2022-01-07-14-06-12.bpo-46205.dnc2OC.rst b/Misc/NEWS.d/next/Tests/2022-01-07-14-06-12.bpo-46205.dnc2OC.rst new file mode 100644 index 00000000000000..7c6121fb162495 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-01-07-14-06-12.bpo-46205.dnc2OC.rst @@ -0,0 +1 @@ +Fix hang in runtest_mp due to race condition diff --git a/Misc/NEWS.d/next/Windows/2017-12-16-12-23-51.bpo-30555.3ybjly.rst b/Misc/NEWS.d/next/Windows/2017-12-16-12-23-51.bpo-30555.3ybjly.rst deleted file mode 100644 index 2b0c2219539e9e..00000000000000 --- a/Misc/NEWS.d/next/Windows/2017-12-16-12-23-51.bpo-30555.3ybjly.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``WindowsConsoleIO`` errors in the presence of fd redirection. Patch by -Segev Finer. diff --git a/Misc/NEWS.d/next/Windows/2021-03-15-11-34-33.bpo-43492.AsYnVX.rst b/Misc/NEWS.d/next/Windows/2021-03-15-11-34-33.bpo-43492.AsYnVX.rst deleted file mode 100644 index 93da1b6dec8e3b..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-03-15-11-34-33.bpo-43492.AsYnVX.rst +++ /dev/null @@ -1 +0,0 @@ -Upgrade Windows installer to use SQLite 3.35.5. diff --git a/Misc/NEWS.d/next/Windows/2021-04-03-18-54-31.bpo-43652.gNmfVN.rst b/Misc/NEWS.d/next/Windows/2021-04-03-18-54-31.bpo-43652.gNmfVN.rst deleted file mode 100644 index 0ef44e28a9a1df..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-03-18-54-31.bpo-43652.gNmfVN.rst +++ /dev/null @@ -1 +0,0 @@ -Update Tcl and Tk to 8.6.11 in Windows installer. diff --git a/Misc/NEWS.d/next/Windows/2021-04-06-12-27-33.bpo-43745.rdKNda.rst b/Misc/NEWS.d/next/Windows/2021-04-06-12-27-33.bpo-43745.rdKNda.rst deleted file mode 100644 index 8ec498d11ea938..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-06-12-27-33.bpo-43745.rdKNda.rst +++ /dev/null @@ -1,2 +0,0 @@ -Actually updates Windows release to OpenSSL 1.1.1k. Earlier releases were -mislabelled and actually included 1.1.1i again. diff --git a/Misc/NEWS.d/next/Windows/2021-04-20-23-07-22.bpo-40432.9OFpoq.rst b/Misc/NEWS.d/next/Windows/2021-04-20-23-07-22.bpo-40432.9OFpoq.rst deleted file mode 100644 index 6f8ce00bf99ecc..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-20-23-07-22.bpo-40432.9OFpoq.rst +++ /dev/null @@ -1,3 +0,0 @@ -Updated pegen regeneration script on Windows to find and use Python 3.8 or -higher. Prior to this, pegen regeneration already required 3.8 or higher, -but the script may have used lower versions of Python. diff --git a/Misc/NEWS.d/next/Windows/2021-04-21-23-37-34.bpo-26227.QMY_eA.rst b/Misc/NEWS.d/next/Windows/2021-04-21-23-37-34.bpo-26227.QMY_eA.rst deleted file mode 100644 index d6826fb39706bd..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-21-23-37-34.bpo-26227.QMY_eA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed decoding of host names in :func:`socket.gethostbyaddr` and -:func:`socket.gethostbyname_ex`. diff --git a/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst b/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst deleted file mode 100644 index 072a96989c3d04..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-22-19-49-20.bpo-38822.jgdPmq.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :func:`os.stat` failing on inaccessible directories with a trailing -slash, rather than falling back to the parent directory's metadata. This -implicitly affected :func:`os.path.exists` and :func:`os.path.isdir`. diff --git a/Misc/NEWS.d/next/Windows/2021-04-22-20-39-49.bpo-43538.F0Cg6X.rst b/Misc/NEWS.d/next/Windows/2021-04-22-20-39-49.bpo-43538.F0Cg6X.rst deleted file mode 100644 index af41b3ceacb648..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-22-20-39-49.bpo-43538.F0Cg6X.rst +++ /dev/null @@ -1,2 +0,0 @@ -Avoid raising errors from :meth:`pathlib.Path.exists()` when passed an -invalid filename. diff --git a/Misc/NEWS.d/next/Windows/2021-04-22-21-37-41.bpo-35306.10kSR-.rst b/Misc/NEWS.d/next/Windows/2021-04-22-21-37-41.bpo-35306.10kSR-.rst deleted file mode 100644 index f1ee2def320070..00000000000000 --- a/Misc/NEWS.d/next/Windows/2021-04-22-21-37-41.bpo-35306.10kSR-.rst +++ /dev/null @@ -1 +0,0 @@ -Adds additional arguments to :func:`os.startfile` function. diff --git a/Misc/NEWS.d/next/macOS/2020-11-01-17-37-16.bpo-42235.A97_BN.rst b/Misc/NEWS.d/next/macOS/2020-11-01-17-37-16.bpo-42235.A97_BN.rst deleted file mode 100644 index eef4fcdaae3cfc..00000000000000 --- a/Misc/NEWS.d/next/macOS/2020-11-01-17-37-16.bpo-42235.A97_BN.rst +++ /dev/null @@ -1,2 +0,0 @@ -``Mac/BuildScript/build-installer.py`` will now use "--enable-optimizations" -and ``--with-lto`` when building on macOS 10.15 or later. diff --git a/Misc/NEWS.d/next/macOS/2021-03-15-11-32-23.bpo-43492.1ZRcV9.rst b/Misc/NEWS.d/next/macOS/2021-03-15-11-32-23.bpo-43492.1ZRcV9.rst deleted file mode 100644 index 39f15370688161..00000000000000 --- a/Misc/NEWS.d/next/macOS/2021-03-15-11-32-23.bpo-43492.1ZRcV9.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer to use SQLite 3.35.4. diff --git a/Misc/NEWS.d/next/macOS/2021-04-15-01-20-45.bpo-43851.sDI60Y.rst b/Misc/NEWS.d/next/macOS/2021-04-15-01-20-45.bpo-43851.sDI60Y.rst deleted file mode 100644 index 0febfb02315e84..00000000000000 --- a/Misc/NEWS.d/next/macOS/2021-04-15-01-20-45.bpo-43851.sDI60Y.rst +++ /dev/null @@ -1 +0,0 @@ -Build SQLite with ``SQLITE_OMIT_AUTOINIT`` on macOS. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/macOS/2021-05-02-03-45-30.bpo-44009.uvhmlh.rst b/Misc/NEWS.d/next/macOS/2021-05-02-03-45-30.bpo-44009.uvhmlh.rst deleted file mode 100644 index f9f11c8ae6a793..00000000000000 --- a/Misc/NEWS.d/next/macOS/2021-05-02-03-45-30.bpo-44009.uvhmlh.rst +++ /dev/null @@ -1,4 +0,0 @@ -Provide "python3.x-intel64" executable to allow reliably forcing macOS -universal2 framework builds to run under Rosetta 2 Intel-64 emulation on -Apple Silicon Macs. This can be useful for testing or when universal2 -wheels are not yet available. diff --git a/Misc/NEWS.d/next/macOS/2021-05-02-19-50-52.bpo-43568.AeLNBd.rst b/Misc/NEWS.d/next/macOS/2021-05-02-19-50-52.bpo-43568.AeLNBd.rst deleted file mode 100644 index 3bc9b0b55bbd35..00000000000000 --- a/Misc/NEWS.d/next/macOS/2021-05-02-19-50-52.bpo-43568.AeLNBd.rst +++ /dev/null @@ -1 +0,0 @@ -Drop support for MACOSX_DEPLOYMENT_TARGET < 10.3 diff --git a/Misc/NEWS.d/next/macOS/2021-05-02-21-03-27.bpo-42119.Y7BSX_.rst b/Misc/NEWS.d/next/macOS/2021-05-02-21-03-27.bpo-42119.Y7BSX_.rst deleted file mode 100644 index 7dd67a527eb009..00000000000000 --- a/Misc/NEWS.d/next/macOS/2021-05-02-21-03-27.bpo-42119.Y7BSX_.rst +++ /dev/null @@ -1,7 +0,0 @@ -Fix check for macOS SDK paths when building Python. Narrow search to match -contents of SDKs, namely only files in ``/System/Library``, -``/System/IOSSupport``, and ``/usr`` other than ``/usr/local``. Previously, -anything under ``/System`` was assumed to be in an SDK which causes problems -with the new file system layout in 10.15+ where user file systems may appear -to be mounted under ``/System``. Paths in ``/Library`` were also -incorrectly treated as SDK locations. diff --git a/Misc/NEWS.d/next/macOS/2022-01-02-21-56-53.bpo-40477.W3nnM6.rst b/Misc/NEWS.d/next/macOS/2022-01-02-21-56-53.bpo-40477.W3nnM6.rst new file mode 100644 index 00000000000000..fc953b85dcc2a5 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2022-01-02-21-56-53.bpo-40477.W3nnM6.rst @@ -0,0 +1,2 @@ +The Python Launcher app for macOS now properly launches scripts and, if +necessary, the Terminal app when running on recent macOS releases. diff --git a/Misc/README.valgrind b/Misc/README.valgrind index b483b2ea60a4d2..ee9bfdf859d7f4 100644 --- a/Misc/README.valgrind +++ b/Misc/README.valgrind @@ -12,12 +12,9 @@ can be used to force the usage of the malloc() allocator of the C library. If you don't want to read about the details of using Valgrind, there are still two things you must do to suppress the warnings. First, you must use a suppressions file. One is supplied in -Misc/valgrind-python.supp. Second, you must do one of the following: - - * Uncomment Py_USING_MEMORY_DEBUGGER in Objects/obmalloc.c, - then rebuild Python - * Uncomment the lines in Misc/valgrind-python.supp that - suppress the warnings for PyObject_Free and PyObject_Realloc +Misc/valgrind-python.supp. Second, you must uncomment the lines in +Misc/valgrind-python.supp that suppress the warnings for PyObject_Free and +PyObject_Realloc. If you want to use Valgrind more effectively and catch even more memory leaks, you will need to configure python --without-pymalloc. diff --git a/Misc/python.man b/Misc/python.man index 10cb807c38a02c..45a49271d4dfe3 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -550,6 +550,7 @@ if Python was configured with the \fB\--with-pydebug\fP build option. .IP PYTHONTHREADDEBUG If this environment variable is set, Python will print threading debug info. +The feature is deprecated in Python 3.10 and will be removed in Python 3.12. .IP PYTHONDUMPREFS If this environment variable is set, Python will dump objects and reference counts still alive after shutting down the interpreter. diff --git a/Misc/stable_abi.txt b/Misc/stable_abi.txt index 2a802bd5f4b831..4a2ee18e8e9750 100644 --- a/Misc/stable_abi.txt +++ b/Misc/stable_abi.txt @@ -38,12 +38,10 @@ struct PyThreadState added 3.2 struct PyInterpreterState added 3.2 -struct _frame +struct PyFrameObject added 3.2 struct symtable added 3.2 -struct _node - added 3.2 struct PyWeakReference added 3.2 struct PyLongObject @@ -287,7 +285,7 @@ macro Py_UNBLOCK_THREADS macro Py_END_ALLOW_THREADS added 3.2 -# The following were added in PC/python3.def in the intial stable ABI commit, +# The following were added in PC/python3.def in the initial stable ABI commit, # 4d0d471a8031de90a2b1ce99c4ac4780e60b3bc9, # and later amendments in 3.2: # 0d012f284be829c6217f60523db0e1671b7db9d9 @@ -1650,6 +1648,17 @@ function _Py_VaBuildValue_SizeT added 3.2 abi_only +# Old buffer protocol support (deprecated) + +function PyObject_AsCharBuffer + added 3.2 +function PyObject_AsReadBuffer + added 3.2 +function PyObject_AsWriteBuffer + added 3.2 +function PyObject_CheckReadBuffer + added 3.2 + # Flags are implicitly part of the ABI: const Py_TPFLAGS_DEFAULT @@ -2045,7 +2054,7 @@ function Py_LeaveRecursiveCall added 3.9 function Py_GenericAlias added 3.9 -function Py_GenericAliasType +data Py_GenericAliasType added 3.9 function PyCMethod_New added 3.9 # Windows: 3.10 & 3.9.2 -- https://bugs.python.org/issue43155 @@ -2079,8 +2088,6 @@ function PyType_GetModule added 3.10 function PyType_GetModuleState added 3.10 -function Py_FrozenMain - added 3.10 function PyFrame_GetLineNumber added 3.10 function PyFrame_GetCode @@ -2097,7 +2104,7 @@ function PyModule_AddObjectRef added 3.10 data Py_FileSystemDefaultEncodeErrors added 3.10 -data PyCodec_Unregister +function PyCodec_Unregister added 3.10 function PyErr_SetInterruptEx added 3.10 @@ -2115,9 +2122,9 @@ function _Py_IncRef function _Py_DecRef added 3.10 abi_only -function PyAiter_Check +function PyAIter_Check added 3.10 -function PyObject_GetAiter +function PyObject_GetAIter added 3.10 data PyExc_EncodingWarning added 3.10 diff --git a/Modules/_abc.c b/Modules/_abc.c index 7720d4051fe9eb..8aa68359039e7d 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -481,6 +481,32 @@ _abc__abc_init(PyObject *module, PyObject *self) Py_RETURN_NONE; } +static void +set_collection_flag_recursive(PyTypeObject *child, unsigned long flag) +{ + assert(flag == Py_TPFLAGS_MAPPING || flag == Py_TPFLAGS_SEQUENCE); + if (PyType_HasFeature(child, Py_TPFLAGS_IMMUTABLETYPE) || + (child->tp_flags & COLLECTION_FLAGS) == flag) + { + return; + } + child->tp_flags &= ~COLLECTION_FLAGS; + child->tp_flags |= flag; + PyObject *grandchildren = child->tp_subclasses; + if (grandchildren == NULL) { + return; + } + assert(PyDict_CheckExact(grandchildren)); + Py_ssize_t i = 0; + while (PyDict_Next(grandchildren, &i, NULL, &grandchildren)) { + assert(PyWeakref_CheckRef(grandchildren)); + PyObject *grandchild = PyWeakref_GET_OBJECT(grandchildren); + if (PyType_Check(grandchild)) { + set_collection_flag_recursive((PyTypeObject *)grandchild, flag); + } + } +} + /*[clinic input] _abc._abc_register @@ -532,12 +558,11 @@ _abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) get_abc_state(module)->abc_invalidation_counter++; /* Set Py_TPFLAGS_SEQUENCE or Py_TPFLAGS_MAPPING flag */ - if (PyType_Check(self) && - !PyType_HasFeature((PyTypeObject *)subclass, Py_TPFLAGS_IMMUTABLETYPE) && - ((PyTypeObject *)self)->tp_flags & COLLECTION_FLAGS) - { - ((PyTypeObject *)subclass)->tp_flags &= ~COLLECTION_FLAGS; - ((PyTypeObject *)subclass)->tp_flags |= (((PyTypeObject *)self)->tp_flags & COLLECTION_FLAGS); + if (PyType_Check(self)) { + unsigned long collection_flag = ((PyTypeObject *)self)->tp_flags & COLLECTION_FLAGS; + if (collection_flag) { + set_collection_flag_recursive((PyTypeObject *)subclass, collection_flag); + } } Py_INCREF(subclass); return subclass; diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index a4d5d4551e9b0a..befec9a8342ef4 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1764,8 +1764,7 @@ static PyTypeObject FutureIterType = { .tp_dealloc = (destructor)FutureIter_dealloc, .tp_as_async = &FutureIterType_as_async, .tp_getattro = PyObject_GenericGetAttr, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .tp_traverse = (traverseproc)FutureIter_traverse, .tp_iter = PyObject_SelfIter, .tp_iternext = (iternextfunc)FutureIter_iternext, @@ -3240,6 +3239,9 @@ new_running_loop_holder(PyObject *loop) static void PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl) { + if (cached_running_holder == (PyObject *)rl) { + cached_running_holder = NULL; + } Py_CLEAR(rl->rl_loop); PyObject_Free(rl); } @@ -3307,17 +3309,14 @@ static int module_init(void) { PyObject *module = NULL; + if (module_initialized) { + return 0; + } asyncio_mod = PyImport_ImportModule("asyncio"); if (asyncio_mod == NULL) { goto fail; } - if (module_initialized != 0) { - return 0; - } - else { - module_initialized = 1; - } current_tasks = PyDict_New(); if (current_tasks == NULL) { @@ -3378,6 +3377,7 @@ module_init(void) goto fail; } + module_initialized = 1; Py_DECREF(module); return 0; diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c index 2d7c15bc1744b6..26c4b9bfb26b22 100644 --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -73,8 +73,8 @@ _bisect.bisect_right -> Py_ssize_t Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in -a[i:] have e > x. So if x already appears in the list, i points just -beyond the rightmost x already there +a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will +insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -83,7 +83,7 @@ slice of a to be searched. static Py_ssize_t _bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, Py_ssize_t lo, Py_ssize_t hi, PyObject *key) -/*[clinic end generated code: output=3a4bc09cc7c8a73d input=1313e9ca20c8bc3c]*/ +/*[clinic end generated code: output=3a4bc09cc7c8a73d input=40fcc5afa06ae593]*/ { return internal_bisect_right(a, x, lo, hi, key); } @@ -199,8 +199,8 @@ _bisect.bisect_left -> Py_ssize_t Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in -a[i:] have e >= x. So if x already appears in the list, i points just -before the leftmost x already there. +a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will +insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -209,7 +209,7 @@ slice of a to be searched. static Py_ssize_t _bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, Py_ssize_t lo, Py_ssize_t hi, PyObject *key) -/*[clinic end generated code: output=70749d6e5cae9284 input=3cbeec690f2f6c6e]*/ +/*[clinic end generated code: output=70749d6e5cae9284 input=90dd35b50ceb05e3]*/ { return internal_bisect_left(a, x, lo, hi, key); } @@ -240,7 +240,7 @@ _bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, { PyObject *result, *key_x; Py_ssize_t index; - + if (key == Py_None) { index = internal_bisect_left(a, x, lo, hi, key); } else { diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index d75bb32d2fc5eb..798e9efc628f05 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -422,7 +422,7 @@ static PyType_Spec bz2_compressor_type_spec = { // bz2_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .slots = bz2_compressor_type_slots, }; @@ -766,7 +766,7 @@ static PyType_Spec bz2_decompressor_type_spec = { // bz2_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .slots = bz2_decompressor_type_slots, }; diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c index 2e8cb97fe77c92..50afc097b35026 100644 --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -489,34 +489,40 @@ _codecs_utf_32_ex_decode_impl(PyObject *module, Py_buffer *data, _codecs.unicode_escape_decode data: Py_buffer(accept={str, buffer}) errors: str(accept={str, NoneType}) = None + final: bool(accept={int}) = True / [clinic start generated code]*/ static PyObject * _codecs_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, - const char *errors) -/*[clinic end generated code: output=3ca3c917176b82ab input=8328081a3a569bd6]*/ + const char *errors, int final) +/*[clinic end generated code: output=b284f97b12c635ee input=6154f039a9f7c639]*/ { - PyObject *decoded = PyUnicode_DecodeUnicodeEscape(data->buf, data->len, - errors); - return codec_tuple(decoded, data->len); + Py_ssize_t consumed = data->len; + PyObject *decoded = _PyUnicode_DecodeUnicodeEscapeStateful(data->buf, data->len, + errors, + final ? NULL : &consumed); + return codec_tuple(decoded, consumed); } /*[clinic input] _codecs.raw_unicode_escape_decode data: Py_buffer(accept={str, buffer}) errors: str(accept={str, NoneType}) = None + final: bool(accept={int}) = True / [clinic start generated code]*/ static PyObject * _codecs_raw_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, - const char *errors) -/*[clinic end generated code: output=c98eeb56028070a6 input=d2f5159ce3b3392f]*/ + const char *errors, int final) +/*[clinic end generated code: output=11dbd96301e2879e input=2d166191beb3235a]*/ { - PyObject *decoded = PyUnicode_DecodeRawUnicodeEscape(data->buf, data->len, - errors); - return codec_tuple(decoded, data->len); + Py_ssize_t consumed = data->len; + PyObject *decoded = _PyUnicode_DecodeRawUnicodeEscapeStateful(data->buf, data->len, + errors, + final ? NULL : &consumed); + return codec_tuple(decoded, consumed); } /*[clinic input] diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 9c8701af904ab9..eff03c789ede61 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2236,7 +2236,7 @@ defdict_init(PyObject *self, PyObject *args, PyObject *kwds) } PyDoc_STRVAR(defdict_doc, -"defaultdict(default_factory[, ...]) --> dict with default factory\n\ +"defaultdict(default_factory=None, /, [...]) --> dict with default factory\n\ \n\ The default factory is called without arguments to produce\n\ a new value when a key is not present, in __getitem__ only.\n\ diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c index a95f55a63c306e..72a4f44600d92c 100644 --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -4,6 +4,9 @@ #include "Python.h" #include +#ifdef HAVE_CRYPT_H +#include +#endif /* Module crypt */ diff --git a/Modules/_csv.c b/Modules/_csv.c index cade1ca9d47f06..72f0791a4398b6 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -229,21 +229,24 @@ _set_int(const char *name, int *target, PyObject *src, int dflt) } static int -_set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) +_set_char_or_none(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) { - if (src == NULL) + if (src == NULL) { *target = dflt; + } else { *target = '\0'; if (src != Py_None) { - Py_ssize_t len; if (!PyUnicode_Check(src)) { PyErr_Format(PyExc_TypeError, - "\"%s\" must be string, not %.200s", name, + "\"%s\" must be string or None, not %.200s", name, Py_TYPE(src)->tp_name); return -1; } - len = PyUnicode_GetLength(src); + Py_ssize_t len = PyUnicode_GetLength(src); + if (len < 0) { + return -1; + } if (len > 1) { PyErr_Format(PyExc_TypeError, "\"%s\" must be a 1-character string", @@ -251,8 +254,41 @@ _set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) return -1; } /* PyUnicode_READY() is called in PyUnicode_GetLength() */ - if (len > 0) + else { *target = PyUnicode_READ_CHAR(src, 0); + } + } + } + return 0; +} + +static int +_set_char(const char *name, Py_UCS4 *target, PyObject *src, Py_UCS4 dflt) +{ + if (src == NULL) { + *target = dflt; + } + else { + *target = '\0'; + if (!PyUnicode_Check(src)) { + PyErr_Format(PyExc_TypeError, + "\"%s\" must be string, not %.200s", name, + Py_TYPE(src)->tp_name); + return -1; + } + Py_ssize_t len = PyUnicode_GetLength(src); + if (len < 0) { + return -1; + } + if (len > 1) { + PyErr_Format(PyExc_TypeError, + "\"%s\" must be a 1-character string", + name); + return -1; + } + /* PyUnicode_READY() is called in PyUnicode_GetLength() */ + else { + *target = PyUnicode_READ_CHAR(src, 0); } } return 0; @@ -316,17 +352,12 @@ static void Dialect_dealloc(DialectObj *self) { PyTypeObject *tp = Py_TYPE(self); - Py_CLEAR(self->lineterminator); - tp->tp_free((PyObject *)self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + PyObject_GC_Del(self); Py_DECREF(tp); } -static void -Dialect_finalize(DialectObj *self) -{ - Py_CLEAR(self->lineterminator); -} - static char *dialect_kws[] = { "dialect", "delimiter", @@ -426,9 +457,14 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_XINCREF(skipinitialspace); Py_XINCREF(strict); if (dialect != NULL) { -#define DIALECT_GETATTR(v, n) \ - if (v == NULL) \ - v = PyObject_GetAttrString(dialect, n) +#define DIALECT_GETATTR(v, n) \ + do { \ + if (v == NULL) { \ + v = PyObject_GetAttrString(dialect, n); \ + if (v == NULL) \ + PyErr_Clear(); \ + } \ + } while (0) DIALECT_GETATTR(delimiter, "delimiter"); DIALECT_GETATTR(doublequote, "doublequote"); DIALECT_GETATTR(escapechar, "escapechar"); @@ -437,7 +473,6 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) DIALECT_GETATTR(quoting, "quoting"); DIALECT_GETATTR(skipinitialspace, "skipinitialspace"); DIALECT_GETATTR(strict, "strict"); - PyErr_Clear(); } /* check types and convert to C values */ @@ -446,9 +481,9 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto err DIASET(_set_char, "delimiter", &self->delimiter, delimiter, ','); DIASET(_set_bool, "doublequote", &self->doublequote, doublequote, true); - DIASET(_set_char, "escapechar", &self->escapechar, escapechar, 0); + DIASET(_set_char_or_none, "escapechar", &self->escapechar, escapechar, 0); DIASET(_set_str, "lineterminator", &self->lineterminator, lineterminator, "\r\n"); - DIASET(_set_char, "quotechar", &self->quotechar, quotechar, '"'); + DIASET(_set_char_or_none, "quotechar", &self->quotechar, quotechar, '"'); DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL); DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, false); DIASET(_set_bool, "strict", &self->strict, strict, false); @@ -490,7 +525,7 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) } /* Since dialect is now a heap type, it inherits pickling method for - * protocol 0 and 1 from object, therefore it needs to be overriden */ + * protocol 0 and 1 from object, therefore it needs to be overridden */ PyDoc_STRVAR(dialect_reduce_doc, "raises an exception to avoid pickling"); @@ -512,21 +547,38 @@ PyDoc_STRVAR(Dialect_Type_doc, "\n" "The Dialect type records CSV parsing and generation options.\n"); +static int +Dialect_clear(DialectObj *self) +{ + Py_CLEAR(self->lineterminator); + return 0; +} + +static int +Dialect_traverse(DialectObj *self, visitproc visit, void *arg) +{ + Py_VISIT(self->lineterminator); + Py_VISIT(Py_TYPE(self)); + return 0; +} + static PyType_Slot Dialect_Type_slots[] = { {Py_tp_doc, (char*)Dialect_Type_doc}, {Py_tp_members, Dialect_memberlist}, {Py_tp_getset, Dialect_getsetlist}, {Py_tp_new, dialect_new}, {Py_tp_methods, dialect_methods}, - {Py_tp_finalize, Dialect_finalize}, {Py_tp_dealloc, Dialect_dealloc}, + {Py_tp_clear, Dialect_clear}, + {Py_tp_traverse, Dialect_traverse}, {0, NULL} }; PyType_Spec Dialect_Type_spec = { .name = "_csv.Dialect", .basicsize = sizeof(DialectObj), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = Dialect_Type_slots, }; @@ -885,9 +937,7 @@ Reader_dealloc(ReaderObj *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - Py_CLEAR(self->dialect); - Py_CLEAR(self->input_iter); - Py_CLEAR(self->fields); + tp->tp_clear((PyObject *)self); if (self->field != NULL) { PyMem_Free(self->field); self->field = NULL; @@ -896,24 +946,13 @@ Reader_dealloc(ReaderObj *self) Py_DECREF(tp); } -static void -Reader_finalize(ReaderObj *self) -{ - Py_CLEAR(self->dialect); - Py_CLEAR(self->input_iter); - Py_CLEAR(self->fields); - if (self->field != NULL) { - PyMem_Free(self->field); - self->field = NULL; - } -} - static int Reader_traverse(ReaderObj *self, visitproc visit, void *arg) { Py_VISIT(self->dialect); Py_VISIT(self->input_iter); Py_VISIT(self->fields); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -948,12 +987,11 @@ static struct PyMemberDef Reader_memberlist[] = { static PyType_Slot Reader_Type_slots[] = { {Py_tp_doc, (char*)Reader_Type_doc}, {Py_tp_traverse, Reader_traverse}, - {Py_tp_clear, Reader_clear}, {Py_tp_iter, PyObject_SelfIter}, {Py_tp_iternext, Reader_iternext}, {Py_tp_methods, Reader_methods}, {Py_tp_members, Reader_memberlist}, - {Py_tp_finalize, Reader_finalize}, + {Py_tp_clear, Reader_clear}, {Py_tp_dealloc, Reader_dealloc}, {0, NULL} }; @@ -961,7 +999,8 @@ static PyType_Slot Reader_Type_slots[] = { PyType_Spec Reader_Type_spec = { .name = "_csv.reader", .basicsize = sizeof(ReaderObj), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = Reader_Type_slots }; @@ -1339,6 +1378,7 @@ Writer_traverse(WriterObj *self, visitproc visit, void *arg) Py_VISIT(self->dialect); Py_VISIT(self->write); Py_VISIT(self->error_obj); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -1352,12 +1392,16 @@ Writer_clear(WriterObj *self) } static void -Writer_finalize(WriterObj *self) +Writer_dealloc(WriterObj *self) { - Writer_clear(self); + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); if (self->rec != NULL) { PyMem_Free(self->rec); } + PyObject_GC_Del(self); + Py_DECREF(tp); } PyDoc_STRVAR(Writer_Type_doc, @@ -1368,10 +1412,10 @@ PyDoc_STRVAR(Writer_Type_doc, ); static PyType_Slot Writer_Type_slots[] = { - {Py_tp_finalize, Writer_finalize}, {Py_tp_doc, (char*)Writer_Type_doc}, {Py_tp_traverse, Writer_traverse}, {Py_tp_clear, Writer_clear}, + {Py_tp_dealloc, Writer_dealloc}, {Py_tp_methods, Writer_methods}, {Py_tp_members, Writer_memberlist}, {0, NULL} @@ -1380,7 +1424,8 @@ static PyType_Slot Writer_Type_slots[] = { PyType_Spec Writer_Type_spec = { .name = "_csv.writer", .basicsize = sizeof(WriterObj), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = Writer_Type_slots, }; @@ -1515,7 +1560,7 @@ static PyType_Slot error_slots[] = { PyType_Spec error_spec = { .name = "_csv.Error", - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .slots = error_slots, }; diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index 1ccad8e0e3d64d..a33d15de9c0d41 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -1034,7 +1034,7 @@ EXPORT (HRESULT) KeepObject(IUnknown *punk) static struct PyModuleDef_Slot _ctypes_test_slots[] = { {0, NULL} -}; +}; static struct PyModuleDef _ctypes_testmodule = { PyModuleDef_HEAD_INIT, diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 56ccc2f1e0b5da..ddf289e3e8f600 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -834,7 +834,7 @@ static int _call_function_pointer(int flags, # define HAVE_FFI_PREP_CIF_VAR_RUNTIME false # endif - /* Even on Apple-arm64 the calling convention for variadic functions conincides + /* Even on Apple-arm64 the calling convention for variadic functions coincides * with the standard calling convention in the case that the function called * only with its fixed arguments. Thus, we do not need a special flag to be * set on variadic functions. We treat a function as variadic if it is called @@ -1442,14 +1442,37 @@ copy_com_pointer(PyObject *self, PyObject *args) return r; } #else - +#ifdef __APPLE__ #ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH +#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \ + __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) +#else +// Support the deprecated case of compiling on an older macOS version +static void *libsystem_b_handle; +static bool (*_dyld_shared_cache_contains_path)(const char *path); + +__attribute__((constructor)) void load_dyld_shared_cache_contains_path(void) { + libsystem_b_handle = dlopen("/usr/lib/libSystem.B.dylib", RTLD_LAZY); + if (libsystem_b_handle != NULL) { + _dyld_shared_cache_contains_path = dlsym(libsystem_b_handle, "_dyld_shared_cache_contains_path"); + } +} + +__attribute__((destructor)) void unload_dyld_shared_cache_contains_path(void) { + if (libsystem_b_handle != NULL) { + dlclose(libsystem_b_handle); + } +} +#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \ + _dyld_shared_cache_contains_path != NULL +#endif + static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args) { PyObject *name, *name2; char *name_str; - if (__builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)) { + if (HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME) { int r; if (!PyArg_ParseTuple(args, "O", &name)) @@ -1992,7 +2015,7 @@ PyMethodDef _ctypes_module_methods[] = { {"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"}, {"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"}, #endif -#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH +#ifdef __APPLE__ {"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"}, #endif {"alignment", align_func, METH_O, alignment_doc}, diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 8d0710fbabcca3..ec6feca8b0f809 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -35,7 +35,7 @@ PyCField_new(PyTypeObject *type, PyObject *args, PyObject *kwds) * Expects the size, index and offset for the current field in *psize and * *poffset, stores the total size so far in *psize, the offset for the next * field in *poffset, the alignment requirements for the current field in - * *palign, and returns a field desriptor for this field. + * *palign, and returns a field descriptor for this field. */ /* * bitfields extension: @@ -71,18 +71,6 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, Py_DECREF(self); return NULL; } - -#ifndef MS_WIN32 - /* if we have a packed bitfield, calculate the minimum number of bytes we - need to fit it. otherwise use the specified size. */ - if (pack && bitsize) { - size = (bitsize - 1) / 8 + 1; - } else -#endif - size = dict->size; - - proto = desc; - if (bitsize /* this is a bitfield request */ && *pfield_size /* we have a bitfield open */ #ifdef MS_WIN32 @@ -99,9 +87,7 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, } else if (bitsize /* this is a bitfield request */ && *pfield_size /* we have a bitfield open */ && dict->size * 8 >= *pfield_size - /* if this is a packed bitfield, always expand it. - otherwise calculate if we need to expand it. */ - && (((*pbitofs + bitsize) <= dict->size * 8) || pack)) { + && (*pbitofs + bitsize) <= dict->size * 8) { /* expand bit field */ fieldtype = EXPAND_BITFIELD; #endif @@ -109,9 +95,7 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, /* start new bitfield */ fieldtype = NEW_BITFIELD; *pbitofs = 0; - /* use our calculated size (size) instead of type size (dict->size), - which can be different for packed bitfields */ - *pfield_size = size * 8; + *pfield_size = dict->size * 8; } else { /* not a bit field */ fieldtype = NO_BITFIELD; @@ -119,6 +103,9 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, *pfield_size = 0; } + size = dict->size; + proto = desc; + /* Field descriptors for 'c_char * n' are be scpecial cased to return a Python string instead of an Array object instance... */ @@ -183,16 +170,10 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, break; case EXPAND_BITFIELD: - /* increase the size if it is a packed bitfield. - EXPAND_BITFIELD should not be selected for non-packed fields if the - current size isn't already enough. */ - if (pack) - size = (*pbitofs + bitsize - 1) / 8 + 1; - - *poffset += size - *pfield_size/8; - *psize += size - *pfield_size/8; + *poffset += dict->size - *pfield_size/8; + *psize += dict->size - *pfield_size/8; - *pfield_size = size * 8; + *pfield_size = dict->size * 8; if (big_endian) self->size = (bitsize << 16) + *pfield_size - *pbitofs - bitsize; diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 6110027980827c..9600ddc7413b2e 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -208,7 +208,7 @@ typedef struct { PyObject *checker; int flags; /* calling convention and such */ - /* pep3118 fields, pointers neeed PyMem_Free */ + /* pep3118 fields, pointers need PyMem_Free */ char *format; int ndim; Py_ssize_t *shape; diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index b6b7ca458b454a..a1de43599c99de 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -35,7 +35,7 @@ A number of SysV or ncurses functions don't have wrappers yet; if you need a given function, add it and send a patch. See - http://www.python.org/dev/patches/ for instructions on how to submit + https://www.python.org/dev/patches/ for instructions on how to submit patches to Python. Here's a list of currently unsupported functions: @@ -135,11 +135,11 @@ typedef chtype attr_t; /* No attr_t type is available */ #define STRICT_SYSV_CURSES #endif -#if NCURSES_EXT_COLORS+0 && NCURSES_EXT_FUNCS+0 +#if NCURSES_EXT_FUNCS+0 >= 20170401 && NCURSES_EXT_COLORS+0 >= 20170401 #define _NCURSES_EXTENDED_COLOR_FUNCS 1 #else #define _NCURSES_EXTENDED_COLOR_FUNCS 0 -#endif /* defined(NCURSES_EXT_COLORS) && defined(NCURSES_EXT_FUNCS) */ +#endif #if _NCURSES_EXTENDED_COLOR_FUNCS #define _CURSES_COLOR_VAL_TYPE int @@ -1226,8 +1226,8 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) return NULL; } - color = (short)((attr >> 8) & 0xff); - attr = attr - (color << 8); + color = (short) PAIR_NUMBER(attr); + attr = attr & A_ATTRIBUTES; if (use_xy) { rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8ef2dad37a3a05..e54a01b44c5bad 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1013,7 +1013,7 @@ new_time_ex(int hour, int minute, int second, int usecond, * true. Passing false is a speed optimization, if you know for sure * that seconds and microseconds are already in their proper ranges. In any * case, raises OverflowError and returns NULL if the normalized days is out - * of range). + * of range. */ static PyObject * new_delta_ex(int days, int seconds, int microseconds, int normalize, diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 58f9c2c357b2c6..5733bb4a80de11 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -65,13 +65,14 @@ typedef struct { static PyObject * newdbmobject(_dbm_state *state, const char *file, int flags, int mode) { - dbmobject *dp; - - dp = PyObject_New(dbmobject, state->dbm_type); - if (dp == NULL) + dbmobject *dp = PyObject_GC_New(dbmobject, state->dbm_type); + if (dp == NULL) { return NULL; + } dp->di_size = -1; dp->flags = flags; + PyObject_GC_Track(dp); + /* See issue #19296 */ if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == 0 ) { PyErr_SetFromErrnoWithFilename(state->dbm_error, file); @@ -82,10 +83,17 @@ newdbmobject(_dbm_state *state, const char *file, int flags, int mode) } /* Methods */ +static int +dbm_traverse(dbmobject *dp, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(dp)); + return 0; +} static void dbm_dealloc(dbmobject *dp) { + PyObject_GC_UnTrack(dp); if (dp->di_dbm) { dbm_close(dp->di_dbm); } @@ -398,6 +406,7 @@ static PyMethodDef dbm_methods[] = { static PyType_Slot dbmtype_spec_slots[] = { {Py_tp_dealloc, dbm_dealloc}, + {Py_tp_traverse, dbm_traverse}, {Py_tp_methods, dbm_methods}, {Py_sq_contains, dbm_contains}, {Py_mp_length, dbm_length}, @@ -414,7 +423,8 @@ static PyType_Spec dbmtype_spec = { // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = dbmtype_spec_slots, }; diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 9b89fa40c926b1..e2979a577c96c7 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -696,8 +696,7 @@ static PyTypeObject PyDecSignalDictMixin_Type = PyObject_GenericGetAttr, /* tp_getattro */ (setattrofunc) 0, /* tp_setattro */ (PyBufferProcs *) 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE| - Py_TPFLAGS_HAVE_GC, /* tp_flags */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ diff --git a/Modules/_decimal/tests/bench.py b/Modules/_decimal/tests/bench.py index 3726db194e032f..24e091b6887ccd 100644 --- a/Modules/_decimal/tests/bench.py +++ b/Modules/_decimal/tests/bench.py @@ -7,10 +7,7 @@ import time -try: - from test.support import import_fresh_module -except ImportError: - from test.test_support import import_fresh_module +from test.support.import_helper import import_fresh_module C = import_fresh_module('decimal', fresh=['_decimal']) P = import_fresh_module('decimal', blocked=['_decimal']) diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index 98ecd502c03fe9..edf753f3704a18 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -47,7 +47,7 @@ from queue import Queue, Empty from threading import Thread, Event, Lock -from test.support import import_fresh_module +from test.support.import_helper import import_fresh_module from randdec import randfloat, all_unary, all_binary, all_ternary from randdec import unary_optarg, binary_optarg, ternary_optarg from formathelper import rand_format, rand_locale diff --git a/Modules/_decimal/tests/formathelper.py b/Modules/_decimal/tests/formathelper.py index 19b2aad4a503b1..c3daacfb7b44f4 100644 --- a/Modules/_decimal/tests/formathelper.py +++ b/Modules/_decimal/tests/formathelper.py @@ -31,7 +31,7 @@ import os, sys, locale, random import platform, subprocess -from test.support import import_fresh_module +from test.support.import_helper import import_fresh_module from distutils.spawn import find_executable C = import_fresh_module('decimal', fresh=['_decimal']) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 85fdfa7e5ed42c..9dadeef7129384 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1,6 +1,6 @@ /*-------------------------------------------------------------------- * Licensed to PSF under a Contributor Agreement. - * See http://www.python.org/psf/license for licensing details. + * See https://www.python.org/psf/license for licensing details. * * _elementtree - C accelerator for xml.etree.ElementTree * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. @@ -1393,22 +1393,19 @@ _elementtree_Element_get_impl(ElementObject *self, PyObject *key, PyObject *default_value) /*[clinic end generated code: output=523c614142595d75 input=ee153bbf8cdb246e]*/ { - PyObject* value; - - if (!self->extra || !self->extra->attrib) - value = default_value; - else { - value = PyDict_GetItemWithError(self->extra->attrib, key); - if (!value) { - if (PyErr_Occurred()) { - return NULL; - } - value = default_value; + if (self->extra && self->extra->attrib) { + PyObject *attrib = self->extra->attrib; + Py_INCREF(attrib); + PyObject *value = PyDict_GetItemWithError(attrib, key); + Py_XINCREF(value); + Py_DECREF(attrib); + if (value != NULL || PyErr_Occurred()) { + return value; } } - Py_INCREF(value); - return value; + Py_INCREF(default_value); + return default_value; } static PyObject * diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 19cfa9b07b340d..fa1452168094b9 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -147,18 +147,37 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) return (PyObject *)pto; } +static int +partial_clear(partialobject *pto) +{ + Py_CLEAR(pto->fn); + Py_CLEAR(pto->args); + Py_CLEAR(pto->kw); + Py_CLEAR(pto->dict); + return 0; +} + +static int +partial_traverse(partialobject *pto, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(pto)); + Py_VISIT(pto->fn); + Py_VISIT(pto->args); + Py_VISIT(pto->kw); + Py_VISIT(pto->dict); + return 0; +} + static void partial_dealloc(partialobject *pto) { PyTypeObject *tp = Py_TYPE(pto); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(pto); - if (pto->weakreflist != NULL) + if (pto->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) pto); - Py_XDECREF(pto->fn); - Py_XDECREF(pto->args); - Py_XDECREF(pto->kw); - Py_XDECREF(pto->dict); + } + (void)partial_clear(pto); tp->tp_free(pto); Py_DECREF(tp); } @@ -307,16 +326,6 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kwargs) return res; } -static int -partial_traverse(partialobject *pto, visitproc visit, void *arg) -{ - Py_VISIT(pto->fn); - Py_VISIT(pto->args); - Py_VISIT(pto->kw); - Py_VISIT(pto->dict); - return 0; -} - PyDoc_STRVAR(partial_doc, "partial(func, *args, **keywords) - new function with partial application\n\ of the given arguments and keywords.\n"); @@ -469,6 +478,7 @@ static PyType_Slot partial_type_slots[] = { {Py_tp_setattro, PyObject_GenericSetAttr}, {Py_tp_doc, (void *)partial_doc}, {Py_tp_traverse, partial_traverse}, + {Py_tp_clear, partial_clear}, {Py_tp_methods, partial_methods}, {Py_tp_members, partial_memberlist}, {Py_tp_getset, partial_getsetlist}, @@ -481,7 +491,8 @@ static PyType_Spec partial_type_spec = { .name = "functools.partial", .basicsize = sizeof(partialobject), .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL, + Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL | + Py_TPFLAGS_IMMUTABLETYPE, .slots = partial_type_slots }; @@ -506,14 +517,16 @@ static void keyobject_dealloc(keyobject *ko) { PyTypeObject *tp = Py_TYPE(ko); - keyobject_clear(ko); - PyObject_Free(ko); + PyObject_GC_UnTrack(ko); + (void)keyobject_clear(ko); + tp->tp_free(ko); Py_DECREF(tp); } static int keyobject_traverse(keyobject *ko, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(ko)); Py_VISIT(ko->cmp); Py_VISIT(ko->object); return 0; @@ -546,7 +559,8 @@ static PyType_Slot keyobject_type_slots[] = { static PyType_Spec keyobject_type_spec = { .name = "functools.KeyWrapper", .basicsize = sizeof(keyobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = keyobject_type_slots }; @@ -560,7 +574,7 @@ keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object)) return NULL; - result = PyObject_New(keyobject, Py_TYPE(ko)); + result = PyObject_GC_New(keyobject, Py_TYPE(ko)); if (result == NULL) { return NULL; } @@ -568,6 +582,7 @@ keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds) result->cmp = ko->cmp; Py_INCREF(object); result->object = object; + PyObject_GC_Track(result); return (PyObject *)result; } @@ -621,12 +636,13 @@ functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds) return NULL; state = get_functools_state(self); - object = PyObject_New(keyobject, state->keyobject_type); + object = PyObject_GC_New(keyobject, state->keyobject_type); if (!object) return NULL; Py_INCREF(cmp); object->cmp = cmp; object->object = NULL; + PyObject_GC_Track(object); return (PyObject *)object; } @@ -754,7 +770,7 @@ lru_list_elem_dealloc(lru_list_elem *link) PyTypeObject *tp = Py_TYPE(link); Py_XDECREF(link->key); Py_XDECREF(link->result); - PyObject_Free(link); + tp->tp_free(link); Py_DECREF(tp); } @@ -766,7 +782,8 @@ static PyType_Slot lru_list_elem_type_slots[] = { static PyType_Spec lru_list_elem_type_spec = { .name = "functools._lru_list_elem", .basicsize = sizeof(lru_list_elem), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE, .slots = lru_list_elem_type_slots }; @@ -1240,8 +1257,8 @@ static int lru_cache_tp_clear(lru_cache_object *self) { lru_list_elem *list = lru_cache_unlink_list(self); - Py_CLEAR(self->func); Py_CLEAR(self->cache); + Py_CLEAR(self->func); Py_CLEAR(self->kwd_mark); Py_CLEAR(self->lru_list_elem_type); Py_CLEAR(self->cache_info_type); @@ -1260,7 +1277,7 @@ lru_cache_dealloc(lru_cache_object *obj) PyObject_ClearWeakRefs((PyObject*)obj); } - lru_cache_tp_clear(obj); + (void)lru_cache_tp_clear(obj); tp->tp_free(obj); Py_DECREF(tp); } @@ -1327,15 +1344,17 @@ lru_cache_deepcopy(PyObject *self, PyObject *unused) static int lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); lru_list_elem *link = self->root.next; while (link != &self->root) { lru_list_elem *next = link->next; Py_VISIT(link->key); Py_VISIT(link->result); + Py_VISIT(Py_TYPE(link)); link = next; } - Py_VISIT(self->func); Py_VISIT(self->cache); + Py_VISIT(self->func); Py_VISIT(self->kwd_mark); Py_VISIT(self->lru_list_elem_type); Py_VISIT(self->cache_info_type); @@ -1400,7 +1419,7 @@ static PyType_Spec lru_cache_type_spec = { .name = "functools._lru_cache_wrapper", .basicsize = sizeof(lru_cache_object), .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_METHOD_DESCRIPTOR, + Py_TPFLAGS_METHOD_DESCRIPTOR | Py_TPFLAGS_IMMUTABLETYPE, .slots = lru_cache_type_slots }; @@ -1460,9 +1479,8 @@ _functools_exec(PyObject *module) if (state->lru_list_elem_type == NULL) { return -1; } - if (PyModule_AddType(module, state->lru_list_elem_type) < 0) { - return -1; - } + // lru_list_elem is used only in _lru_cache_wrapper. + // So we don't expose it in module namespace. return 0; } diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index c52190a7ed2db5..a7fb6a33c862c4 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -74,12 +74,14 @@ nextkey, reorganize, and sync."); static PyObject * newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode) { - gdbmobject *dp = PyObject_New(gdbmobject, state->gdbm_type); + gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type); if (dp == NULL) { return NULL; } dp->di_size = -1; errno = 0; + PyObject_GC_Track(dp); + if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) { if (errno != 0) { PyErr_SetFromErrnoWithFilename(state->gdbm_error, file); @@ -94,10 +96,17 @@ newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode) } /* Methods */ +static int +gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(dp)); + return 0; +} static void gdbm_dealloc(gdbmobject *dp) { + PyObject_GC_UnTrack(dp); if (dp->di_dbm) { gdbm_close(dp->di_dbm); } @@ -441,7 +450,7 @@ The following code prints every key in the database db, without having to create a list in memory that contains them all: k = db.firstkey() - while k != None: + while k is not None: print(k) k = db.nextkey(k) [clinic start generated code]*/ @@ -449,7 +458,7 @@ to create a list in memory that contains them all: static PyObject * _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key, Py_ssize_clean_t key_length) -/*[clinic end generated code: output=204964441fdbaf02 input=fcf6a51a96ce0172]*/ +/*[clinic end generated code: output=204964441fdbaf02 input=365e297bc0b3db48]*/ { PyObject *v; datum dbm_key, nextkey; @@ -554,6 +563,7 @@ static PyMethodDef gdbm_methods[] = { static PyType_Slot gdbmtype_spec_slots[] = { {Py_tp_dealloc, gdbm_dealloc}, + {Py_tp_traverse, gdbm_traverse}, {Py_tp_methods, gdbm_methods}, {Py_sq_contains, gdbm_contains}, {Py_mp_length, gdbm_length}, @@ -570,7 +580,8 @@ static PyType_Spec gdbmtype_spec = { // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = gdbmtype_spec_slots, }; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index b2c67759e95ea3..2eaa5f7d85d80a 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -18,9 +18,14 @@ #endif #define OPENSSL_NO_DEPRECATED 1 +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_hashtable.h" #include "hashlib.h" #include "pystrhex.h" @@ -45,6 +50,160 @@ #define PY_OPENSSL_HAS_SHAKE 1 #define PY_OPENSSL_HAS_BLAKE2 1 +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#define PY_EVP_MD EVP_MD +#define PY_EVP_MD_fetch(algorithm, properties) EVP_MD_fetch(NULL, algorithm, properties) +#define PY_EVP_MD_up_ref(md) EVP_MD_up_ref(md) +#define PY_EVP_MD_free(md) EVP_MD_free(md) +#else +#define PY_EVP_MD const EVP_MD +#define PY_EVP_MD_fetch(algorithm, properties) EVP_get_digestbyname(algorithm) +#define PY_EVP_MD_up_ref(md) do {} while(0) +#define PY_EVP_MD_free(md) do {} while(0) +#endif + +/* hash alias map and fast lookup + * + * Map between Python's preferred names and OpenSSL internal names. Maintain + * cache of fetched EVP MD objects. The EVP_get_digestbyname() and + * EVP_MD_fetch() API calls have a performance impact. + * + * The py_hashentry_t items are stored in a _Py_hashtable_t with py_name and + * py_alias as keys. + */ + +enum Py_hash_type { + Py_ht_evp, // usedforsecurity=True / default + Py_ht_evp_nosecurity, // usedforsecurity=False + Py_ht_mac, // HMAC + Py_ht_pbkdf2, // PKBDF2 +}; + +typedef struct { + const char *py_name; + const char *py_alias; + const char *ossl_name; + int ossl_nid; + int refcnt; + PY_EVP_MD *evp; + PY_EVP_MD *evp_nosecurity; +} py_hashentry_t; + +#define Py_hash_md5 "md5" +#define Py_hash_sha1 "sha1" +#define Py_hash_sha224 "sha224" +#define Py_hash_sha256 "sha256" +#define Py_hash_sha384 "sha384" +#define Py_hash_sha512 "sha512" +#define Py_hash_sha512_224 "sha512_224" +#define Py_hash_sha512_256 "sha512_256" +#define Py_hash_sha3_224 "sha3_224" +#define Py_hash_sha3_256 "sha3_256" +#define Py_hash_sha3_384 "sha3_384" +#define Py_hash_sha3_512 "sha3_512" +#define Py_hash_shake_128 "shake_128" +#define Py_hash_shake_256 "shake_256" +#define Py_hash_blake2s "blake2s" +#define Py_hash_blake2b "blake2b" + +#define PY_HASH_ENTRY(py_name, py_alias, ossl_name, ossl_nid) \ + {py_name, py_alias, ossl_name, ossl_nid, 0, NULL, NULL} + +static const py_hashentry_t py_hashes[] = { + /* md5 */ + PY_HASH_ENTRY(Py_hash_md5, "MD5", SN_md5, NID_md5), + /* sha1 */ + PY_HASH_ENTRY(Py_hash_sha1, "SHA1", SN_sha1, NID_sha1), + /* sha2 family */ + PY_HASH_ENTRY(Py_hash_sha224, "SHA224", SN_sha224, NID_sha224), + PY_HASH_ENTRY(Py_hash_sha256, "SHA256", SN_sha256, NID_sha256), + PY_HASH_ENTRY(Py_hash_sha384, "SHA384", SN_sha384, NID_sha384), + PY_HASH_ENTRY(Py_hash_sha512, "SHA512", SN_sha512, NID_sha512), + /* truncated sha2 */ + PY_HASH_ENTRY(Py_hash_sha512_224, "SHA512_224", SN_sha512_224, NID_sha512_224), + PY_HASH_ENTRY(Py_hash_sha512_256, "SHA512_256", SN_sha512_256, NID_sha512_256), + /* sha3 */ + PY_HASH_ENTRY(Py_hash_sha3_224, NULL, SN_sha3_224, NID_sha3_224), + PY_HASH_ENTRY(Py_hash_sha3_256, NULL, SN_sha3_256, NID_sha3_256), + PY_HASH_ENTRY(Py_hash_sha3_384, NULL, SN_sha3_384, NID_sha3_384), + PY_HASH_ENTRY(Py_hash_sha3_512, NULL, SN_sha3_512, NID_sha3_512), + /* sha3 shake */ + PY_HASH_ENTRY(Py_hash_shake_128, NULL, SN_shake128, NID_shake128), + PY_HASH_ENTRY(Py_hash_shake_256, NULL, SN_shake256, NID_shake256), + /* blake2 digest */ + PY_HASH_ENTRY(Py_hash_blake2s, "blake2s256", SN_blake2s256, NID_blake2s256), + PY_HASH_ENTRY(Py_hash_blake2b, "blake2b512", SN_blake2b512, NID_blake2b512), + PY_HASH_ENTRY(NULL, NULL, NULL, 0), +}; + +static Py_uhash_t +py_hashentry_t_hash_name(const void *key) { + return _Py_HashBytes(key, strlen((const char *)key)); +} + +static int +py_hashentry_t_compare_name(const void *key1, const void *key2) { + return strcmp((const char *)key1, (const char *)key2) == 0; +} + +static void +py_hashentry_t_destroy_value(void *entry) { + py_hashentry_t *h = (py_hashentry_t *)entry; + if (--(h->refcnt) == 0) { + if (h->evp != NULL) { + PY_EVP_MD_free(h->evp); + h->evp = NULL; + } + if (h->evp_nosecurity != NULL) { + PY_EVP_MD_free(h->evp_nosecurity); + h->evp_nosecurity = NULL; + } + PyMem_Free(entry); + } +} + +static _Py_hashtable_t * +py_hashentry_table_new(void) { + _Py_hashtable_t *ht = _Py_hashtable_new_full( + py_hashentry_t_hash_name, + py_hashentry_t_compare_name, + NULL, + py_hashentry_t_destroy_value, + NULL + ); + if (ht == NULL) { + return NULL; + } + + for (const py_hashentry_t *h = py_hashes; h->py_name != NULL; h++) { + py_hashentry_t *entry = (py_hashentry_t *)PyMem_Malloc(sizeof(py_hashentry_t)); + if (entry == NULL) { + goto error; + } + memcpy(entry, h, sizeof(py_hashentry_t)); + + if (_Py_hashtable_set(ht, (const void*)entry->py_name, (void*)entry) < 0) { + PyMem_Free(entry); + goto error; + } + entry->refcnt = 1; + + if (h->py_alias != NULL) { + if (_Py_hashtable_set(ht, (const void*)entry->py_alias, (void*)entry) < 0) { + PyMem_Free(entry); + goto error; + } + entry->refcnt++; + } + } + + return ht; + error: + _Py_hashtable_destroy(ht); + return NULL; +} + +/* Module state */ static PyModuleDef _hashlibmodule; typedef struct { @@ -55,6 +214,7 @@ typedef struct { #endif PyObject *constructs; PyObject *unsupported_digestmod_error; + _Py_hashtable_t *hashtable; } _hashlibstate; static inline _hashlibstate* @@ -89,16 +249,26 @@ class _hashlib.HMAC "HMACobject *" "((_hashlibstate *)PyModule_GetState(module)) /* LCOV_EXCL_START */ static PyObject * -_setException(PyObject *exc) +_setException(PyObject *exc, const char* altmsg, ...) { - unsigned long errcode; + unsigned long errcode = ERR_peek_last_error(); const char *lib, *func, *reason; + va_list vargs; - errcode = ERR_peek_last_error(); +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, altmsg); +#else + va_start(vargs); +#endif if (!errcode) { - PyErr_SetString(exc, "unknown reasons"); + if (altmsg == NULL) { + PyErr_SetString(exc, "no reason supplied"); + } else { + PyErr_FormatV(exc, altmsg, vargs); + } return NULL; } + va_end(vargs); ERR_clear_error(); lib = ERR_lib_error_string(errcode); @@ -123,68 +293,15 @@ py_digest_name(const EVP_MD *md) { int nid = EVP_MD_nid(md); const char *name = NULL; + const py_hashentry_t *h; - /* Hard-coded names for well-known hashing algorithms. - * OpenSSL uses slightly different names algorithms like SHA3. - */ - switch (nid) { - case NID_md5: - name = "md5"; - break; - case NID_sha1: - name = "sha1"; - break; - case NID_sha224: - name ="sha224"; - break; - case NID_sha256: - name ="sha256"; - break; - case NID_sha384: - name ="sha384"; - break; - case NID_sha512: - name ="sha512"; - break; -#ifdef NID_sha512_224 - case NID_sha512_224: - name ="sha512_224"; - break; - case NID_sha512_256: - name ="sha512_256"; - break; -#endif -#ifdef PY_OPENSSL_HAS_SHA3 - case NID_sha3_224: - name ="sha3_224"; - break; - case NID_sha3_256: - name ="sha3_256"; - break; - case NID_sha3_384: - name ="sha3_384"; - break; - case NID_sha3_512: - name ="sha3_512"; - break; -#endif -#ifdef PY_OPENSSL_HAS_SHAKE - case NID_shake128: - name ="shake_128"; - break; - case NID_shake256: - name ="shake_256"; - break; -#endif -#ifdef PY_OPENSSL_HAS_BLAKE2 - case NID_blake2s256: - name ="blake2s"; - break; - case NID_blake2b512: - name ="blake2b"; - break; -#endif - default: + for (h = py_hashes; h->py_name != NULL; h++) { + if (h->ossl_nid == nid) { + name = h->py_name; + break; + } + } + if (name == NULL) { /* Ignore aliased names and only use long, lowercase name. The aliases * pollute the list and OpenSSL appears to have its own definition of * alias as the resulting list still contains duplicate and alternate @@ -193,67 +310,58 @@ py_digest_name(const EVP_MD *md) name = OBJ_nid2ln(nid); if (name == NULL) name = OBJ_nid2sn(nid); - break; } return PyUnicode_FromString(name); } -static const EVP_MD* -py_digest_by_name(const char *name) +/* Get EVP_MD by HID and purpose */ +static PY_EVP_MD* +py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht) { - const EVP_MD *digest = EVP_get_digestbyname(name); + PY_EVP_MD *digest = NULL; + _hashlibstate *state = get_hashlib_state(module); + py_hashentry_t *entry = (py_hashentry_t *)_Py_hashtable_get( + state->hashtable, (const void*)name + ); - /* OpenSSL uses dash instead of underscore in names of some algorithms - * like SHA3 and SHAKE. Detect different spellings. */ - if (digest == NULL) { - if (0) {} -#ifdef NID_sha512_224 - else if (!strcmp(name, "sha512_224") || !strcmp(name, "SHA512_224")) { - digest = EVP_sha512_224(); + if (entry != NULL) { + switch (py_ht) { + case Py_ht_evp: + case Py_ht_mac: + case Py_ht_pbkdf2: + if (entry->evp == NULL) { + entry->evp = PY_EVP_MD_fetch(entry->ossl_name, NULL); + } + digest = entry->evp; + break; + case Py_ht_evp_nosecurity: + if (entry->evp_nosecurity == NULL) { + entry->evp_nosecurity = PY_EVP_MD_fetch(entry->ossl_name, "-fips"); + } + digest = entry->evp_nosecurity; + break; } - else if (!strcmp(name, "sha512_256") || !strcmp(name, "SHA512_256")) { - digest = EVP_sha512_256(); + if (digest != NULL) { + PY_EVP_MD_up_ref(digest); } -#endif -#ifdef PY_OPENSSL_HAS_SHA3 - /* could be sha3_ or shake_, Python never defined upper case */ - else if (!strcmp(name, "sha3_224")) { - digest = EVP_sha3_224(); - } - else if (!strcmp(name, "sha3_256")) { - digest = EVP_sha3_256(); - } - else if (!strcmp(name, "sha3_384")) { - digest = EVP_sha3_384(); - } - else if (!strcmp(name, "sha3_512")) { - digest = EVP_sha3_512(); - } -#endif -#ifdef PY_OPENSSL_HAS_SHAKE - else if (!strcmp(name, "shake_128")) { - digest = EVP_shake128(); - } - else if (!strcmp(name, "shake_256")) { - digest = EVP_shake256(); - } -#endif -#ifdef PY_OPENSSL_HAS_BLAKE2 - else if (!strcmp(name, "blake2s256")) { - digest = EVP_blake2s256(); - } - else if (!strcmp(name, "blake2b512")) { - digest = EVP_blake2b512(); + } else { + // Fall back for looking up an unindexed OpenSSL specific name. + switch (py_ht) { + case Py_ht_evp: + case Py_ht_mac: + case Py_ht_pbkdf2: + digest = PY_EVP_MD_fetch(name, NULL); + break; + case Py_ht_evp_nosecurity: + digest = PY_EVP_MD_fetch(name, "-fips"); + break; } -#endif } - if (digest == NULL) { - PyErr_Format(PyExc_ValueError, "unsupported hash type %s", name); + _setException(PyExc_ValueError, "unsupported hash type %s", name); return NULL; } - return digest; } @@ -264,9 +372,9 @@ py_digest_by_name(const char *name) * * on error returns NULL with exception set. */ -static const EVP_MD* -py_digest_by_digestmod(PyObject *module, PyObject *digestmod) { - const EVP_MD* evp; +static PY_EVP_MD* +py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type py_ht) { + PY_EVP_MD* evp; PyObject *name_obj = NULL; const char *name; @@ -291,7 +399,7 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod) { return NULL; } - evp = py_digest_by_name(name); + evp = py_digest_by_name(module, name, py_ht); if (evp == NULL) { return NULL; } @@ -330,7 +438,7 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len) else process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int); if (!EVP_DigestUpdate(self->ctx, (const void*)cp, process)) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return -1; } len -= process; @@ -381,7 +489,7 @@ EVP_copy_impl(EVPobject *self) if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) { Py_DECREF(newobj); - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } return (PyObject *)newobj; } @@ -408,11 +516,11 @@ EVP_digest_impl(EVPobject *self) } if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } digest_size = EVP_MD_CTX_size(temp_ctx); if (!EVP_DigestFinal(temp_ctx, digest, NULL)) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } @@ -443,11 +551,11 @@ EVP_hexdigest_impl(EVPobject *self) /* Get the raw (binary) digest value */ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } digest_size = EVP_MD_CTX_size(temp_ctx); if (!EVP_DigestFinal(temp_ctx, digest, NULL)) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } @@ -623,14 +731,14 @@ EVPXOF_digest_impl(EVPobject *self, Py_ssize_t length) if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { Py_DECREF(retval); EVP_MD_CTX_free(temp_ctx); - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } if (!EVP_DigestFinalXOF(temp_ctx, (unsigned char*)PyBytes_AS_STRING(retval), length)) { Py_DECREF(retval); EVP_MD_CTX_free(temp_ctx); - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } @@ -671,12 +779,12 @@ EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length) if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { PyMem_Free(digest); EVP_MD_CTX_free(temp_ctx); - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } if (!EVP_DigestFinalXOF(temp_ctx, digest, length)) { PyMem_Free(digest); EVP_MD_CTX_free(temp_ctx); - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } @@ -744,55 +852,74 @@ static PyType_Spec EVPXOFtype_spec = { #endif -static PyObject * -EVPnew(PyObject *module, const EVP_MD *digest, - const unsigned char *cp, Py_ssize_t len, int usedforsecurity) +static PyObject* +py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj, + int usedforsecurity) { - int result = 0; - EVPobject *self; - PyTypeObject *type = get_hashlib_state(module)->EVPtype; + Py_buffer view = { 0 }; + PY_EVP_MD *digest = NULL; + PyTypeObject *type; + EVPobject *self = NULL; - if (!digest) { - PyErr_SetString(PyExc_ValueError, "unsupported hash type"); - return NULL; + if (data_obj != NULL) { + GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); + } + + digest = py_digest_by_name( + module, digestname, usedforsecurity ? Py_ht_evp : Py_ht_evp_nosecurity + ); + if (digest == NULL) { + goto exit; } -#ifdef PY_OPENSSL_HAS_SHAKE if ((EVP_MD_flags(digest) & EVP_MD_FLAG_XOF) == EVP_MD_FLAG_XOF) { type = get_hashlib_state(module)->EVPXOFtype; + } else { + type = get_hashlib_state(module)->EVPtype; } -#endif - if ((self = newEVPobject(type)) == NULL) - return NULL; + self = newEVPobject(type); + if (self == NULL) { + goto exit; + } +#if defined(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) && OPENSSL_VERSION_NUMBER < 0x30000000L + // In OpenSSL 1.1.1 the non FIPS allowed flag is context specific while + // in 3.0.0 it is a different EVP_MD provider. if (!usedforsecurity) { -#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW EVP_MD_CTX_set_flags(self->ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif } +#endif - - if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) { - _setException(PyExc_ValueError); - Py_DECREF(self); - return NULL; + int result = EVP_DigestInit_ex(self->ctx, digest, NULL); + if (!result) { + _setException(PyExc_ValueError, NULL); + Py_CLEAR(self); + goto exit; } - if (cp && len) { - if (len >= HASHLIB_GIL_MINSIZE) { + if (view.buf && view.len) { + if (view.len >= HASHLIB_GIL_MINSIZE) { Py_BEGIN_ALLOW_THREADS - result = EVP_hash(self, cp, len); + result = EVP_hash(self, view.buf, view.len); Py_END_ALLOW_THREADS } else { - result = EVP_hash(self, cp, len); + result = EVP_hash(self, view.buf, view.len); } if (result == -1) { - Py_DECREF(self); - return NULL; + Py_CLEAR(self); + goto exit; } } + exit: + if (data_obj != NULL) { + PyBuffer_Release(&view); + } + if (digest != NULL) { + PY_EVP_MD_free(digest); + } + return (PyObject *)self; } @@ -820,53 +947,14 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=ddd5053f92dffe90 input=c24554d0337be1b0]*/ { - Py_buffer view = { 0 }; - PyObject *ret_obj = NULL; char *name; - const EVP_MD *digest = NULL; - if (!PyArg_Parse(name_obj, "s", &name)) { PyErr_SetString(PyExc_TypeError, "name must be a string"); return NULL; } - - if (data_obj) - GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); - - digest = py_digest_by_name(name); - if (digest == NULL) { - goto exit; - } - - ret_obj = EVPnew(module, digest, - (unsigned char*)view.buf, view.len, - usedforsecurity); - -exit: - if (data_obj) - PyBuffer_Release(&view); - return ret_obj; + return py_evp_fromname(module, name, data_obj, usedforsecurity); } -static PyObject* -EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest, - int usedforsecurity) -{ - Py_buffer view = { 0 }; - PyObject *ret_obj; - - if (data_obj) - GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); - - ret_obj = EVPnew(module, digest, - (unsigned char*)view.buf, view.len, - usedforsecurity); - - if (data_obj) - PyBuffer_Release(&view); - - return ret_obj; -} /*[clinic input] _hashlib.openssl_md5 @@ -884,7 +972,7 @@ _hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=87b0186440a44f8c input=990e36d5e689b16e]*/ { - return EVP_fast_new(module, data_obj, EVP_md5(), usedforsecurity); + return py_evp_fromname(module, Py_hash_md5, data_obj, usedforsecurity); } @@ -904,7 +992,7 @@ _hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=6813024cf690670d input=948f2f4b6deabc10]*/ { - return EVP_fast_new(module, data_obj, EVP_sha1(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha1, data_obj, usedforsecurity); } @@ -924,7 +1012,7 @@ _hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=a2dfe7cc4eb14ebb input=f9272821fadca505]*/ { - return EVP_fast_new(module, data_obj, EVP_sha224(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha224, data_obj, usedforsecurity); } @@ -944,7 +1032,7 @@ _hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=1f874a34870f0a68 input=549fad9d2930d4c5]*/ { - return EVP_fast_new(module, data_obj, EVP_sha256(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha256, data_obj, usedforsecurity); } @@ -964,7 +1052,7 @@ _hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=58529eff9ca457b2 input=48601a6e3bf14ad7]*/ { - return EVP_fast_new(module, data_obj, EVP_sha384(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha384, data_obj, usedforsecurity); } @@ -984,7 +1072,7 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=2c744c9e4a40d5f6 input=c5c46a2a817aa98f]*/ { - return EVP_fast_new(module, data_obj, EVP_sha512(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha512, data_obj, usedforsecurity); } @@ -1006,7 +1094,7 @@ _hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=144641c1d144b974 input=e3a01b2888916157]*/ { - return EVP_fast_new(module, data_obj, EVP_sha3_224(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha3_224, data_obj, usedforsecurity); } /*[clinic input] @@ -1025,7 +1113,7 @@ _hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=c61f1ab772d06668 input=e2908126c1b6deed]*/ { - return EVP_fast_new(module, data_obj, EVP_sha3_256(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha3_256, data_obj , usedforsecurity); } /*[clinic input] @@ -1044,7 +1132,7 @@ _hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=f68e4846858cf0ee input=ec0edf5c792f8252]*/ { - return EVP_fast_new(module, data_obj, EVP_sha3_384(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha3_384, data_obj , usedforsecurity); } /*[clinic input] @@ -1063,7 +1151,7 @@ _hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=2eede478c159354a input=64e2cc0c094d56f4]*/ { - return EVP_fast_new(module, data_obj, EVP_sha3_512(), usedforsecurity); + return py_evp_fromname(module, Py_hash_sha3_512, data_obj , usedforsecurity); } #endif /* PY_OPENSSL_HAS_SHA3 */ @@ -1084,7 +1172,7 @@ _hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=bc49cdd8ada1fa97 input=6c9d67440eb33ec8]*/ { - return EVP_fast_new(module, data_obj, EVP_shake128(), usedforsecurity); + return py_evp_fromname(module, Py_hash_shake_128, data_obj , usedforsecurity); } /*[clinic input] @@ -1103,7 +1191,7 @@ _hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj, int usedforsecurity) /*[clinic end generated code: output=358d213be8852df7 input=479cbe9fefd4a9f8]*/ { - return EVP_fast_new(module, data_obj, EVP_shake256(), usedforsecurity); + return py_evp_fromname(module, Py_hash_shake_256, data_obj , usedforsecurity); } #endif /* PY_OPENSSL_HAS_SHAKE */ @@ -1129,9 +1217,8 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name, char *key; long dklen; int retval; - const EVP_MD *digest; - digest = py_digest_by_name(hash_name); + PY_EVP_MD *digest = py_digest_by_name(module, hash_name, Py_ht_pbkdf2); if (digest == NULL) { goto end; } @@ -1194,11 +1281,14 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name, if (!retval) { Py_CLEAR(key_obj); - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); goto end; } end: + if (digest != NULL) { + PY_EVP_MD_free(digest); + } return key_obj; } @@ -1297,9 +1387,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, /* let OpenSSL validate the rest */ retval = EVP_PBE_scrypt(NULL, 0, NULL, 0, n, r, p, maxmem, NULL, 0); if (!retval) { - /* sorry, can't do much better */ - PyErr_SetString(PyExc_ValueError, - "Invalid parameter combination for n, r, p, maxmem."); + _setException(PyExc_ValueError, "Invalid parameter combination for n, r, p, maxmem."); return NULL; } @@ -1320,7 +1408,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, if (!retval) { Py_CLEAR(key_obj); - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } return key_obj; @@ -1348,12 +1436,7 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, unsigned char md[EVP_MAX_MD_SIZE] = {0}; unsigned int md_len = 0; unsigned char *result; - const EVP_MD *evp; - - evp = py_digest_by_digestmod(module, digest); - if (evp == NULL) { - return NULL; - } + PY_EVP_MD *evp; if (key->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, @@ -1366,6 +1449,11 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, return NULL; } + evp = py_digest_by_digestmod(module, digest, Py_ht_mac); + if (evp == NULL) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS result = HMAC( evp, @@ -1374,9 +1462,10 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, md, &md_len ); Py_END_ALLOW_THREADS + PY_EVP_MD_free(evp); if (result == NULL) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return NULL; } return PyBytes_FromStringAndSize((const char*)md, md_len); @@ -1403,7 +1492,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, /*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/ { PyTypeObject *type = get_hashlib_state(module)->HMACtype; - const EVP_MD *digest; + PY_EVP_MD *digest; HMAC_CTX *ctx = NULL; HMACobject *self = NULL; int r; @@ -1420,14 +1509,14 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, return NULL; } - digest = py_digest_by_digestmod(module, digestmod); + digest = py_digest_by_digestmod(module, digestmod, Py_ht_mac); if (digest == NULL) { return NULL; } ctx = HMAC_CTX_new(); if (ctx == NULL) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); goto error; } @@ -1437,8 +1526,9 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, (int)key->len, digest, NULL /*impl*/); + PY_EVP_MD_free(digest); if (r == 0) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); goto error; } @@ -1496,9 +1586,11 @@ _hmac_update(HMACobject *self, PyObject *obj) } if (self->lock != NULL) { - ENTER_HASHLIB(self); + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); r = HMAC_Update(self->ctx, (const unsigned char*)view.buf, view.len); - LEAVE_HASHLIB(self); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS } else { r = HMAC_Update(self->ctx, (const unsigned char*)view.buf, view.len); } @@ -1506,7 +1598,7 @@ _hmac_update(HMACobject *self, PyObject *obj) PyBuffer_Release(&view); if (r == 0) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return 0; } return 1; @@ -1526,11 +1618,11 @@ _hashlib_HMAC_copy_impl(HMACobject *self) HMAC_CTX *ctx = HMAC_CTX_new(); if (ctx == NULL) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } if (!locked_HMAC_CTX_copy(ctx, self)) { HMAC_CTX_free(ctx); - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } retval = (HMACobject *)PyObject_New(HMACobject, Py_TYPE(self)); @@ -1596,13 +1688,13 @@ _hmac_digest(HMACobject *self, unsigned char *buf, unsigned int len) return 0; } if (!locked_HMAC_CTX_copy(temp_ctx, self)) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return 0; } int r = HMAC_Final(temp_ctx, buf, &len); HMAC_CTX_free(temp_ctx); if (r == 0) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return 0; } return 1; @@ -1620,7 +1712,7 @@ _hashlib_HMAC_digest_impl(HMACobject *self) unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } int r = _hmac_digest(self, digest, digest_size); if (r == 0) { @@ -1645,7 +1737,7 @@ _hashlib_HMAC_hexdigest_impl(HMACobject *self) unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } int r = _hmac_digest(self, digest, digest_size); if (r == 0) { @@ -1659,7 +1751,7 @@ _hashlib_hmac_get_digest_size(HMACobject *self, void *closure) { unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } return PyLong_FromLong(digest_size); } @@ -1669,7 +1761,7 @@ _hashlib_hmac_get_block_size(HMACobject *self, void *closure) { const EVP_MD *md = HMAC_CTX_get_md(self->ctx); if (md == NULL) { - return _setException(PyExc_ValueError); + return _setException(PyExc_ValueError, NULL); } return PyLong_FromLong(EVP_MD_block_size(md)); } @@ -1822,7 +1914,7 @@ _hashlib_get_fips_mode_impl(PyObject *module) // But 0 is also a valid result value. unsigned long errcode = ERR_peek_last_error(); if (errcode) { - _setException(PyExc_ValueError); + _setException(PyExc_ValueError, NULL); return -1; } } @@ -1998,6 +2090,12 @@ hashlib_clear(PyObject *m) #endif Py_CLEAR(state->constructs); Py_CLEAR(state->unsupported_digestmod_error); + + if (state->hashtable != NULL) { + _Py_hashtable_destroy(state->hashtable); + state->hashtable = NULL; + } + return 0; } @@ -2008,6 +2106,19 @@ hashlib_free(void *m) } /* Py_mod_exec functions */ +static int +hashlib_init_hashtable(PyObject *module) +{ + _hashlibstate *state = get_hashlib_state(module); + + state->hashtable = py_hashentry_table_new(); + if (state->hashtable == NULL) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + static int hashlib_init_evptype(PyObject *module) { @@ -2093,20 +2204,25 @@ hashlib_init_constructors(PyObject *module) } func = PyObject_GetAttrString(module, fdef->ml_name); if (func == NULL) { + Py_DECREF(name_obj); return -1; } - if (PyDict_SetItem(state->constructs, func, name_obj) < 0) { - return -1; - } + int rc = PyDict_SetItem(state->constructs, func, name_obj); Py_DECREF(func); Py_DECREF(name_obj); + if (rc < 0) { + return -1; + } } proxy = PyDictProxy_New(state->constructs); if (proxy == NULL) { return -1; } - if (PyModule_AddObjectRef(module, "_constructors", proxy) < 0) { + + int rc = PyModule_AddObjectRef(module, "_constructors", proxy); + Py_DECREF(proxy); + if (rc < 0) { return -1; } return 0; @@ -2130,6 +2246,7 @@ hashlib_exception(PyObject *module) static PyModuleDef_Slot hashlib_slots[] = { + {Py_mod_exec, hashlib_init_hashtable}, {Py_mod_exec, hashlib_init_evptype}, {Py_mod_exec, hashlib_init_evpxoftype}, {Py_mod_exec, hashlib_init_hmactype}, diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 5984d34cc08290..ba966f568b399a 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -341,11 +341,10 @@ _enter_buffered_busy(buffered *self) : buffered_closed(self))) #define CHECK_CLOSED(self, error_msg) \ - if (IS_CLOSED(self)) { \ + if (IS_CLOSED(self) & (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) { \ PyErr_SetString(PyExc_ValueError, error_msg); \ return NULL; \ - } - + } \ #define VALID_READ_BUFFER(self) \ (self->readable && self->read_end != -1) @@ -530,6 +529,9 @@ buffered_close(buffered *self, PyObject *args) Py_CLEAR(res); } + self->read_end = 0; + self->pos = 0; + end: LEAVE_BUFFERED(self) return res; diff --git a/Modules/_json.c b/Modules/_json.c index e10f83c96c565f..6f68c1f7f9b715 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -321,7 +321,7 @@ raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end) if (decoder == NULL) { return; } - + _Py_IDENTIFIER(JSONDecodeError); PyObject *JSONDecodeError = _PyObject_GetAttrId(decoder, &PyId_JSONDecodeError); Py_DECREF(decoder); diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index c32699cb8ad580..703067cc743a55 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -731,6 +731,13 @@ profiler_clear(ProfilerObject *pObj, PyObject* noarg) Py_RETURN_NONE; } +static int +profiler_traverse(ProfilerObject *op, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(op)); + return 0; +} + static void profiler_dealloc(ProfilerObject *op) { @@ -798,16 +805,15 @@ static PyType_Slot _lsprof_profiler_type_spec_slots[] = { {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, {Py_tp_init, profiler_init}, - {Py_tp_alloc, PyType_GenericAlloc}, - {Py_tp_new, PyType_GenericNew}, - {Py_tp_free, PyObject_Del}, + {Py_tp_traverse, profiler_traverse}, {0, 0} }; static PyType_Spec _lsprof_profiler_type_spec = { .name = "_lsprof.Profiler", .basicsize = sizeof(ProfilerObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = _lsprof_profiler_type_spec_slots, }; diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 2f80bf0496bb3f..915c0c918f6443 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -915,7 +915,7 @@ static PyType_Spec lzma_compressor_type_spec = { // lzma_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .slots = lzma_compressor_type_slots, }; @@ -1359,7 +1359,7 @@ static PyType_Spec lzma_decompressor_type_spec = { // lzma_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .slots = lzma_decompressor_type_slots, }; diff --git a/Modules/_math.c b/Modules/_math.c index 02d8f1c43c8007..68e3a2346925de 100644 --- a/Modules/_math.c +++ b/Modules/_math.c @@ -90,7 +90,7 @@ _Py_acosh(double x) * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] * we have * asinh(x) := x if 1+x*x=1, - * := sign(x)*(log(x)+ln2)) for large |x|, else + * := sign(x)*(log(x)+ln2) for large |x|, else * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) */ diff --git a/Modules/_operator.c b/Modules/_operator.c index f55c2f1d1f415e..f051513fc793a0 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -507,12 +507,12 @@ _operator_indexOf_impl(PyObject *module, PyObject *a, PyObject *b) /*[clinic input] _operator.countOf = _operator.indexOf -Return the number of times b occurs in a. +Return the number of items in a which are, or which equal, b. [clinic start generated code]*/ static Py_ssize_t _operator_countOf_impl(PyObject *module, PyObject *a, PyObject *b) -/*[clinic end generated code: output=9e1623197daf3382 input=0c3a2656add252db]*/ +/*[clinic end generated code: output=9e1623197daf3382 input=93ea57f170f3f0bb]*/ { return PySequence_Count(a, b); } @@ -1004,12 +1004,19 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)ig; } +static int +itemgetter_clear(itemgetterobject *ig) +{ + Py_CLEAR(ig->item); + return 0; +} + static void itemgetter_dealloc(itemgetterobject *ig) { PyTypeObject *tp = Py_TYPE(ig); PyObject_GC_UnTrack(ig); - Py_XDECREF(ig->item); + (void)itemgetter_clear(ig); tp->tp_free(ig); Py_DECREF(tp); } @@ -1017,6 +1024,7 @@ itemgetter_dealloc(itemgetterobject *ig) static int itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(ig)); Py_VISIT(ig->item); return 0; } @@ -1113,6 +1121,7 @@ static PyType_Slot itemgetter_type_slots[] = { {Py_tp_dealloc, itemgetter_dealloc}, {Py_tp_call, itemgetter_call}, {Py_tp_traverse, itemgetter_traverse}, + {Py_tp_clear, itemgetter_clear}, {Py_tp_methods, itemgetter_methods}, {Py_tp_new, itemgetter_new}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -1124,7 +1133,8 @@ static PyType_Spec itemgetter_type_spec = { .name = "operator.itemgetter", .basicsize = sizeof(itemgetterobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = itemgetter_type_slots, }; @@ -1250,12 +1260,19 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)ag; } +static int +attrgetter_clear(attrgetterobject *ag) +{ + Py_CLEAR(ag->attr); + return 0; +} + static void attrgetter_dealloc(attrgetterobject *ag) { PyTypeObject *tp = Py_TYPE(ag); PyObject_GC_UnTrack(ag); - Py_XDECREF(ag->attr); + (void)attrgetter_clear(ag); tp->tp_free(ag); Py_DECREF(tp); } @@ -1264,6 +1281,7 @@ static int attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg) { Py_VISIT(ag->attr); + Py_VISIT(Py_TYPE(ag)); return 0; } @@ -1435,6 +1453,7 @@ static PyType_Slot attrgetter_type_slots[] = { {Py_tp_dealloc, attrgetter_dealloc}, {Py_tp_call, attrgetter_call}, {Py_tp_traverse, attrgetter_traverse}, + {Py_tp_clear, attrgetter_clear}, {Py_tp_methods, attrgetter_methods}, {Py_tp_new, attrgetter_new}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -1446,7 +1465,8 @@ static PyType_Spec attrgetter_type_spec = { .name = "operator.attrgetter", .basicsize = sizeof(attrgetterobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = attrgetter_type_slots, }; @@ -1505,14 +1525,21 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)mc; } +static int +methodcaller_clear(methodcallerobject *mc) +{ + Py_CLEAR(mc->name); + Py_CLEAR(mc->args); + Py_CLEAR(mc->kwds); + return 0; +} + static void methodcaller_dealloc(methodcallerobject *mc) { PyTypeObject *tp = Py_TYPE(mc); PyObject_GC_UnTrack(mc); - Py_XDECREF(mc->name); - Py_XDECREF(mc->args); - Py_XDECREF(mc->kwds); + (void)methodcaller_clear(mc); tp->tp_free(mc); Py_DECREF(tp); } @@ -1520,8 +1547,10 @@ methodcaller_dealloc(methodcallerobject *mc) static int methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg) { + Py_VISIT(mc->name); Py_VISIT(mc->args); Py_VISIT(mc->kwds); + Py_VISIT(Py_TYPE(mc)); return 0; } @@ -1680,6 +1709,7 @@ static PyType_Slot methodcaller_type_slots[] = { {Py_tp_dealloc, methodcaller_dealloc}, {Py_tp_call, methodcaller_call}, {Py_tp_traverse, methodcaller_traverse}, + {Py_tp_clear, methodcaller_clear}, {Py_tp_methods, methodcaller_methods}, {Py_tp_new, methodcaller_new}, {Py_tp_getattro, PyObject_GenericGetAttr}, @@ -1691,7 +1721,8 @@ static PyType_Spec methodcaller_type_spec = { .name = "operator.methodcaller", .basicsize = sizeof(methodcallerobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = methodcaller_type_slots, }; diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 691d4a293e8498..919490c88f7d09 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4527,7 +4527,7 @@ dump(PicklerObject *self, PyObject *obj) * call when setting the reducer_override attribute of the Pickler instance * to a bound method of the same instance. This is important as the Pickler * instance holds a reference to each object it has pickled (through its - * memo): thus, these objects wont be garbage-collected as long as the + * memo): thus, these objects won't be garbage-collected as long as the * Pickler itself is not collected. */ Py_CLEAR(self->reducer_override); return status; @@ -6540,7 +6540,7 @@ do_setitems(UnpicklerObject *self, Py_ssize_t x) return 0; if ((len - x) % 2 != 0) { PickleState *st = _Pickle_GetGlobalState(); - /* Currupt or hostile pickle -- we never write one like this. */ + /* Corrupt or hostile pickle -- we never write one like this. */ PyErr_SetString(st->UnpicklingError, "odd number of items for SETITEMS"); return -1; diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index c27fb1a001d21e..a124255a72cae2 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -34,6 +34,13 @@ class _queue.SimpleQueue "simplequeueobject *" "simplequeue_get_state_by_type(ty [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a4023fe4d198c8d]*/ +static int +simplequeue_clear(simplequeueobject *self) +{ + Py_CLEAR(self->lst); + return 0; +} + static void simplequeue_dealloc(simplequeueobject *self) { @@ -46,7 +53,7 @@ simplequeue_dealloc(simplequeueobject *self) PyThread_release_lock(self->lock); PyThread_free_lock(self->lock); } - Py_XDECREF(self->lst); + (void)simplequeue_clear(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_TYPE(self)->tp_free(self); @@ -57,6 +64,7 @@ static int simplequeue_traverse(simplequeueobject *self, visitproc visit, void *arg) { Py_VISIT(self->lst); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -362,6 +370,7 @@ static PyType_Slot simplequeue_slots[] = { {Py_tp_dealloc, simplequeue_dealloc}, {Py_tp_doc, (void *)simplequeue_new__doc__}, {Py_tp_traverse, simplequeue_traverse}, + {Py_tp_clear, simplequeue_clear}, {Py_tp_members, simplequeue_members}, {Py_tp_methods, simplequeue_methods}, {Py_tp_new, simplequeue_new}, @@ -371,7 +380,8 @@ static PyType_Slot simplequeue_slots[] = { static PyType_Spec simplequeue_spec = { .name = "_queue.SimpleQueue", .basicsize = sizeof(simplequeueobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = simplequeue_slots, }; diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index cae49a009cbcc8..0137e34da650a1 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -597,7 +597,7 @@ _random_exec(PyObject *module) } /* Look up and save int.__abs__, which is needed in random_seed(). */ - PyObject *longval = longval = PyLong_FromLong(0); + PyObject *longval = PyLong_FromLong(0); if (longval == NULL) { return -1; } diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index aba7f6d4b45c22..3974e0b6b47faa 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -64,6 +64,11 @@ #define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #endif +/* Prevent bus errors on platforms requiring aligned accesses such ARM. */ +#if HAVE_ALIGNED_REQUIRED && !defined(NO_MISALIGNED_ACCESSES) +#define NO_MISALIGNED_ACCESSES +#endif + /* mangle names */ #define KeccakF1600_FastLoop_Absorb _PySHA3_KeccakF1600_FastLoop_Absorb #define Keccak_HashFinal _PySHA3_Keccak_HashFinal diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 8da0a64a3f90a4..fd4e619f6a0115 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -44,14 +44,29 @@ pysqlite_new_node(PyObject *key, PyObject *data) return node; } +static int +node_traverse(pysqlite_Node *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->key); + Py_VISIT(self->data); + return 0; +} + +static int +node_clear(pysqlite_Node *self) +{ + Py_CLEAR(self->key); + Py_CLEAR(self->data); + return 0; +} + static void pysqlite_node_dealloc(pysqlite_Node *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_DECREF(self->key); - Py_DECREF(self->data); - + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -88,31 +103,53 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs) return 0; } -static void -pysqlite_cache_dealloc(pysqlite_Cache *self) +static int +cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); - pysqlite_Node* node; - pysqlite_Node* delete_node; + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->mapping); + if (self->decref_factory) { + Py_VISIT(self->factory); + } - if (!self->factory) { - /* constructor failed, just get out of here */ - return; + pysqlite_Node *node = self->first; + while (node) { + Py_VISIT(node); + node = node->next; + } + return 0; +} + +static int +cache_clear(pysqlite_Cache *self) +{ + Py_CLEAR(self->mapping); + if (self->decref_factory) { + Py_CLEAR(self->factory); } /* iterate over all nodes and deallocate them */ - node = self->first; + pysqlite_Node *node = self->first; + self->first = NULL; while (node) { - delete_node = node; + pysqlite_Node *delete_node = node; node = node->next; - Py_DECREF(delete_node); + Py_CLEAR(delete_node); } + return 0; +} - if (self->decref_factory) { - Py_DECREF(self->factory); +static void +pysqlite_cache_dealloc(pysqlite_Cache *self) +{ + if (!self->factory) { + /* constructor failed, just get out of here */ + return; } - Py_DECREF(self->mapping); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -260,14 +297,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args) static PyType_Slot node_slots[] = { {Py_tp_dealloc, pysqlite_node_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, node_traverse}, + {Py_tp_clear, node_clear}, {0, NULL}, }; static PyType_Spec node_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = node_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -283,15 +321,16 @@ static PyMethodDef cache_methods[] = { static PyType_Slot cache_slots[] = { {Py_tp_dealloc, pysqlite_cache_dealloc}, {Py_tp_methods, cache_methods}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cache_init}, + {Py_tp_traverse, cache_traverse}, + {Py_tp_clear, cache_clear}, {0, NULL}, }; static PyType_Spec cache_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cache_slots, }; PyTypeObject *pysqlite_CacheType = NULL; diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h index f231ecc2ae78be..22aa8abf7c4360 100644 --- a/Modules/_sqlite/clinic/connection.c.h +++ b/Modules/_sqlite/clinic/connection.c.h @@ -475,7 +475,7 @@ PyDoc_STRVAR(pysqlite_connection_executescript__doc__, "executescript($self, sql_script, /)\n" "--\n" "\n" -"Executes a multiple SQL statements at once. Non-standard."); +"Executes multiple SQL statements at once. Non-standard."); #define PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF \ {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_O, pysqlite_connection_executescript__doc__}, @@ -710,4 +710,4 @@ pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ss #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ -/*[clinic end generated code: output=c1bf09db3bcd0105 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6c40101de3ae46fc input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h index 7a79d74818a2e2..7e0745f448f5fd 100644 --- a/Modules/_sqlite/clinic/cursor.c.h +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -114,7 +114,7 @@ PyDoc_STRVAR(pysqlite_cursor_executescript__doc__, "executescript($self, sql_script, /)\n" "--\n" "\n" -"Executes a multiple SQL statements at once. Non-standard."); +"Executes multiple SQL statements at once. Non-standard."); #define PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF \ {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_O, pysqlite_cursor_executescript__doc__}, @@ -259,4 +259,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) { return pysqlite_cursor_close_impl(self); } -/*[clinic end generated code: output=6a2d4d49784aa686 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c319842c7e7e4c51 input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index fb5411243c6798..64610393ec1c35 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -87,13 +87,12 @@ pysqlite_connection_init(pysqlite_Connection *self, PyObject *args, } if (PySys_Audit("sqlite3.connect", "O", database_obj) < 0) { + Py_DECREF(database_obj); return -1; } database = PyBytes_AsString(database_obj); - self->initialized = 1; - self->begin_statement = NULL; Py_CLEAR(self->statement_cache); @@ -114,6 +113,10 @@ pysqlite_connection_init(pysqlite_Connection *self, PyObject *args, Py_DECREF(database_obj); + if (self->db == NULL && rc == SQLITE_NOMEM) { + PyErr_NoMemory(); + return -1; + } if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); return -1; @@ -128,7 +131,7 @@ pysqlite_connection_init(pysqlite_Connection *self, PyObject *args, Py_INCREF(isolation_level); } Py_CLEAR(self->isolation_level); - if (pysqlite_connection_set_isolation_level(self, isolation_level, NULL) < 0) { + if (pysqlite_connection_set_isolation_level(self, isolation_level, NULL) != 0) { Py_DECREF(isolation_level); return -1; } @@ -187,6 +190,8 @@ pysqlite_connection_init(pysqlite_Connection *self, PyObject *args, return -1; } + self->initialized = 1; + return 0; } @@ -225,28 +230,51 @@ pysqlite_do_all_statements(pysqlite_Connection *self, int action, } } +static int +connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->isolation_level); + Py_VISIT(self->statement_cache); + Py_VISIT(self->statements); + Py_VISIT(self->cursors); + Py_VISIT(self->row_factory); + Py_VISIT(self->text_factory); + Py_VISIT(self->function_pinboard_trace_callback); + Py_VISIT(self->function_pinboard_progress_handler); + Py_VISIT(self->function_pinboard_authorizer_cb); + Py_VISIT(self->collations); + return 0; +} + +static int +connection_clear(pysqlite_Connection *self) +{ + Py_CLEAR(self->isolation_level); + Py_CLEAR(self->statement_cache); + Py_CLEAR(self->statements); + Py_CLEAR(self->cursors); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->text_factory); + Py_CLEAR(self->function_pinboard_trace_callback); + Py_CLEAR(self->function_pinboard_progress_handler); + Py_CLEAR(self->function_pinboard_authorizer_cb); + Py_CLEAR(self->collations); + return 0; +} + static void -pysqlite_connection_dealloc(pysqlite_Connection *self) +connection_dealloc(pysqlite_Connection *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_XDECREF(self->statement_cache); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); /* Clean up if user has not called .close() explicitly. */ if (self->db) { sqlite3_close_v2(self->db); } - Py_XDECREF(self->isolation_level); - Py_XDECREF(self->function_pinboard_trace_callback); - Py_XDECREF(self->function_pinboard_progress_handler); - Py_XDECREF(self->function_pinboard_authorizer_cb); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->text_factory); - Py_XDECREF(self->collations); - Py_XDECREF(self->statements); - Py_XDECREF(self->cursors); - tp->tp_free(self); Py_DECREF(tp); } @@ -336,6 +364,12 @@ pysqlite_connection_close_impl(pysqlite_Connection *self) return NULL; } + if (!self->initialized) { + PyErr_SetString(pysqlite_ProgrammingError, + "Base Connection.__init__ not called."); + return NULL; + } + pysqlite_do_all_statements(self, ACTION_FINALIZE, 1); if (self->db) { @@ -520,10 +554,17 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val) } else if (PyFloat_Check(py_val)) { sqlite3_result_double(context, PyFloat_AsDouble(py_val)); } else if (PyUnicode_Check(py_val)) { - const char *str = PyUnicode_AsUTF8(py_val); - if (str == NULL) + Py_ssize_t sz; + const char *str = PyUnicode_AsUTF8AndSize(py_val, &sz); + if (str == NULL) { return -1; - sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT); + } + if (sz > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "string is longer than INT_MAX bytes"); + return -1; + } + sqlite3_result_text(context, str, (int)sz, SQLITE_TRANSIENT); } else if (PyObject_CheckBuffer(py_val)) { Py_buffer view; if (PyObject_GetBuffer(py_val, &view, PyBUF_SIMPLE) != 0) { @@ -553,7 +594,6 @@ _pysqlite_build_py_params(sqlite3_context *context, int argc, int i; sqlite3_value* cur_value; PyObject* cur_py_value; - const char* val_str; args = PyTuple_New(argc); if (!args) { @@ -569,15 +609,19 @@ _pysqlite_build_py_params(sqlite3_context *context, int argc, case SQLITE_FLOAT: cur_py_value = PyFloat_FromDouble(sqlite3_value_double(cur_value)); break; - case SQLITE_TEXT: - val_str = (const char*)sqlite3_value_text(cur_value); - cur_py_value = PyUnicode_FromString(val_str); - /* TODO: have a way to show errors here */ - if (!cur_py_value) { - PyErr_Clear(); - cur_py_value = Py_NewRef(Py_None); + case SQLITE_TEXT: { + sqlite3 *db = sqlite3_context_db_handle(context); + const char *text = (const char *)sqlite3_value_text(cur_value); + + if (text == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) { + PyErr_NoMemory(); + goto error; } + + Py_ssize_t size = sqlite3_value_bytes(cur_value); + cur_py_value = PyUnicode_FromStringAndSize(text, size); break; + } case SQLITE_BLOB: { sqlite3 *db = sqlite3_context_db_handle(context); const void *blob = sqlite3_value_blob(cur_value); @@ -825,7 +869,12 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self) static void _destructor(void* args) { + // This function may be called without the GIL held, so we need to ensure + // that we destroy 'args' with the GIL + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); Py_DECREF((PyObject*)args); + PyGILState_Release(gstate); } /*[clinic input] @@ -1233,6 +1282,9 @@ int pysqlite_check_thread(pysqlite_Connection* self) static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* self, void* unused) { + if (!pysqlite_check_connection(self)) { + return NULL; + } return Py_NewRef(self->isolation_level); } @@ -1264,11 +1316,17 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso return -1; } if (isolation_level == Py_None) { - PyObject *res = pysqlite_connection_commit(self, NULL); - if (!res) { - return -1; + /* We might get called during connection init, so we cannot use + * pysqlite_connection_commit() here. */ + if (self->db && !sqlite3_get_autocommit(self->db)) { + int rc; + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_exec(self->db, "COMMIT", NULL, NULL, NULL); + Py_END_ALLOW_THREADS + if (rc != SQLITE_OK) { + return _pysqlite_seterror(self->db, NULL); + } } - Py_DECREF(res); self->begin_statement = NULL; } else { @@ -1314,7 +1372,6 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, PyObject* sql; pysqlite_Statement* statement; PyObject* weakref; - int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1328,31 +1385,11 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType); - if (!statement) { + statement = pysqlite_statement_create(self, sql); + if (statement == NULL) { return NULL; } - statement->db = NULL; - statement->st = NULL; - statement->sql = NULL; - statement->in_use = 0; - statement->in_weakreflist = NULL; - - rc = pysqlite_statement_create(statement, self, sql); - if (rc != SQLITE_OK) { - if (rc == PYSQLITE_TOO_MUCH_SQL) { - PyErr_SetString(pysqlite_Warning, "You can only execute one statement at a time."); - } else if (rc == PYSQLITE_SQL_WRONG_TYPE) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_SetString(pysqlite_Warning, "SQL is of wrong type. Must be string."); - } else { - (void)pysqlite_statement_reset(statement); - _pysqlite_seterror(self->db, NULL); - } - goto error; - } - weakref = PyWeakref_NewRef((PyObject*)statement, NULL); if (weakref == NULL) goto error; @@ -1446,13 +1483,13 @@ _sqlite3.Connection.executescript as pysqlite_connection_executescript sql_script as script_obj: object / -Executes a multiple SQL statements at once. Non-standard. +Executes multiple SQL statements at once. Non-standard. [clinic start generated code]*/ static PyObject * pysqlite_connection_executescript(pysqlite_Connection *self, PyObject *script_obj) -/*[clinic end generated code: output=4c4f9d77aa0ae37d input=c0b14695aa6c81d9]*/ +/*[clinic end generated code: output=4c4f9d77aa0ae37d input=b27ae5c24ffb8b43]*/ { _Py_IDENTIFIER(executescript); PyObject* cursor = 0; @@ -1839,17 +1876,32 @@ pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb) /*[clinic end generated code: output=0705200e9321202a input=bd66f1532c9c54a7]*/ { - const char* method_name; + int commit = 0; PyObject* result; if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) { - method_name = "commit"; - } else { - method_name = "rollback"; + commit = 1; + result = pysqlite_connection_commit_impl(self); } - - result = PyObject_CallMethod((PyObject*)self, method_name, NULL); - if (!result) { + else { + result = pysqlite_connection_rollback_impl(self); + } + + if (result == NULL) { + if (commit) { + /* Commit failed; try to rollback in order to unlock the database. + * If rollback also fails, chain the exceptions. */ + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); + result = pysqlite_connection_rollback_impl(self); + if (result == NULL) { + _PyErr_ChainExceptions(exc, val, tb); + } + else { + Py_DECREF(result); + PyErr_Restore(exc, val, tb); + } + } return NULL; } Py_DECREF(result); @@ -1909,21 +1961,23 @@ static struct PyMemberDef connection_members[] = }; static PyType_Slot connection_slots[] = { - {Py_tp_dealloc, pysqlite_connection_dealloc}, + {Py_tp_dealloc, connection_dealloc}, {Py_tp_doc, (void *)connection_doc}, {Py_tp_methods, connection_methods}, {Py_tp_members, connection_members}, {Py_tp_getset, connection_getset}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_connection_init}, {Py_tp_call, pysqlite_connection_call}, + {Py_tp_traverse, connection_traverse}, + {Py_tp_clear, connection_clear}, {0, NULL}, }; static PyType_Spec connection_spec = { .name = MODULE_NAME ".Connection", .basicsize = sizeof(pysqlite_Connection), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = connection_slots, }; diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 82f6baf6eef3d7..8773c9eac08861 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -93,7 +93,7 @@ typedef struct /* a dictionary of registered collation name => collation callable mappings */ PyObject* collations; - /* Exception objects */ + /* Exception objects: borrowed refs. */ PyObject* Warning; PyObject* Error; PyObject* InterfaceError; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 60dfc7dce8fb5e..36f63863cc1f89 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -81,27 +81,47 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self, return 0; } -static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) +static int +cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->connection); + Py_VISIT(self->description); + Py_VISIT(self->row_cast_map); + Py_VISIT(self->lastrowid); + Py_VISIT(self->row_factory); + Py_VISIT(self->statement); + Py_VISIT(self->next_row); + return 0; +} - /* Reset the statement if the user has not closed the cursor */ +static int +cursor_clear(pysqlite_Cursor *self) +{ + Py_CLEAR(self->connection); + Py_CLEAR(self->description); + Py_CLEAR(self->row_cast_map); + Py_CLEAR(self->lastrowid); + Py_CLEAR(self->row_factory); if (self->statement) { + /* Reset the statement if the user has not closed the cursor */ pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); + Py_CLEAR(self->statement); } + Py_CLEAR(self->next_row); - Py_XDECREF(self->connection); - Py_XDECREF(self->row_cast_map); - Py_XDECREF(self->description); - Py_XDECREF(self->lastrowid); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->next_row); + return 0; +} +static void +cursor_dealloc(pysqlite_Cursor *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } - + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -487,13 +507,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, pysqlite_StatementType)); - if (!self->statement) { - goto error; - } - rc = pysqlite_statement_create(self->statement, self->connection, operation); - if (rc != SQLITE_OK) { - Py_CLEAR(self->statement); + pysqlite_statement_create(self->connection, operation)); + if (self->statement == NULL) { goto error; } } @@ -670,12 +685,12 @@ _sqlite3.Cursor.executescript as pysqlite_cursor_executescript sql_script as script_obj: object / -Executes a multiple SQL statements at once. Non-standard. +Executes multiple SQL statements at once. Non-standard. [clinic start generated code]*/ static PyObject * pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) -/*[clinic end generated code: output=115a8132b0f200fe input=38c6fa6de570bb9b]*/ +/*[clinic end generated code: output=115a8132b0f200fe input=ba3ec59df205e362]*/ { _Py_IDENTIFIER(commit); const char* script_cstr; @@ -1006,21 +1021,23 @@ static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); static PyType_Slot cursor_slots[] = { - {Py_tp_dealloc, pysqlite_cursor_dealloc}, + {Py_tp_dealloc, cursor_dealloc}, {Py_tp_doc, (void *)cursor_doc}, {Py_tp_iter, PyObject_SelfIter}, {Py_tp_iternext, pysqlite_cursor_iternext}, {Py_tp_methods, cursor_methods}, {Py_tp_members, cursor_members}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cursor_init}, + {Py_tp_traverse, cursor_traverse}, + {Py_tp_clear, cursor_clear}, {0, NULL}, }; static PyType_Spec cursor_spec = { .name = MODULE_NAME ".Cursor", .basicsize = sizeof(pysqlite_Cursor), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = cursor_slots, }; diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index a5e5525481f756..ba70a6c51f4409 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -273,51 +273,58 @@ static PyMethodDef module_methods[] = { {NULL, NULL} }; -static int add_integer_constants(PyObject *module) { - int ret = 0; - - ret += PyModule_AddIntMacro(module, PARSE_DECLTYPES); - ret += PyModule_AddIntMacro(module, PARSE_COLNAMES); - ret += PyModule_AddIntMacro(module, SQLITE_OK); - ret += PyModule_AddIntMacro(module, SQLITE_DENY); - ret += PyModule_AddIntMacro(module, SQLITE_IGNORE); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_INDEX); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TABLE); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_INDEX); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TABLE); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_TRIGGER); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TEMP_VIEW); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_TRIGGER); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VIEW); - ret += PyModule_AddIntMacro(module, SQLITE_DELETE); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_INDEX); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TABLE); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_INDEX); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TABLE); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_TRIGGER); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TEMP_VIEW); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_TRIGGER); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_VIEW); - ret += PyModule_AddIntMacro(module, SQLITE_INSERT); - ret += PyModule_AddIntMacro(module, SQLITE_PRAGMA); - ret += PyModule_AddIntMacro(module, SQLITE_READ); - ret += PyModule_AddIntMacro(module, SQLITE_SELECT); - ret += PyModule_AddIntMacro(module, SQLITE_TRANSACTION); - ret += PyModule_AddIntMacro(module, SQLITE_UPDATE); - ret += PyModule_AddIntMacro(module, SQLITE_ATTACH); - ret += PyModule_AddIntMacro(module, SQLITE_DETACH); - ret += PyModule_AddIntMacro(module, SQLITE_ALTER_TABLE); - ret += PyModule_AddIntMacro(module, SQLITE_REINDEX); - ret += PyModule_AddIntMacro(module, SQLITE_ANALYZE); - ret += PyModule_AddIntMacro(module, SQLITE_CREATE_VTABLE); - ret += PyModule_AddIntMacro(module, SQLITE_DROP_VTABLE); - ret += PyModule_AddIntMacro(module, SQLITE_FUNCTION); - ret += PyModule_AddIntMacro(module, SQLITE_SAVEPOINT); +static int +add_integer_constants(PyObject *module) { +#define ADD_INT(ival) \ + do { \ + if (PyModule_AddIntConstant(module, #ival, ival) < 0) { \ + return -1; \ + } \ + } while (0); \ + + ADD_INT(PARSE_DECLTYPES); + ADD_INT(PARSE_COLNAMES); + ADD_INT(SQLITE_OK); + ADD_INT(SQLITE_DENY); + ADD_INT(SQLITE_IGNORE); + ADD_INT(SQLITE_CREATE_INDEX); + ADD_INT(SQLITE_CREATE_TABLE); + ADD_INT(SQLITE_CREATE_TEMP_INDEX); + ADD_INT(SQLITE_CREATE_TEMP_TABLE); + ADD_INT(SQLITE_CREATE_TEMP_TRIGGER); + ADD_INT(SQLITE_CREATE_TEMP_VIEW); + ADD_INT(SQLITE_CREATE_TRIGGER); + ADD_INT(SQLITE_CREATE_VIEW); + ADD_INT(SQLITE_DELETE); + ADD_INT(SQLITE_DROP_INDEX); + ADD_INT(SQLITE_DROP_TABLE); + ADD_INT(SQLITE_DROP_TEMP_INDEX); + ADD_INT(SQLITE_DROP_TEMP_TABLE); + ADD_INT(SQLITE_DROP_TEMP_TRIGGER); + ADD_INT(SQLITE_DROP_TEMP_VIEW); + ADD_INT(SQLITE_DROP_TRIGGER); + ADD_INT(SQLITE_DROP_VIEW); + ADD_INT(SQLITE_INSERT); + ADD_INT(SQLITE_PRAGMA); + ADD_INT(SQLITE_READ); + ADD_INT(SQLITE_SELECT); + ADD_INT(SQLITE_TRANSACTION); + ADD_INT(SQLITE_UPDATE); + ADD_INT(SQLITE_ATTACH); + ADD_INT(SQLITE_DETACH); + ADD_INT(SQLITE_ALTER_TABLE); + ADD_INT(SQLITE_REINDEX); + ADD_INT(SQLITE_ANALYZE); + ADD_INT(SQLITE_CREATE_VTABLE); + ADD_INT(SQLITE_DROP_VTABLE); + ADD_INT(SQLITE_FUNCTION); + ADD_INT(SQLITE_SAVEPOINT); #if SQLITE_VERSION_NUMBER >= 3008003 - ret += PyModule_AddIntMacro(module, SQLITE_RECURSIVE); + ADD_INT(SQLITE_RECURSIVE); #endif - ret += PyModule_AddIntMacro(module, SQLITE_DONE); - return ret; + ADD_INT(SQLITE_DONE); +#undef ADD_INT + return 0; } static struct PyModuleDef _sqlite3module = { diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7d2d7ade591467..800eef8794b455 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -30,26 +30,34 @@ pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args, return 0; } +static int +pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self) { PyTypeObject *tp = Py_TYPE(self); - + PyObject_GC_UnTrack(self); tp->tp_free(self); Py_DECREF(tp); } static PyType_Slot type_slots[] = { {Py_tp_dealloc, pysqlite_prepare_protocol_dealloc}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_prepare_protocol_init}, + {Py_tp_traverse, pysqlite_prepare_protocol_traverse}, {0, NULL}, }; static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = type_slots, }; diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index f9dfcbd5d615e5..643194df040755 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -31,14 +31,29 @@ class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ -static void -pysqlite_row_dealloc(pysqlite_Row *self) +static int +row_clear(pysqlite_Row *self) { - PyTypeObject *tp = Py_TYPE(self); + Py_CLEAR(self->data); + Py_CLEAR(self->description); + return 0; +} - Py_XDECREF(self->data); - Py_XDECREF(self->description); +static int +row_traverse(pysqlite_Row *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->data); + Py_VISIT(self->description); + return 0; +} +static void +pysqlite_row_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -231,13 +246,16 @@ static PyType_Slot row_slots[] = { {Py_sq_length, pysqlite_row_length}, {Py_sq_item, pysqlite_row_item}, {Py_tp_new, pysqlite_row_new}, + {Py_tp_traverse, row_traverse}, + {Py_tp_clear, row_clear}, {0, NULL}, }; static PyType_Spec row_spec = { .name = MODULE_NAME ".Row", .basicsize = sizeof(pysqlite_Row), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = row_slots, }; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 57026270e1eeb5..c875eb0cd74a40 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -48,7 +48,8 @@ typedef enum { TYPE_UNKNOWN } parameter_type; -int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql) +pysqlite_Statement * +pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) { const char* tail; int rc; @@ -56,27 +57,36 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con Py_ssize_t sql_cstr_len; const char* p; - self->st = NULL; - self->in_use = 0; - assert(PyUnicode_Check(sql)); sql_cstr = PyUnicode_AsUTF8AndSize(sql, &sql_cstr_len); if (sql_cstr == NULL) { - rc = PYSQLITE_SQL_WRONG_TYPE; - return rc; + PyErr_Format(pysqlite_Warning, + "SQL is of wrong type ('%s'). Must be string.", + Py_TYPE(sql)->tp_name); + return NULL; } if (strlen(sql_cstr) != (size_t)sql_cstr_len) { - PyErr_SetString(PyExc_ValueError, "the query contains a null character"); - return PYSQLITE_SQL_WRONG_TYPE; + PyErr_SetString(PyExc_ValueError, + "the query contains a null character"); + return NULL; } - self->in_weakreflist = NULL; + pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement, + pysqlite_StatementType); + if (self == NULL) { + return NULL; + } + + self->db = connection->db; + self->st = NULL; self->sql = Py_NewRef(sql); + self->in_use = 0; + self->is_dml = 0; + self->in_weakreflist = NULL; /* Determine if the statement is a DML statement. SELECT is the only exception. See #9924. */ - self->is_dml = 0; for (p = sql_cstr; *p != 0; p++) { switch (*p) { case ' ': @@ -94,22 +104,33 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con } Py_BEGIN_ALLOW_THREADS - rc = sqlite3_prepare_v2(connection->db, + rc = sqlite3_prepare_v2(self->db, sql_cstr, -1, &self->st, &tail); Py_END_ALLOW_THREADS - self->db = connection->db; + PyObject_GC_Track(self); + + if (rc != SQLITE_OK) { + _pysqlite_seterror(self->db, NULL); + goto error; + } if (rc == SQLITE_OK && pysqlite_check_remaining_sql(tail)) { (void)sqlite3_finalize(self->st); self->st = NULL; - rc = PYSQLITE_TOO_MUCH_SQL; + PyErr_SetString(pysqlite_Warning, + "You can only execute one statement at a time."); + goto error; } - return rc; + return self; + +error: + Py_DECREF(self); + return NULL; } int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter) @@ -369,28 +390,39 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) } static void -pysqlite_statement_dealloc(pysqlite_Statement *self) +stmt_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); - + PyObject_GC_UnTrack(self); + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject*)self); + } if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); Py_END_ALLOW_THREADS + self->st = 0; } - - self->st = NULL; - - Py_XDECREF(self->sql); - - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject*)self); - } - + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } +static int +stmt_clear(pysqlite_Statement *self) +{ + Py_CLEAR(self->sql); + return 0; +} + +static int +stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->sql); + return 0; +} + /* * Checks if there is anything left in an SQL string after SQLite compiled it. * This is used to check if somebody tried to execute more than one SQL command @@ -467,15 +499,17 @@ static PyMemberDef stmt_members[] = { }; static PyType_Slot stmt_slots[] = { {Py_tp_members, stmt_members}, - {Py_tp_dealloc, pysqlite_statement_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_dealloc, stmt_dealloc}, + {Py_tp_traverse, stmt_traverse}, + {Py_tp_clear, stmt_clear}, {0, NULL}, }; static PyType_Spec stmt_spec = { .name = MODULE_NAME ".Statement", .basicsize = sizeof(pysqlite_Statement), - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION), .slots = stmt_slots, }; PyTypeObject *pysqlite_StatementType = NULL; diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index 56ff7271448d1c..e8c86a0ec963fd 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -29,9 +29,6 @@ #include "connection.h" #include "sqlite3.h" -#define PYSQLITE_TOO_MUCH_SQL (-100) -#define PYSQLITE_SQL_WRONG_TYPE (-101) - typedef struct { PyObject_HEAD @@ -45,7 +42,7 @@ typedef struct extern PyTypeObject *pysqlite_StatementType; -int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); +pysqlite_Statement *pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql); int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter); void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters); diff --git a/Modules/_sre.c b/Modules/_sre.c index 9d0fc4ab7c03ab..d21b533530187e 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -15,7 +15,7 @@ * 2001-05-14 fl fixes for 1.5.2 compatibility * 2001-07-01 fl added BIGCHARSET support (from Martin von Loewis) * 2001-10-18 fl fixed group reset issue (from Matthew Mueller) - * 2001-10-20 fl added split primitive; reenable unicode for 1.6/2.0/2.1 + * 2001-10-20 fl added split primitive; re-enable unicode for 1.6/2.0/2.1 * 2001-10-21 fl added sub/subn primitive * 2001-10-24 fl added finditer primitive (for 2.2 only) * 2001-12-07 fl fixed memory leak in sub/subn (Guido van Rossum) @@ -562,17 +562,36 @@ pattern_error(Py_ssize_t status) } } +static int +pattern_traverse(PatternObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->groupindex); + Py_VISIT(self->indexgroup); + Py_VISIT(self->pattern); + return 0; +} + +static int +pattern_clear(PatternObject *self) +{ + Py_CLEAR(self->groupindex); + Py_CLEAR(self->indexgroup); + Py_CLEAR(self->pattern); + return 0; +} + static void pattern_dealloc(PatternObject* self) { PyTypeObject *tp = Py_TYPE(self); - if (self->weakreflist != NULL) + PyObject_GC_UnTrack(self); + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); - Py_XDECREF(self->pattern); - Py_XDECREF(self->groupindex); - Py_XDECREF(self->indexgroup); - PyObject_Free(self); + } + (void)pattern_clear(self); + tp->tp_free(self); Py_DECREF(tp); } @@ -1396,7 +1415,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, module_state->Pattern_Type, n); + self = PyObject_GC_NewVar(PatternObject, module_state->Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -1416,6 +1435,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, break; } } + PyObject_GC_Track(self); if (PyErr_Occurred()) { Py_DECREF(self); @@ -1937,15 +1957,33 @@ _validate(PatternObject *self) /* -------------------------------------------------------------------- */ /* match methods */ +static int +match_traverse(MatchObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->string); + Py_VISIT(self->regs); + Py_VISIT(self->pattern); + return 0; +} + +static int +match_clear(MatchObject *self) +{ + Py_CLEAR(self->string); + Py_CLEAR(self->regs); + Py_CLEAR(self->pattern); + return 0; +} + static void match_dealloc(MatchObject* self) { PyTypeObject *tp = Py_TYPE(self); - Py_XDECREF(self->regs); - Py_XDECREF(self->string); - Py_DECREF(self->pattern); - PyObject_Free(self); + PyObject_GC_UnTrack(self); + (void)match_clear(self); + tp->tp_free(self); Py_DECREF(tp); } @@ -2391,9 +2429,9 @@ pattern_new_match(_sremodulestate* module_state, /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, - module_state->Match_Type, - 2*(pattern->groups+1)); + match = PyObject_GC_NewVar(MatchObject, + module_state->Match_Type, + 2*(pattern->groups+1)); if (!match) return NULL; @@ -2426,6 +2464,7 @@ pattern_new_match(_sremodulestate* module_state, match->lastindex = state->lastindex; + PyObject_GC_Track(match); return (PyObject*) match; } else if (status == 0) { @@ -2444,14 +2483,30 @@ pattern_new_match(_sremodulestate* module_state, /* -------------------------------------------------------------------- */ /* scanner methods (experimental) */ +static int +scanner_traverse(ScannerObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->pattern); + return 0; +} + +static int +scanner_clear(ScannerObject *self) +{ + Py_CLEAR(self->pattern); + return 0; +} + static void scanner_dealloc(ScannerObject* self) { PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); state_fini(&self->state); - Py_XDECREF(self->pattern); - PyObject_Free(self); + (void)scanner_clear(self); + tp->tp_free(self); Py_DECREF(tp); } @@ -2548,7 +2603,7 @@ pattern_scanner(_sremodulestate *module_state, ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, module_state->Scanner_Type); + scanner = PyObject_GC_New(ScannerObject, module_state->Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2562,6 +2617,7 @@ pattern_scanner(_sremodulestate *module_state, Py_INCREF(self); scanner->pattern = (PyObject*) self; + PyObject_GC_Track(scanner); return (PyObject*) scanner; } @@ -2683,6 +2739,8 @@ static PyType_Slot pattern_slots[] = { {Py_tp_methods, pattern_methods}, {Py_tp_members, pattern_members}, {Py_tp_getset, pattern_getset}, + {Py_tp_traverse, pattern_traverse}, + {Py_tp_clear, pattern_clear}, {0, NULL}, }; @@ -2691,7 +2749,7 @@ static PyType_Spec pattern_spec = { .basicsize = sizeof(PatternObject), .itemsize = sizeof(SRE_CODE), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), .slots = pattern_slots, }; @@ -2741,6 +2799,8 @@ static PyType_Slot match_slots[] = { {Py_tp_methods, match_methods}, {Py_tp_members, match_members}, {Py_tp_getset, match_getset}, + {Py_tp_traverse, match_traverse}, + {Py_tp_clear, match_clear}, /* As mapping. * @@ -2757,7 +2817,7 @@ static PyType_Spec match_spec = { .basicsize = sizeof(MatchObject), .itemsize = sizeof(Py_ssize_t), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), .slots = match_slots, }; @@ -2777,6 +2837,8 @@ static PyType_Slot scanner_slots[] = { {Py_tp_dealloc, scanner_dealloc}, {Py_tp_methods, scanner_methods}, {Py_tp_members, scanner_members}, + {Py_tp_traverse, scanner_traverse}, + {Py_tp_clear, scanner_clear}, {0, NULL}, }; @@ -2784,7 +2846,7 @@ static PyType_Spec scanner_spec = { .name = "_" SRE_MODULE ".SRE_Scanner", .basicsize = sizeof(ScannerObject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), .slots = scanner_slots, }; diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 5f03214ea3eedc..6c63301b2a7d8d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -434,11 +434,10 @@ static PyType_Slot sslerror_type_slots[] = { }; static PyType_Spec sslerror_type_spec = { - "ssl.SSLError", - sizeof(PyOSErrorObject), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE, - sslerror_type_slots + .name = "ssl.SSLError", + .basicsize = sizeof(PyOSErrorObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), + .slots = sslerror_type_slots }; static void @@ -698,10 +697,9 @@ _setSSLError (_sslmodulestate *state, const char *errstr, int errcode, const cha } static int -_ssl_deprecated(const char* name, int stacklevel) { - return PyErr_WarnFormat( - PyExc_DeprecationWarning, stacklevel, - "ssl module: %s is deprecated", name +_ssl_deprecated(const char* msg, int stacklevel) { + return PyErr_WarnEx( + PyExc_DeprecationWarning, msg, stacklevel ); } @@ -789,7 +787,23 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, SSL_CTX *ctx = sslctx->ctx; _PySSLError err = { 0 }; - self = PyObject_New(PySSLSocket, get_state_ctx(sslctx)->PySSLSocket_Type); + if ((socket_type == PY_SSL_SERVER) && + (sslctx->protocol == PY_SSL_VERSION_TLS_CLIENT)) { + _setSSLError(get_state_ctx(sslctx), + "Cannot create a server socket with a " + "PROTOCOL_TLS_CLIENT context", 0, __FILE__, __LINE__); + return NULL; + } + if ((socket_type == PY_SSL_CLIENT) && + (sslctx->protocol == PY_SSL_VERSION_TLS_SERVER)) { + _setSSLError(get_state_ctx(sslctx), + "Cannot create a client socket with a " + "PROTOCOL_TLS_SERVER context", 0, __FILE__, __LINE__); + return NULL; + } + + self = PyObject_GC_New(PySSLSocket, + get_state_ctx(sslctx)->PySSLSocket_Type); if (self == NULL) return NULL; @@ -896,6 +910,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, return NULL; } } + + PyObject_GC_Track(self); return self; } @@ -2169,6 +2185,7 @@ PySSL_traverse(PySSLSocket *self, visitproc visit, void *arg) Py_VISIT(self->exc_type); Py_VISIT(self->exc_value); Py_VISIT(self->exc_tb); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -2185,13 +2202,15 @@ static void PySSL_dealloc(PySSLSocket *self) { PyTypeObject *tp = Py_TYPE(self); - if (self->ssl) + PyObject_GC_UnTrack(self); + if (self->ssl) { SSL_free(self->ssl); + } Py_XDECREF(self->Socket); Py_XDECREF(self->ctx); Py_XDECREF(self->server_hostname); Py_XDECREF(self->owner); - PyObject_Free(self); + PyObject_GC_Del(self); Py_DECREF(tp); } @@ -2327,7 +2346,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) do { PySSL_BEGIN_ALLOW_THREADS - retval = SSL_write_ex(self->ssl, b->buf, (int)b->len, &count); + retval = SSL_write_ex(self->ssl, b->buf, (size_t)b->len, &count); err = _PySSL_errno(retval == 0, self->ssl, retval); PySSL_END_ALLOW_THREADS self->err = err; @@ -2399,7 +2418,7 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self) /*[clinic input] _ssl._SSLSocket.read - size as len: int + size as len: Py_ssize_t [ buffer: Py_buffer(accept={rwbuffer}) ] @@ -2409,9 +2428,9 @@ Read up to size bytes from the SSL socket. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, - Py_buffer *buffer) -/*[clinic end generated code: output=00097776cec2a0af input=ff157eb918d0905b]*/ +_ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, + int group_right_1, Py_buffer *buffer) +/*[clinic end generated code: output=49b16e6406023734 input=ec48bf622be1c4a1]*/ { PyObject *dest = NULL; char *mem; @@ -2479,7 +2498,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, do { PySSL_BEGIN_ALLOW_THREADS - retval = SSL_read_ex(self->ssl, mem, len, &count); + retval = SSL_read_ex(self->ssl, mem, (size_t)len, &count); err = _PySSL_errno(retval == 0, self->ssl, retval); PySSL_END_ALLOW_THREADS self->err = err; @@ -2903,11 +2922,11 @@ static PyType_Slot PySSLSocket_slots[] = { }; static PyType_Spec PySSLSocket_spec = { - "_ssl._SSLSocket", - sizeof(PySSLSocket), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, - PySSLSocket_slots, + .name = "_ssl._SSLSocket", + .basicsize = sizeof(PySSLSocket), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC), + .slots = PySSLSocket_slots, }; /* @@ -2975,7 +2994,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) switch(proto_version) { #if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) case PY_SSL_VERSION_SSL3: - PY_SSL_DEPRECATED("PROTOCOL_SSLv3", 2, NULL); + PY_SSL_DEPRECATED("ssl.PROTOCOL_SSLv3 is deprecated", 2, NULL); method = SSLv3_method(); break; #endif @@ -2983,7 +3002,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) !defined(OPENSSL_NO_TLS1) && \ !defined(OPENSSL_NO_TLS1_METHOD)) case PY_SSL_VERSION_TLS1: - PY_SSL_DEPRECATED("PROTOCOL_TLSv1", 2, NULL); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1 is deprecated", 2, NULL); method = TLSv1_method(); break; #endif @@ -2991,7 +3010,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) !defined(OPENSSL_NO_TLS1_1) && \ !defined(OPENSSL_NO_TLS1_1_METHOD)) case PY_SSL_VERSION_TLS1_1: - PY_SSL_DEPRECATED("PROTOCOL_TLSv1_1", 2, NULL); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_1 is deprecated", 2, NULL); method = TLSv1_1_method(); break; #endif @@ -2999,12 +3018,12 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) !defined(OPENSSL_NO_TLS1_2) && \ !defined(OPENSSL_NO_TLS1_2_METHOD)) case PY_SSL_VERSION_TLS1_2: - PY_SSL_DEPRECATED("PROTOCOL_TLSv1_2", 2, NULL); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_2 is deprecated", 2, NULL); method = TLSv1_2_method(); break; #endif case PY_SSL_VERSION_TLS: - PY_SSL_DEPRECATED("PROTOCOL_TLS", 2, NULL); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLS is deprecated", 2, NULL); method = TLS_method(); break; case PY_SSL_VERSION_TLS_CLIENT: @@ -3159,6 +3178,7 @@ context_traverse(PySSLContext *self, visitproc visit, void *arg) { Py_VISIT(self->set_sni_cb); Py_VISIT(self->msg_cb); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -3427,13 +3447,13 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) /* check for deprecations and supported values */ switch(v) { case PY_PROTO_SSLv3: - PY_SSL_DEPRECATED("TLSVersion.SSLv3", 2, -1); + PY_SSL_DEPRECATED("ssl.TLSVersion.SSLv3 is deprecated", 2, -1); break; case PY_PROTO_TLSv1: - PY_SSL_DEPRECATED("TLSVersion.TLSv1", 2, -1); + PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1 is deprecated", 2, -1); break; case PY_PROTO_TLSv1_1: - PY_SSL_DEPRECATED("TLSVersion.TLSv1_1", 2, -1); + PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1_1 is deprecated", 2, -1); break; case PY_PROTO_MINIMUM_SUPPORTED: case PY_PROTO_MAXIMUM_SUPPORTED: @@ -3567,7 +3587,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c) long new_opts, opts, set, clear; long opt_no = ( SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | - SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_2 + SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 ); if (!PyArg_Parse(arg, "l", &new_opts)) @@ -3577,7 +3597,7 @@ set_options(PySSLContext *self, PyObject *arg, void *c) set = ~opts & new_opts; if ((set & opt_no) != 0) { - if (_ssl_deprecated("Setting OP_NO_SSL* or SSL_NO_TLS* options is " + if (_ssl_deprecated("ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are " "deprecated", 2) < 0) { return -1; } @@ -4027,7 +4047,7 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, goto error; } - /* validata cadata type and load cadata */ + /* validate cadata type and load cadata */ if (cadata) { if (PyUnicode_Check(cadata)) { PyObject *cadata_ascii = PyUnicode_AsASCIIString(cadata); @@ -4641,11 +4661,11 @@ static PyType_Slot PySSLContext_slots[] = { }; static PyType_Spec PySSLContext_spec = { - "_ssl._SSLContext", - sizeof(PySSLContext), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE, - PySSLContext_slots, + .name = "_ssl._SSLContext", + .basicsize = sizeof(PySSLContext), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = PySSLContext_slots, }; @@ -4689,10 +4709,18 @@ _ssl_MemoryBIO_impl(PyTypeObject *type) return (PyObject *) self; } +static int +memory_bio_traverse(PySSLMemoryBIO *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void memory_bio_dealloc(PySSLMemoryBIO *self) { PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); BIO_free(self->bio); Py_TYPE(self)->tp_free(self); Py_DECREF(tp); @@ -4843,15 +4871,16 @@ static PyType_Slot PySSLMemoryBIO_slots[] = { {Py_tp_getset, memory_bio_getsetlist}, {Py_tp_new, _ssl_MemoryBIO}, {Py_tp_dealloc, memory_bio_dealloc}, + {Py_tp_traverse, memory_bio_traverse}, {0, 0}, }; static PyType_Spec PySSLMemoryBIO_spec = { - "_ssl.MemoryBIO", - sizeof(PySSLMemoryBIO), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, - PySSLMemoryBIO_slots, + .name = "_ssl.MemoryBIO", + .basicsize = sizeof(PySSLMemoryBIO), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC), + .slots = PySSLMemoryBIO_slots, }; /* @@ -4934,6 +4963,7 @@ static int PySSLSession_traverse(PySSLSession *self, visitproc visit, void *arg) { Py_VISIT(self->ctx); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -5022,11 +5052,11 @@ static PyType_Slot PySSLSession_slots[] = { }; static PyType_Spec PySSLSession_spec = { - "_ssl.SSLSession", - sizeof(PySSLSession), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE, - PySSLSession_slots, + .name = "_ssl.SSLSession", + .basicsize = sizeof(PySSLSession), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = PySSLSession_slots, }; @@ -5130,7 +5160,7 @@ static PyObject * _ssl_RAND_pseudo_bytes_impl(PyObject *module, int n) /*[clinic end generated code: output=b1509e937000e52d input=58312bd53f9bbdd0]*/ { - PY_SSL_DEPRECATED("RAND_pseudo_bytes", 1, NULL); + PY_SSL_DEPRECATED("ssl.RAND_pseudo_bytes() is deprecated", 1, NULL); return PySSL_RAND(module, n, 1); } diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 26ebacba642a4f..c5c942820b66fa 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -390,6 +390,19 @@ static PyTypeObject _HashInheritanceTester_Type = { PyType_GenericNew, /* tp_new */ }; +static PyObject* +pycompilestring(PyObject* self, PyObject *obj) { + if (PyBytes_CheckExact(obj) == 0) { + PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); + return NULL; + } + const char *the_string = PyBytes_AsString(obj); + if (the_string == NULL) { + return NULL; + } + return Py_CompileString(the_string, "", Py_file_input); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -2342,16 +2355,22 @@ test_long_numbits(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -/* Example passing NULLs to PyObject_Str(NULL). */ +static PyObject * +pyobject_repr_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyObject_Repr(NULL); +} static PyObject * -test_null_strings(PyObject *self, PyObject *Py_UNUSED(ignored)) +pyobject_str_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *o1 = PyObject_Str(NULL), *o2 = PyObject_Str(NULL); - PyObject *tuple = PyTuple_Pack(2, o1, o2); - Py_XDECREF(o1); - Py_XDECREF(o2); - return tuple; + return PyObject_Str(NULL); +} + +static PyObject * +pyobject_bytes_from_null(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyObject_Bytes(NULL); } static PyObject * @@ -3860,6 +3879,25 @@ test_structseq_newtype_doesnt_leak(PyObject *Py_UNUSED(self), Py_RETURN_NONE; } +static PyObject * +test_structseq_newtype_null_descr_doc(PyObject *Py_UNUSED(self), + PyObject *Py_UNUSED(args)) +{ + PyStructSequence_Field descr_fields[1] = { + (PyStructSequence_Field){NULL, NULL} + }; + // Test specifically for NULL .doc field. + PyStructSequence_Desc descr = {"_testcapi.test_descr", NULL, &descr_fields[0], 0}; + + PyTypeObject* structseq_type = PyStructSequence_NewType(&descr); + assert(structseq_type != NULL); + assert(PyType_Check(structseq_type)); + assert(PyType_FastSubclass(structseq_type, Py_TPFLAGS_TUPLE_SUBCLASS)); + Py_DECREF(structseq_type); + + Py_RETURN_NONE; +} + static PyObject * test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored)) { @@ -4810,6 +4848,10 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self, PyObject *Py_UNUSED(args static PyObject* check_pyobject_freed_is_freed(PyObject *self, PyObject *Py_UNUSED(args)) { + /* This test would fail if run with the address sanitizer */ +#ifdef _Py_ADDRESS_SANITIZER + Py_RETURN_NONE; +#else PyObject *op = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type); if (op == NULL) { return NULL; @@ -4819,6 +4861,7 @@ check_pyobject_freed_is_freed(PyObject *self, PyObject *Py_UNUSED(args)) Py_SET_REFCNT(op, 1); /* object memory is freed! */ return test_pyobject_is_freed("check_pyobject_freed_is_freed", op); +#endif } @@ -5239,7 +5282,7 @@ encode_locale_ex(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "unsupported error handler"); break; default: - PyErr_SetString(PyExc_ValueError, "unknow error code"); + PyErr_SetString(PyExc_ValueError, "unknown error code"); break; } return res; @@ -5282,7 +5325,7 @@ decode_locale_ex(PyObject *self, PyObject *args) PyErr_SetString(PyExc_ValueError, "unsupported error handler"); break; default: - PyErr_SetString(PyExc_ValueError, "unknow error code"); + PyErr_SetString(PyExc_ValueError, "unknown error code"); break; } return res; @@ -5436,9 +5479,6 @@ pynumber_tobase(PyObject *module, PyObject *args) } -static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); - - static PyObject* test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored)) { @@ -5577,6 +5617,8 @@ test_fatal_error(PyObject *self, PyObject *args) } +static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); +static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -5618,6 +5660,8 @@ static PyMethodDef TestMethods[] = { {"test_decref_doesnt_leak", test_decref_doesnt_leak, METH_NOARGS}, {"test_structseq_newtype_doesnt_leak", test_structseq_newtype_doesnt_leak, METH_NOARGS}, + {"test_structseq_newtype_null_descr_doc", + test_structseq_newtype_null_descr_doc, METH_NOARGS}, {"test_incref_decref_API", test_incref_decref_API, METH_NOARGS}, {"test_long_and_overflow", test_long_and_overflow, METH_NOARGS}, {"test_long_as_double", test_long_as_double, METH_NOARGS}, @@ -5628,7 +5672,9 @@ static PyMethodDef TestMethods[] = { {"test_k_code", test_k_code, METH_NOARGS}, {"test_empty_argparse", test_empty_argparse, METH_NOARGS}, {"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS}, - {"test_null_strings", test_null_strings, METH_NOARGS}, + {"pyobject_repr_from_null", pyobject_repr_from_null, METH_NOARGS}, + {"pyobject_str_from_null", pyobject_str_from_null, METH_NOARGS}, + {"pyobject_bytes_from_null", pyobject_bytes_from_null, METH_NOARGS}, {"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS}, {"test_with_docstring", test_with_docstring, METH_NOARGS, PyDoc_STR("This is a pretty normal docstring.")}, @@ -5682,6 +5728,8 @@ static PyMethodDef TestMethods[] = { {"getargs_s", getargs_s, METH_VARARGS}, {"getargs_s_star", getargs_s_star, METH_VARARGS}, {"getargs_s_hash", getargs_s_hash, METH_VARARGS}, + {"getargs_s_hash_int", (PyCFunction)(void(*)(void))getargs_s_hash_int, + METH_VARARGS|METH_KEYWORDS}, {"getargs_z", getargs_z, METH_VARARGS}, {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"getargs_z_hash", getargs_z_hash, METH_VARARGS}, @@ -5791,6 +5839,7 @@ static PyMethodDef TestMethods[] = { {"return_null_without_error", return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, + {"Py_CompileString", pycompilestring, METH_O}, {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, @@ -6573,6 +6622,13 @@ heapctype_init(PyObject *self, PyObject *args, PyObject *kwargs) return 0; } +static int +heapgcctype_traverse(HeapCTypeObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void heapgcctype_dealloc(HeapCTypeObject *self) { @@ -6586,6 +6642,7 @@ static PyType_Slot HeapGcCType_slots[] = { {Py_tp_init, heapctype_init}, {Py_tp_members, heapctype_members}, {Py_tp_dealloc, heapgcctype_dealloc}, + {Py_tp_traverse, heapgcctype_traverse}, {Py_tp_doc, (char*)heapgctype__doc__}, {0, 0}, }; @@ -7354,3 +7411,19 @@ test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } + +#undef PyArg_ParseTupleAndKeywords +PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, ...); + +static PyObject * +getargs_s_hash_int(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *keywords[] = {"", "x", NULL}; + const char *s; + int len; + int i = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s#i", keywords, &s, &len, &i)) + return NULL; + Py_RETURN_NONE; +} diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index ad60f32f7e7a62..e0ed77d265cdcc 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -844,6 +844,28 @@ PyInit__testmultiphase_meth_state_access(PyObject *spec) return PyModuleDef_Init(&def_meth_state_access); } +static PyModuleDef def_module_state_shared = { + PyModuleDef_HEAD_INIT, + .m_name = "_test_module_state_shared", + .m_doc = PyDoc_STR("Regression Test module for single-phase init."), + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit__test_module_state_shared(PyObject *spec) +{ + PyObject *module = PyModule_Create(&def_module_state_shared); + if (module == NULL) { + return NULL; + } + + if (PyModule_AddObjectRef(module, "Error", PyExc_Exception) < 0) { + Py_DECREF(module); + return NULL; + } + return module; +} + /*** Helper for imp test ***/ diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 6924d6553a1ff8..813d7ec232c35d 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -313,7 +313,7 @@ static PyType_Spec lock_type_spec = { .name = "_thread.lock", .basicsize = sizeof(lockobject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), .slots = lock_type_slots, }; @@ -327,6 +327,14 @@ typedef struct { PyObject *in_weakreflist; } rlockobject; +static int +rlock_traverse(rlockobject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + + static void rlock_dealloc(rlockobject *self) { @@ -579,13 +587,15 @@ static PyType_Slot rlock_type_slots[] = { {Py_tp_alloc, PyType_GenericAlloc}, {Py_tp_new, rlock_new}, {Py_tp_members, rlock_type_members}, + {Py_tp_traverse, rlock_traverse}, {0, 0}, }; static PyType_Spec rlock_type_spec = { .name = "_thread.RLock", .basicsize = sizeof(rlockobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = rlock_type_slots, }; @@ -684,7 +694,8 @@ static PyType_Slot local_dummy_type_slots[] = { static PyType_Spec local_dummy_type_spec = { .name = "_thread._localdummy", .basicsize = sizeof(localdummyobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE), .slots = local_dummy_type_slots, }; @@ -968,7 +979,8 @@ static PyType_Slot local_type_slots[] = { static PyType_Spec local_type_spec = { .name = "_thread._local", .basicsize = sizeof(localobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), .slots = local_type_slots, }; @@ -1093,7 +1105,9 @@ thread_run(void *boot_raw) PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); - PyThread_exit_thread(); + // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with + // the glibc, pthread_exit() can abort the whole process if dlopen() fails + // to open the libgcc_s.so library (ex: EMFILE error). } static PyObject * @@ -1201,7 +1215,7 @@ where the corresponding signal handler will be executed.\n\ If *signum* is omitted, SIGINT is assumed.\n\ A subthread can use this function to interrupt the main thread.\n\ \n\ -Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``." +Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``." ); static lockobject *newlockobject(PyObject *module); diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 3a0e5def0cf3c1..2a3e65b6c97df2 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -246,12 +246,15 @@ static PyThreadState *tcl_tstate = NULL; #endif #define ENTER_TCL \ - { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \ - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; + { PyThreadState *tstate = PyThreadState_Get(); \ + Py_BEGIN_ALLOW_THREADS \ + if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \ + tcl_tstate = tstate; #define LEAVE_TCL \ tcl_tstate = NULL; \ - if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS} + if(tcl_lock)PyThread_release_lock(tcl_lock); \ + Py_END_ALLOW_THREADS} #define ENTER_OVERLAP \ Py_END_ALLOW_THREADS @@ -261,12 +264,14 @@ static PyThreadState *tcl_tstate = NULL; #define ENTER_PYTHON \ { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \ - if(tcl_lock) \ - PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); } + if(tcl_lock) \ + PyThread_release_lock(tcl_lock); \ + PyEval_RestoreThread((tstate)); } #define LEAVE_PYTHON \ { PyThreadState *tstate = PyEval_SaveThread(); \ - if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; } + if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \ + tcl_tstate = tstate; } #define CHECK_TCL_APPARTMENT \ if (((TkappObject *)self)->threaded && \ @@ -931,7 +936,7 @@ PyTclObject_str(PyTclObject *self) Py_INCREF(self->string); return self->string; } - /* XXX Could chache result if it is non-ASCII. */ + /* XXX Could cache result if it is non-ASCII. */ return unicodeFromTclObj(self->value); } @@ -3192,8 +3197,10 @@ _tkinter__flatten(PyObject *module, PyObject *item) context.size = 0; - if (!_flatten1(&context, item,0)) + if (!_flatten1(&context, item, 0)) { + Py_XDECREF(context.tuple); return NULL; + } if (_PyTuple_Resize(&context.tuple, context.size)) return NULL; diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 04f6c243b5ca4d..ba0eb738abcbc5 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -836,7 +836,7 @@ tracemalloc_clear_filename(void *value) static void tracemalloc_clear_traces(void) { - /* The GIL protects variables againt concurrent access */ + /* The GIL protects variables against concurrent access */ assert(PyGILState_Check()); TABLES_LOCK(); @@ -1241,6 +1241,9 @@ tracemalloc_copy_domain(_Py_hashtable_t *domains, _Py_hashtable_t *traces = (_Py_hashtable_t *)value; _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); + if (traces2 == NULL) { + return -1; + } if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { _Py_hashtable_destroy(traces2); return -1; diff --git a/Modules/_winapi.c b/Modules/_winapi.c index bc2126c8e2ee99..3e24d512cac384 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -32,7 +32,7 @@ */ /* Licensed to PSF under a Contributor Agreement. */ -/* See http://www.python.org/2.4/license for licensing details. */ +/* See https://www.python.org/2.4/license for licensing details. */ #include "Python.h" #include "pycore_moduleobject.h" // _PyModule_GetState() @@ -112,12 +112,27 @@ typedef struct { Py_buffer write_buffer; } OverlappedObject; +/* +Note: tp_clear (overlapped_clear) is not implemented because it +requires cancelling the IO operation if it's pending and the cancellation is +quite complex and can fail (see: overlapped_dealloc). +*/ +static int +overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->read_buffer); + Py_VISIT(self->write_buffer.obj); + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void overlapped_dealloc(OverlappedObject *self) { DWORD bytes; int err = GetLastError(); + PyObject_GC_UnTrack(self); if (self->pending) { if (check_CancelIoEx() && Py_CancelIoEx(self->handle, &self->overlapped) && @@ -321,6 +336,7 @@ static PyMemberDef overlapped_members[] = { }; static PyType_Slot winapi_overlapped_type_slots[] = { + {Py_tp_traverse, overlapped_traverse}, {Py_tp_dealloc, overlapped_dealloc}, {Py_tp_doc, "OVERLAPPED structure wrapper"}, {Py_tp_methods, overlapped_methods}, @@ -331,7 +347,8 @@ static PyType_Slot winapi_overlapped_type_slots[] = { static PyType_Spec winapi_overlapped_type_spec = { .name = "_winapi.Overlapped", .basicsize = sizeof(OverlappedObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = winapi_overlapped_type_slots, }; @@ -339,7 +356,7 @@ static OverlappedObject * new_overlapped(PyObject *module, HANDLE handle) { WinApiState *st = winapi_get_state(module); - OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type); + OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type); if (!self) return NULL; @@ -351,6 +368,8 @@ new_overlapped(PyObject *module, HANDLE handle) memset(&self->write_buffer, 0, sizeof(Py_buffer)); /* Manual reset, initially non-signalled */ self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + PyObject_GC_Track(self); return self; } @@ -1703,7 +1722,7 @@ _winapi_WaitForMultipleObjects_impl(PyObject *module, PyObject *handle_seq, nhandles = PySequence_Length(handle_seq); if (nhandles == -1) return NULL; - if (nhandles < 0 || nhandles >= MAXIMUM_WAIT_OBJECTS - 1) { + if (nhandles < 0 || nhandles > MAXIMUM_WAIT_OBJECTS - 1) { PyErr_Format(PyExc_ValueError, "need at most %zd handles, got a sequence of length %zd", MAXIMUM_WAIT_OBJECTS - 1, nhandles); @@ -1875,6 +1894,113 @@ _winapi_GetFileType_impl(PyObject *module, HANDLE handle) return result; } +/*[clinic input] +_winapi._mimetypes_read_windows_registry + + on_type_read: object + +Optimized function for reading all known MIME types from the registry. + +*on_type_read* is a callable taking *type* and *ext* arguments, as for +MimeTypes.add_type. +[clinic start generated code]*/ + +static PyObject * +_winapi__mimetypes_read_windows_registry_impl(PyObject *module, + PyObject *on_type_read) +/*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/ +{ +#define CCH_EXT 128 +#define CB_TYPE 510 + struct { + wchar_t ext[CCH_EXT]; + wchar_t type[CB_TYPE / sizeof(wchar_t) + 1]; + } entries[64]; + int entry = 0; + HKEY hkcr = NULL; + LRESULT err; + + Py_BEGIN_ALLOW_THREADS + err = RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkcr); + for (DWORD i = 0; err == ERROR_SUCCESS || err == ERROR_MORE_DATA; ++i) { + LPWSTR ext = entries[entry].ext; + LPWSTR type = entries[entry].type; + DWORD cchExt = CCH_EXT; + DWORD cbType = CB_TYPE; + HKEY subkey; + DWORD regType; + + err = RegEnumKeyExW(hkcr, i, ext, &cchExt, NULL, NULL, NULL, NULL); + if (err != ERROR_SUCCESS || (cchExt && ext[0] != L'.')) { + continue; + } + + err = RegOpenKeyExW(hkcr, ext, 0, KEY_READ, &subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } + + err = RegQueryValueExW(subkey, L"Content Type", NULL, + ®Type, (LPBYTE)type, &cbType); + RegCloseKey(subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } else if (regType != REG_SZ || !cbType) { + continue; + } + type[cbType / sizeof(wchar_t)] = L'\0'; + + entry += 1; + + /* Flush our cached entries if we are full */ + if (entry == sizeof(entries) / sizeof(entries[0])) { + Py_BLOCK_THREADS + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + /* We blocked threads, so safe to return from here */ + RegCloseKey(hkcr); + return NULL; + } + Py_DECREF(r); + } + Py_UNBLOCK_THREADS + entry = 0; + } + } + if (hkcr) { + RegCloseKey(hkcr); + } + Py_END_ALLOW_THREADS + + if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS) { + PyErr_SetFromWindowsErr((int)err); + return NULL; + } + + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + return NULL; + } + Py_DECREF(r); + } + + Py_RETURN_NONE; +#undef CCH_EXT +#undef CB_TYPE +} + static PyMethodDef winapi_functions[] = { _WINAPI_CLOSEHANDLE_METHODDEF @@ -1907,6 +2033,7 @@ static PyMethodDef winapi_functions[] = { _WINAPI_WRITEFILE_METHODDEF _WINAPI_GETACP_METHODDEF _WINAPI_GETFILETYPE_METHODDEF + _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF {NULL, NULL} }; @@ -2043,12 +2170,37 @@ static PyModuleDef_Slot winapi_slots[] = { {0, NULL} }; +static int +winapi_traverse(PyObject *module, visitproc visit, void *arg) +{ + WinApiState *st = winapi_get_state(module); + Py_VISIT(st->overlapped_type); + return 0; +} + +static int +winapi_clear(PyObject *module) +{ + WinApiState *st = winapi_get_state(module); + Py_CLEAR(st->overlapped_type); + return 0; +} + +static void +winapi_free(void *module) +{ + winapi_clear((PyObject *)module); +} + static struct PyModuleDef winapi_module = { PyModuleDef_HEAD_INIT, .m_name = "_winapi", .m_size = sizeof(WinApiState), .m_methods = winapi_functions, .m_slots = winapi_slots, + .m_traverse = winapi_traverse, + .m_clear = winapi_clear, + .m_free = winapi_free, }; PyMODINIT_FUNC diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index 755442f857652b..04fa09422b2134 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -1342,7 +1342,7 @@ tzrule_transitions(_tzrule *rule, int year, int64_t *start, int64_t *end) * could technically be calculated from the timestamp, but given that the * callers of this function already have the year information accessible from * the datetime struct, it is taken as an additional parameter to reduce - * unncessary calculation. + * unnecessary calculation. * */ static _ttinfo * find_tzrule_ttinfo(_tzrule *rule, int64_t ts, unsigned char fold, int year) @@ -1468,11 +1468,11 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out) long std_offset = 1 << 20; long dst_offset = 1 << 20; - char *tz_str = PyBytes_AsString(tz_str_obj); + const char *tz_str = PyBytes_AsString(tz_str_obj); if (tz_str == NULL) { return -1; } - char *p = tz_str; + const char *p = tz_str; // Read the `std` abbreviation, which must be at least 3 characters long. Py_ssize_t num_chars = parse_abbr(p, &std_abbr); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index aa5886f4af7f69..72b90111a83735 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -661,10 +661,18 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v) /* Methods */ +static int +array_tp_traverse(arrayobject *op, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(op)); + return 0; +} + static void array_dealloc(arrayobject *op) { PyTypeObject *tp = Py_TYPE(op); + PyObject_GC_UnTrack(op); if (op->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) op); @@ -1670,12 +1678,12 @@ array.array.frombytes buffer: Py_buffer / -Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method). +Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method. [clinic start generated code]*/ static PyObject * array_array_frombytes_impl(arrayobject *self, Py_buffer *buffer) -/*[clinic end generated code: output=d9842c8f7510a516 input=2bbf2b53ebfcc988]*/ +/*[clinic end generated code: output=d9842c8f7510a516 input=378db226dfac949e]*/ { return frombytes(self, buffer); } @@ -2820,7 +2828,7 @@ static PyType_Slot array_slots[] = { {Py_tp_getset, array_getsets}, {Py_tp_alloc, PyType_GenericAlloc}, {Py_tp_new, array_new}, - {Py_tp_free, PyObject_Del}, + {Py_tp_traverse, array_tp_traverse}, /* as sequence */ {Py_sq_length, array_length}, @@ -2848,7 +2856,7 @@ static PyType_Spec array_spec = { .name = "array.array", .basicsize = sizeof(arrayobject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE), .slots = array_slots, }; @@ -2922,6 +2930,7 @@ arrayiter_dealloc(arrayiterobject *it) static int arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(it)); Py_VISIT(it->ao); return 0; } @@ -2988,7 +2997,7 @@ static PyType_Spec arrayiter_spec = { .name = "array.arrayiterator", .basicsize = sizeof(arrayiterobject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), .slots = arrayiter_slots, }; diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index e536b4abe295f0..95c653cf4782a2 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -93,13 +93,16 @@ atexit_callfuncs(struct atexit_state *state) continue; } + // bpo-46025: Increment the refcount of cb->func as the call itself may unregister it + PyObject* the_func = Py_NewRef(cb->func); PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs); if (res == NULL) { - _PyErr_WriteUnraisableMsg("in atexit callback", cb->func); + _PyErr_WriteUnraisableMsg("in atexit callback", the_func); } else { Py_DECREF(res); } + Py_DECREF(the_func); } atexit_cleanup(state); diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index cb7182ff21fbcd..ba558d0dbf2f1d 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -749,7 +749,7 @@ static PyType_Spec multibytecodec_spec = { .name = MODULE_NAME ".MultibyteCodec", .basicsize = sizeof(MultibyteCodecObject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), .slots = multibytecodec_slots, }; @@ -1111,7 +1111,8 @@ static PyType_Slot encoder_slots[] = { static PyType_Spec encoder_spec = { .name = MODULE_NAME ".MultibyteIncrementalEncoder", .basicsize = sizeof(MultibyteIncrementalEncoderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), .slots = encoder_slots, }; @@ -1384,7 +1385,8 @@ static PyType_Slot decoder_slots[] = { static PyType_Spec decoder_spec = { .name = MODULE_NAME ".MultibyteIncrementalDecoder", .basicsize = sizeof(MultibyteIncrementalDecoderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), .slots = decoder_slots, }; @@ -1705,7 +1707,8 @@ static PyType_Slot reader_slots[] = { static PyType_Spec reader_spec = { .name = MODULE_NAME ".MultibyteStreamReader", .basicsize = sizeof(MultibyteStreamReaderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), .slots = reader_slots, }; @@ -1925,7 +1928,8 @@ static PyType_Slot writer_slots[] = { static PyType_Spec writer_spec = { .name = MODULE_NAME ".MultibyteStreamWriter", .basicsize = sizeof(MultibyteStreamWriterObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), .slots = writer_slots, }; diff --git a/Modules/clinic/_bisectmodule.c.h b/Modules/clinic/_bisectmodule.c.h index 304e46cf158a74..f118f4bbf86288 100644 --- a/Modules/clinic/_bisectmodule.c.h +++ b/Modules/clinic/_bisectmodule.c.h @@ -9,8 +9,8 @@ PyDoc_STRVAR(_bisect_bisect_right__doc__, "Return the index where to insert item x in list a, assuming a is sorted.\n" "\n" "The return value i is such that all e in a[:i] have e <= x, and all e in\n" -"a[i:] have e > x. So if x already appears in the list, i points just\n" -"beyond the rightmost x already there\n" +"a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will\n" +"insert just after the rightmost x already there.\n" "\n" "Optional args lo (default 0) and hi (default len(a)) bound the\n" "slice of a to be searched."); @@ -172,8 +172,8 @@ PyDoc_STRVAR(_bisect_bisect_left__doc__, "Return the index where to insert item x in list a, assuming a is sorted.\n" "\n" "The return value i is such that all e in a[:i] have e < x, and all e in\n" -"a[i:] have e >= x. So if x already appears in the list, i points just\n" -"before the leftmost x already there.\n" +"a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will\n" +"insert just before the leftmost x already there.\n" "\n" "Optional args lo (default 0) and hi (default len(a)) bound the\n" "slice of a to be searched."); @@ -327,4 +327,4 @@ _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=b3a5be025aa4ed7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=aeb97db6db79bf96 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h index 43378f94f98450..855ac77a7f73fd 100644 --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -1063,7 +1063,7 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_codecs_unicode_escape_decode__doc__, -"unicode_escape_decode($module, data, errors=None, /)\n" +"unicode_escape_decode($module, data, errors=None, final=True, /)\n" "--\n" "\n"); @@ -1072,7 +1072,7 @@ PyDoc_STRVAR(_codecs_unicode_escape_decode__doc__, static PyObject * _codecs_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, - const char *errors); + const char *errors, int final); static PyObject * _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) @@ -1080,8 +1080,9 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; const char *errors = NULL; + int final = 1; - if (!_PyArg_CheckPositional("unicode_escape_decode", nargs, 1, 2)) { + if (!_PyArg_CheckPositional("unicode_escape_decode", nargs, 1, 3)) { goto exit; } if (PyUnicode_Check(args[0])) { @@ -1122,8 +1123,15 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ _PyArg_BadArgument("unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } + if (nargs < 3) { + goto skip_optional; + } + final = _PyLong_AsInt(args[2]); + if (final == -1 && PyErr_Occurred()) { + goto exit; + } skip_optional: - return_value = _codecs_unicode_escape_decode_impl(module, &data, errors); + return_value = _codecs_unicode_escape_decode_impl(module, &data, errors, final); exit: /* Cleanup for data */ @@ -1135,7 +1143,7 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ } PyDoc_STRVAR(_codecs_raw_unicode_escape_decode__doc__, -"raw_unicode_escape_decode($module, data, errors=None, /)\n" +"raw_unicode_escape_decode($module, data, errors=None, final=True, /)\n" "--\n" "\n"); @@ -1144,7 +1152,7 @@ PyDoc_STRVAR(_codecs_raw_unicode_escape_decode__doc__, static PyObject * _codecs_raw_unicode_escape_decode_impl(PyObject *module, Py_buffer *data, - const char *errors); + const char *errors, int final); static PyObject * _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) @@ -1152,8 +1160,9 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; const char *errors = NULL; + int final = 1; - if (!_PyArg_CheckPositional("raw_unicode_escape_decode", nargs, 1, 2)) { + if (!_PyArg_CheckPositional("raw_unicode_escape_decode", nargs, 1, 3)) { goto exit; } if (PyUnicode_Check(args[0])) { @@ -1194,8 +1203,15 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss _PyArg_BadArgument("raw_unicode_escape_decode", "argument 2", "str or None", args[1]); goto exit; } + if (nargs < 3) { + goto skip_optional; + } + final = _PyLong_AsInt(args[2]); + if (final == -1 && PyErr_Occurred()) { + goto exit; + } skip_optional: - return_value = _codecs_raw_unicode_escape_decode_impl(module, &data, errors); + return_value = _codecs_raw_unicode_escape_decode_impl(module, &data, errors, final); exit: /* Cleanup for data */ @@ -2801,4 +2817,4 @@ _codecs_lookup_error(PyObject *module, PyObject *arg) #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=557c3b37e4c492ac input=a9049054013a1b77]*/ +/*[clinic end generated code: output=814dae36b6f885cb input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index ffd2179f36970a..ea4ee7df001c18 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -161,7 +161,7 @@ PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__, "to create a list in memory that contains them all:\n" "\n" " k = db.firstkey()\n" -" while k != None:\n" +" while k is not None:\n" " print(k)\n" " k = db.nextkey(k)"); @@ -340,4 +340,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=e84bc6ac82fcb6d4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3b88446433e43d96 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_operator.c.h b/Modules/clinic/_operator.c.h index 34b6fdadfb7309..bda2eba6d12a21 100644 --- a/Modules/clinic/_operator.c.h +++ b/Modules/clinic/_operator.c.h @@ -957,7 +957,7 @@ PyDoc_STRVAR(_operator_countOf__doc__, "countOf($module, a, b, /)\n" "--\n" "\n" -"Return the number of times b occurs in a."); +"Return the number of items in a which are, or which equal, b."); #define _OPERATOR_COUNTOF_METHODDEF \ {"countOf", (PyCFunction)(void(*)(void))_operator_countOf, METH_FASTCALL, _operator_countOf__doc__}, @@ -1486,4 +1486,4 @@ _operator__compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t na exit: return return_value; } -/*[clinic end generated code: output=eae5d08f971a65fd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=16749e11fda51785 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index b153c30cf39ae0..b59b129af8a095 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -271,25 +271,25 @@ PyDoc_STRVAR(_ssl__SSLSocket_read__doc__, {"read", (PyCFunction)_ssl__SSLSocket_read, METH_VARARGS, _ssl__SSLSocket_read__doc__}, static PyObject * -_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, - Py_buffer *buffer); +_ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, + int group_right_1, Py_buffer *buffer); static PyObject * _ssl__SSLSocket_read(PySSLSocket *self, PyObject *args) { PyObject *return_value = NULL; - int len; + Py_ssize_t len; int group_right_1 = 0; Py_buffer buffer = {NULL, NULL}; switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "i:read", &len)) { + if (!PyArg_ParseTuple(args, "n:read", &len)) { goto exit; } break; case 2: - if (!PyArg_ParseTuple(args, "iw*:read", &len, &buffer)) { + if (!PyArg_ParseTuple(args, "nw*:read", &len, &buffer)) { goto exit; } group_right_1 = 1; @@ -1358,4 +1358,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=3b6f4471fb187d85 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a7d7bf5cf8ee092 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h index a9630d55998d3d..5bda156d7aa80c 100644 --- a/Modules/clinic/_winapi.c.h +++ b/Modules/clinic/_winapi.c.h @@ -1148,4 +1148,40 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=1f10e03f64ff9777 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_winapi__mimetypes_read_windows_registry__doc__, +"_mimetypes_read_windows_registry($module, /, on_type_read)\n" +"--\n" +"\n" +"Optimized function for reading all known MIME types from the registry.\n" +"\n" +"*on_type_read* is a callable taking *type* and *ext* arguments, as for\n" +"MimeTypes.add_type."); + +#define _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF \ + {"_mimetypes_read_windows_registry", (PyCFunction)(void(*)(void))_winapi__mimetypes_read_windows_registry, METH_FASTCALL|METH_KEYWORDS, _winapi__mimetypes_read_windows_registry__doc__}, + +static PyObject * +_winapi__mimetypes_read_windows_registry_impl(PyObject *module, + PyObject *on_type_read); + +static PyObject * +_winapi__mimetypes_read_windows_registry(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"on_type_read", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "_mimetypes_read_windows_registry", 0}; + PyObject *argsbuf[1]; + PyObject *on_type_read; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + on_type_read = args[0]; + return_value = _winapi__mimetypes_read_windows_registry_impl(module, on_type_read); + +exit: + return return_value; +} +/*[clinic end generated code: output=ac3623be6e42017c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h index d2513eb4f48cfd..c46cc738de91b7 100644 --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -359,7 +359,7 @@ PyDoc_STRVAR(array_array_frombytes__doc__, "frombytes($self, buffer, /)\n" "--\n" "\n" -"Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method)."); +"Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method."); #define ARRAY_ARRAY_FROMBYTES_METHODDEF \ {"frombytes", (PyCFunction)array_array_frombytes, METH_O, array_array_frombytes__doc__}, @@ -572,4 +572,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=376001addedc67ee input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f130a994f98f1227 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 4713bab7486acb..4c27314a80c862 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -354,7 +354,7 @@ signal_getitimer(PyObject *module, PyObject *arg) #endif /* defined(HAVE_GETITIMER) */ -#if defined(PYPTHREAD_SIGMASK) +#if defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) PyDoc_STRVAR(signal_pthread_sigmask__doc__, "pthread_sigmask($module, how, mask, /)\n" @@ -391,9 +391,9 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } -#endif /* defined(PYPTHREAD_SIGMASK) */ +#endif /* defined(HAVE_SIGSET_T) && defined(PYPTHREAD_SIGMASK) */ -#if defined(HAVE_SIGPENDING) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) PyDoc_STRVAR(signal_sigpending__doc__, "sigpending($module, /)\n" @@ -416,9 +416,9 @@ signal_sigpending(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_sigpending_impl(module); } -#endif /* defined(HAVE_SIGPENDING) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGPENDING) */ -#if defined(HAVE_SIGWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) PyDoc_STRVAR(signal_sigwait__doc__, "sigwait($module, sigset, /)\n" @@ -451,9 +451,9 @@ signal_sigwait(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAIT) */ -#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) +#if ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) PyDoc_STRVAR(signal_valid_signals__doc__, "valid_signals($module, /)\n" @@ -476,9 +476,9 @@ signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) return signal_valid_signals_impl(module); } -#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ +#endif /* ((defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS)) */ -#if defined(HAVE_SIGWAITINFO) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, "sigwaitinfo($module, sigset, /)\n" @@ -509,9 +509,9 @@ signal_sigwaitinfo(PyObject *module, PyObject *arg) return return_value; } -#endif /* defined(HAVE_SIGWAITINFO) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGWAITINFO) */ -#if defined(HAVE_SIGTIMEDWAIT) +#if defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) PyDoc_STRVAR(signal_sigtimedwait__doc__, "sigtimedwait($module, sigset, timeout, /)\n" @@ -548,7 +548,7 @@ signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* defined(HAVE_SIGTIMEDWAIT) */ +#endif /* defined(HAVE_SIGSET_T) && defined(HAVE_SIGTIMEDWAIT) */ #if defined(HAVE_PTHREAD_KILL) @@ -698,4 +698,4 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=59c33f0af42aebb5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c353e686367bc384 input=a9049054013a1b77]*/ diff --git a/Modules/expat/COPYING b/Modules/expat/COPYING index 8d288f0f28fddd..3c0142e71c8d4f 100644 --- a/Modules/expat/COPYING +++ b/Modules/expat/COPYING @@ -1,5 +1,5 @@ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper -Copyright (c) 2001-2017 Expat maintainers +Copyright (c) 2001-2019 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/Modules/expat/ascii.h b/Modules/expat/ascii.h index c3587e57332bff..1f594d2e54b4d2 100644 --- a/Modules/expat/ascii.h +++ b/Modules/expat/ascii.h @@ -6,8 +6,11 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 1999-2000 Thai Open Source Software Center Ltd + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2007 Karl Waclawek + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/asciitab.h b/Modules/expat/asciitab.h index 63b1d1b4482efa..af766fb24785ea 100644 --- a/Modules/expat/asciitab.h +++ b/Modules/expat/asciitab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/expat.h b/Modules/expat/expat.h index 6c8eb1fda4a30c..b7d6d354801b3d 100644 --- a/Modules/expat/expat.h +++ b/Modules/expat/expat.h @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2005 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Cristian Rodríguez + Copyright (c) 2016 Thomas Beutlich + Copyright (c) 2017 Rhodri James Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -115,7 +122,11 @@ enum XML_Error { XML_ERROR_RESERVED_PREFIX_XMLNS, XML_ERROR_RESERVED_NAMESPACE_URI, /* Added in 2.2.1. */ - XML_ERROR_INVALID_ARGUMENT + XML_ERROR_INVALID_ARGUMENT, + /* Added in 2.3.0. */ + XML_ERROR_NO_BUFFER, + /* Added in 2.4.0. */ + XML_ERROR_AMPLIFICATION_LIMIT_BREACH }; enum XML_Content_Type { @@ -318,7 +329,7 @@ typedef void(XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); For internal entities (), value will be non-NULL and systemId, publicID, and notationName will be NULL. - The value string is NOT nul-terminated; the length is provided in + The value string is NOT null-terminated; the length is provided in the value_length argument. Since it is legal to have zero-length values, do not use this argument to test for internal entities. @@ -513,7 +524,7 @@ typedef struct { Otherwise it must return XML_STATUS_ERROR. If info does not describe a suitable encoding, then the parser will - return an XML_UNKNOWN_ENCODING error. + return an XML_ERROR_UNKNOWN_ENCODING error. */ typedef int(XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, @@ -707,7 +718,7 @@ XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus - this correspondds to an index into the atts array passed to the + this corresponds to an index into the atts array passed to the XML_StartElementHandler. Returns -1 if parser == NULL. */ XMLPARSEAPI(int) @@ -716,7 +727,7 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute or parser == NULL. Each attribute/value pair counts as 2; thus this - correspondds to an index into the atts array passed to the + corresponds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) @@ -997,7 +1008,10 @@ enum XML_FeatureEnum { XML_FEATURE_SIZEOF_XML_LCHAR, XML_FEATURE_NS, XML_FEATURE_LARGE_SIZE, - XML_FEATURE_ATTR_INFO + XML_FEATURE_ATTR_INFO, + /* Added in Expat 2.4.0. */ + XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT /* Additional features must be added to the end of this enum. */ }; @@ -1010,12 +1024,24 @@ typedef struct { XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); +#ifdef XML_DTD +/* Added in Expat 2.4.0. */ +XMLPARSEAPI(XML_Bool) +XML_SetBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor); + +/* Added in Expat 2.4.0. */ +XMLPARSEAPI(XML_Bool) +XML_SetBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes); +#endif + /* Expat follows the semantic versioning convention. See http://semver.org. */ #define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 2 -#define XML_MICRO_VERSION 8 +#define XML_MINOR_VERSION 4 +#define XML_MICRO_VERSION 1 #ifdef __cplusplus } diff --git a/Modules/expat/expat_external.h b/Modules/expat/expat_external.h index f2b75dda8e2798..12c560e14716ff 100644 --- a/Modules/expat/expat_external.h +++ b/Modules/expat/expat_external.h @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2004 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2016 Cristian Rodríguez + Copyright (c) 2016-2019 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2018 Yury Gribov Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/iasciitab.h b/Modules/expat/iasciitab.h index ea97cfcf678e06..5d8646f2a318b8 100644 --- a/Modules/expat/iasciitab.h +++ b/Modules/expat/iasciitab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/internal.h b/Modules/expat/internal.h index 60913dab762f8f..444eba0fb03170 100644 --- a/Modules/expat/internal.h +++ b/Modules/expat/internal.h @@ -25,8 +25,12 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2002-2003 Fred L. Drake, Jr. + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2003 Greg Stein + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2018 Yury Gribov + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -101,22 +105,58 @@ # endif #endif +#include // ULONG_MAX + +#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO) +# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u" +# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u" +# else +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" +# endif +#else +# define EXPAT_FMT_ULL(midpart) "%" midpart "llu" +# if ! defined(ULONG_MAX) +# error Compiler did not define ULONG_MAX for us +# elif ULONG_MAX == 18446744073709551615u // 2^64-1 +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu" +# else +# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" +# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" +# endif +#endif + #ifndef UNUSED_P # define UNUSED_P(p) (void)p #endif +/* NOTE BEGIN If you ever patch these defaults to greater values + for non-attack XML payload in your environment, + please file a bug report with libexpat. Thank you! +*/ +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \ + 100.0f +#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \ + 8388608 // 8 MiB, 2^23 +/* NOTE END */ + +#include "expat.h" // so we can use type XML_Parser below + #ifdef __cplusplus extern "C" { #endif -#ifdef XML_ENABLE_VISIBILITY -# if XML_ENABLE_VISIBILITY -__attribute__((visibility("default"))) -# endif +void _INTERNAL_trim_to_complete_utf8_characters(const char *from, + const char **fromLimRef); + +#if defined(XML_DTD) +unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser); +unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser); +const char *unsignedCharToPrintable(unsigned char c); #endif -void -_INTERNAL_trim_to_complete_utf8_characters(const char *from, - const char **fromLimRef); #ifdef __cplusplus } diff --git a/Modules/expat/latin1tab.h b/Modules/expat/latin1tab.h index 6f916041355a86..b681d278af6569 100644 --- a/Modules/expat/latin1tab.h +++ b/Modules/expat/latin1tab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/nametab.h b/Modules/expat/nametab.h index 3681df348eebd6..63485446b96727 100644 --- a/Modules/expat/nametab.h +++ b/Modules/expat/nametab.h @@ -6,8 +6,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/siphash.h b/Modules/expat/siphash.h index bfee65a332f1bf..e5406d7ee9eb54 100644 --- a/Modules/expat/siphash.h +++ b/Modules/expat/siphash.h @@ -11,6 +11,9 @@ * -------------------------------------------------------------------------- * HISTORY: * + * 2020-10-03 (Sebastian Pipping) + * - Drop support for Visual Studio 9.0/2008 and earlier + * * 2019-08-03 (Sebastian Pipping) * - Mark part of sip24_valid as to be excluded from clang-format * - Re-format code using clang-format 9 @@ -96,15 +99,7 @@ #define SIPHASH_H #include /* size_t */ - -#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600) -/* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */ -typedef unsigned __int8 uint8_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#else -# include /* uint64_t uint32_t uint8_t */ -#endif +#include /* uint64_t uint32_t uint8_t */ /* * Workaround to not require a C++11 compiler for using ULL suffix diff --git a/Modules/expat/utf8tab.h b/Modules/expat/utf8tab.h index a22986acbb9526..88efcf91cc16a6 100644 --- a/Modules/expat/utf8tab.h +++ b/Modules/expat/utf8tab.h @@ -7,7 +7,9 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/winconfig.h b/Modules/expat/winconfig.h index 562a4a82dc1d63..2ecd61b5b94820 100644 --- a/Modules/expat/winconfig.h +++ b/Modules/expat/winconfig.h @@ -6,8 +6,10 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2005 Karl Waclawek + Copyright (c) 2017-2021 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -40,17 +42,4 @@ #include #include -#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */ -# include -#else /* !defined(HAVE_EXPAT_CONFIG_H) */ - -# define XML_NS 1 -# define XML_DTD 1 -# define XML_CONTEXT_BYTES 1024 - -/* we will assume all Windows platforms are little endian */ -# define BYTEORDER 1234 - -#endif /* !defined(HAVE_EXPAT_CONFIG_H) */ - #endif /* ndef WINCONFIG_H */ diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index e740f0e19c7d4a..034a03c30851a1 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -1,4 +1,4 @@ -/* f2d0ab6d1d4422a08cf1cf3bbdfba96b49dea42fb5ff4615e03a2a25c306e769 (2.2.8+) +/* 8539b9040d9d901366a62560a064af7cb99811335784b363abc039c5b0ebc416 (2.4.1+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -7,7 +7,31 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2000-2006 Fred L. Drake, Jr. + Copyright (c) 2001-2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016 Eric Rahm + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Gaurav + Copyright (c) 2016 Thomas Beutlich + Copyright (c) 2016 Gustavo Grieco + Copyright (c) 2016 Pascal Cuoq + Copyright (c) 2016 Ed Schouten + Copyright (c) 2017-2018 Rhodri James + Copyright (c) 2017 Václav Slavík + Copyright (c) 2017 Viktor Szakats + Copyright (c) 2017 Chanho Park + Copyright (c) 2017 Rolf Eike Beer + Copyright (c) 2017 Hans Wennborg + Copyright (c) 2018 Anton Maklakov + Copyright (c) 2018 Benjamin Peterson + Copyright (c) 2018 Marco Maggi + Copyright (c) 2018 Mariusz Zaborski + Copyright (c) 2019 David Loffredo + Copyright (c) 2019-2020 Ben Wagner + Copyright (c) 2019 Vadim Zeitlin Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -36,7 +60,9 @@ #ifdef _WIN32 /* force stdlib to define rand_s() */ -# define _CRT_RAND_S +# if ! defined(_CRT_RAND_S) +# define _CRT_RAND_S +# endif #endif #include @@ -45,6 +71,8 @@ #include /* UINT_MAX */ #include /* fprintf */ #include /* getenv, rand_s */ +#include /* uintptr_t */ +#include /* isnan */ #ifdef _WIN32 # define getpid GetCurrentProcessId @@ -60,9 +88,9 @@ #ifdef _WIN32 # include "winconfig.h" -#elif defined(HAVE_EXPAT_CONFIG_H) -# include -#endif /* ndef _WIN32 */ +#endif + +#include #include "ascii.h" #include "expat.h" @@ -97,14 +125,14 @@ enabled. For end user security, that is probably not what you want. \ \ Your options include: \ - * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \ - * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \ + * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \ + * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \ * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \ - * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \ + * BSD / macOS (including <10.7) (arc4random): HAVE_ARC4RANDOM, \ * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \ * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \ - * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \ - * Windows (rand_s): _WIN32. \ + * Linux (including <3.17) / BSD / macOS (including <10.7) (/dev/urandom): XML_DEV_URANDOM, \ + * Windows >=Vista (rand_s): _WIN32. \ \ If insist on not using any of these, bypass this error by defining \ XML_POOR_ENTROPY; you have been warned. \ @@ -119,9 +147,7 @@ # define XmlGetInternalEncoding XmlGetUtf16InternalEncoding # define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS # define XmlEncode XmlUtf16Encode -/* Using pointer subtraction to convert to integer type. */ -# define MUST_CONVERT(enc, s) \ - (! (enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1)) +# define MUST_CONVERT(enc, s) (! (enc)->isUtf16 || (((uintptr_t)(s)) & 1)) typedef unsigned short ICHAR; #else # define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX @@ -371,6 +397,31 @@ typedef struct open_internal_entity { XML_Bool betweenDecl; /* WFC: PE Between Declarations */ } OPEN_INTERNAL_ENTITY; +enum XML_Account { + XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */ + XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity + expansion */ + XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */ +}; + +#ifdef XML_DTD +typedef unsigned long long XmlBigCount; +typedef struct accounting { + XmlBigCount countBytesDirect; + XmlBigCount countBytesIndirect; + int debugLevel; + float maximumAmplificationFactor; // >=1.0 + unsigned long long activationThresholdBytes; +} ACCOUNTING; + +typedef struct entity_stats { + unsigned int countEverOpened; + unsigned int currentDepth; + unsigned int maximumDepthSeen; + int debugLevel; +} ENTITY_STATS; +#endif /* XML_DTD */ + typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr); @@ -401,16 +452,18 @@ static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, - XML_Bool haveMore, XML_Bool allowClosingDoctype); + XML_Bool haveMore, XML_Bool allowClosingDoctype, + enum XML_Account account); static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *start, const char *end, const char **endPtr, - XML_Bool haveMore); + XML_Bool haveMore, enum XML_Account account); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, - const char **nextPtr, XML_Bool haveMore); + const char **nextPtr, XML_Bool haveMore, + enum XML_Account account); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, @@ -420,7 +473,8 @@ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *, static void freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, - BINDING **bindingsPtr); + BINDING **bindingsPtr, + enum XML_Account account); static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); @@ -429,15 +483,18 @@ static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, XML_Parser parser); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, - const char *, STRING_POOL *); + const char *, STRING_POOL *, + enum XML_Account account); static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, const char *, - const char *, STRING_POOL *); + const char *, STRING_POOL *, + enum XML_Account account); static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, - const char *start, const char *end); + const char *start, const char *end, + enum XML_Account account); static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportComment(XML_Parser parser, const ENCODING *enc, @@ -501,6 +558,34 @@ static XML_Parser parserCreate(const XML_Char *encodingName, static void parserInit(XML_Parser parser, const XML_Char *encodingName); +#ifdef XML_DTD +static float accountingGetCurrentAmplification(XML_Parser rootParser); +static void accountingReportStats(XML_Parser originParser, const char *epilog); +static void accountingOnAbort(XML_Parser originParser); +static void accountingReportDiff(XML_Parser rootParser, + unsigned int levelsAwayFromRootParser, + const char *before, const char *after, + ptrdiff_t bytesMore, int source_line, + enum XML_Account account); +static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok, + const char *before, const char *after, + int source_line, + enum XML_Account account); + +static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity, + const char *action, int sourceLine); +static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity, + int sourceLine); +static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity, + int sourceLine); + +static XML_Parser getRootParserOf(XML_Parser parser, + unsigned int *outLevelDiff); +#endif /* XML_DTD */ + +static unsigned long getDebugLevel(const char *variableName, + unsigned long defaultDebugLevel); + #define poolStart(pool) ((pool)->start) #define poolEnd(pool) ((pool)->ptr) #define poolLength(pool) ((pool)->ptr - (pool)->start) @@ -614,6 +699,10 @@ struct XML_ParserStruct { enum XML_ParamEntityParsing m_paramEntityParsing; #endif unsigned long m_hash_secret_salt; +#ifdef XML_DTD + ACCOUNTING m_accounting; + ENTITY_STATS m_entity_stats; +#endif }; #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) @@ -734,6 +823,15 @@ writeRandomBytes_arc4random(void *target, size_t count) { #ifdef _WIN32 +/* Provide declaration of rand_s() for MinGW-32 (not 64, which has it), + as it didn't declare it in its header prior to version 5.3.0 of its + runtime package (mingwrt, containing stdlib.h). The upstream fix + was introduced at https://osdn.net/projects/mingw/ticket/39658 . */ +# if defined(__MINGW32__) && defined(__MINGW32_VERSION) \ + && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR) +__declspec(dllimport) int rand_s(unsigned int *); +# endif + /* Obtain entropy on Windows using the rand_s() function which * generates cryptographically secure random numbers. Internally it * uses RtlGenRandom API which is present in Windows XP and later. @@ -789,9 +887,8 @@ gather_time_entropy(void) { static unsigned long ENTROPY_DEBUG(const char *label, unsigned long entropy) { - const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG"); - if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) { - fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, + if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) { + fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy)); } return entropy; @@ -1053,6 +1150,18 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif parser->m_hash_secret_salt = 0; + +#ifdef XML_DTD + memset(&parser->m_accounting, 0, sizeof(ACCOUNTING)); + parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u); + parser->m_accounting.maximumAmplificationFactor + = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT; + parser->m_accounting.activationThresholdBytes + = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT; + + memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS)); + parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u); +#endif } /* moves list of bindings to m_freeBindingList */ @@ -1399,6 +1508,7 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { parser->m_useForeignDTD = useDTD; return XML_ERROR_NONE; #else + UNUSED_P(useDTD); return XML_ERROR_FEATURE_REQUIRES_XML_DTD; #endif } @@ -1780,7 +1890,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { int nLeftOver; enum XML_Status result; /* Detect overflow (a+b > MAX <==> b > MAX-a) */ - if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) { + if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) { parser->m_errorCode = XML_ERROR_NO_MEMORY; parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_processor = errorProcessor; @@ -1872,6 +1982,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { parser->m_errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR; case XML_INITIALIZED: + /* Has someone called XML_GetBuffer successfully before? */ + if (! parser->m_bufferPtr) { + parser->m_errorCode = XML_ERROR_NO_BUFFER; + return XML_STATUS_ERROR; + } + if (parser->m_parentParser == NULL && ! startParsing(parser)) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; @@ -2155,7 +2271,7 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size) { (void)offset; (void)size; #endif /* defined XML_CONTEXT_BYTES */ - return (char *)0; + return (const char *)0; } XML_Size XMLCALL @@ -2316,6 +2432,14 @@ XML_ErrorString(enum XML_Error code) { /* Added in 2.2.5. */ case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */ return XML_L("invalid argument"); + /* Added in 2.3.0. */ + case XML_ERROR_NO_BUFFER: + return XML_L( + "a successful prior call to function XML_GetBuffer is required"); + /* Added in 2.4.0. */ + case XML_ERROR_AMPLIFICATION_LIMIT_BREACH: + return XML_L( + "limit on input amplification factor (from DTD and entities) breached"); } return NULL; } @@ -2352,41 +2476,75 @@ XML_ExpatVersionInfo(void) { const XML_Feature *XMLCALL XML_GetFeatureList(void) { - static const XML_Feature features[] - = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), - sizeof(XML_Char)}, - {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), - sizeof(XML_LChar)}, + static const XML_Feature features[] = { + {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), + sizeof(XML_Char)}, + {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), + sizeof(XML_LChar)}, #ifdef XML_UNICODE - {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, + {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, #endif #ifdef XML_UNICODE_WCHAR_T - {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, + {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, #endif #ifdef XML_DTD - {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, + {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, #endif #ifdef XML_CONTEXT_BYTES - {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), - XML_CONTEXT_BYTES}, + {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), + XML_CONTEXT_BYTES}, #endif #ifdef XML_MIN_SIZE - {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, + {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, #endif #ifdef XML_NS - {XML_FEATURE_NS, XML_L("XML_NS"), 0}, + {XML_FEATURE_NS, XML_L("XML_NS"), 0}, #endif #ifdef XML_LARGE_SIZE - {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, + {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, #endif #ifdef XML_ATTR_INFO - {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, + {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, +#endif +#ifdef XML_DTD + /* Added in Expat 2.4.0. */ + {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, + XML_L("XML_BLAP_MAX_AMP"), + (long int) + EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT}, + {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, + XML_L("XML_BLAP_ACT_THRES"), + EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT}, #endif - {XML_FEATURE_END, NULL, 0}}; + {XML_FEATURE_END, NULL, 0}}; return features; } +#ifdef XML_DTD +XML_Bool XMLCALL +XML_SetBillionLaughsAttackProtectionMaximumAmplification( + XML_Parser parser, float maximumAmplificationFactor) { + if ((parser == NULL) || (parser->m_parentParser != NULL) + || isnan(maximumAmplificationFactor) + || (maximumAmplificationFactor < 1.0f)) { + return XML_FALSE; + } + parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor; + return XML_TRUE; +} + +XML_Bool XMLCALL +XML_SetBillionLaughsAttackProtectionActivationThreshold( + XML_Parser parser, unsigned long long activationThresholdBytes) { + if ((parser == NULL) || (parser->m_parentParser != NULL)) { + return XML_FALSE; + } + parser->m_accounting.activationThresholdBytes = activationThresholdBytes; + return XML_TRUE; +} +#endif /* XML_DTD */ + /* Initially tag->rawName always points into the parse buffer; for those TAG instances opened while the current parse buffer was processed, and not yet closed, we need to store tag->rawName in a more @@ -2439,9 +2597,9 @@ storeRawNames(XML_Parser parser) { static enum XML_Error PTRCALL contentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { - enum XML_Error result - = doContent(parser, 0, parser->m_encoding, start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + enum XML_Error result = doContent( + parser, 0, parser->m_encoding, start, end, endPtr, + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; @@ -2466,6 +2624,14 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start, int tok = XmlContentTok(parser->m_encoding, start, end, &next); switch (tok) { case XML_TOK_BOM: +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, start, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif /* XML_DTD */ + /* If we are at the end of the buffer, this would cause the next stage, i.e. externalEntityInitProcessor3, to pass control directly to doContent (by detecting XML_TOK_NONE) without processing any xml text @@ -2503,6 +2669,10 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start, const char *next = start; /* XmlContentTok doesn't always set the last arg */ parser->m_eventPtr = start; tok = XmlContentTok(parser->m_encoding, start, end, &next); + /* Note: These bytes are accounted later in: + - processXmlDecl + - externalEntityContentProcessor + */ parser->m_eventEndPtr = next; switch (tok) { @@ -2544,7 +2714,8 @@ externalEntityContentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, + XML_ACCOUNT_ENTITY_EXPANSION); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; @@ -2555,7 +2726,7 @@ externalEntityContentProcessor(XML_Parser parser, const char *start, static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *s, const char *end, const char **nextPtr, - XML_Bool haveMore) { + XML_Bool haveMore, enum XML_Account account) { /* save one level of indirection */ DTD *const dtd = parser->m_dtd; @@ -2573,6 +2744,17 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); +#ifdef XML_DTD + const char *accountAfter + = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR)) + ? (haveMore ? s /* i.e. 0 bytes */ : end) + : next; + if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__, + account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: @@ -2628,6 +2810,14 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { +#ifdef XML_DTD + /* NOTE: We are replacing 4-6 characters original input for 1 character + * so there is no amplification and hence recording without + * protection. */ + accountingDiffTolerated(parser, tok, (char *)&ch, + ((char *)&ch) + sizeof(XML_Char), __LINE__, + XML_ACCOUNT_ENTITY_EXPANSION); +#endif /* XML_DTD */ if (parser->m_characterDataHandler) parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1); else if (parser->m_defaultHandler) @@ -2746,7 +2936,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, } tag->name.str = (XML_Char *)tag->buf; *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + result + = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account); if (result) return result; if (parser->m_startElementHandler) @@ -2770,7 +2961,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, if (! name.str) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); + result = storeAtts(parser, enc, s, &name, &bindings, + XML_ACCOUNT_NONE /* token spans whole start tag */); if (result != XML_ERROR_NONE) { freeBindings(parser, bindings); return result; @@ -2905,7 +3097,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, /* END disabled code */ else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + result + = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account); if (result != XML_ERROR_NONE) return result; else if (! next) { @@ -3034,7 +3227,8 @@ freeBindings(XML_Parser parser, BINDING *bindings) { */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, - TAG_NAME *tagNamePtr, BINDING **bindingsPtr) { + TAG_NAME *tagNamePtr, BINDING **bindingsPtr, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ ELEMENT_TYPE *elementType; int nDefaultAtts; @@ -3144,7 +3338,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, /* normalize the attribute value */ result = storeAttributeValue( parser, enc, isCdata, parser->m_atts[i].valuePtr, - parser->m_atts[i].valueEnd, &parser->m_tempPool); + parser->m_atts[i].valueEnd, &parser->m_tempPool, account); if (result) return result; appAtts[attIndex] = poolStart(&parser->m_tempPool); @@ -3533,9 +3727,9 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, static enum XML_Error PTRCALL cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { - enum XML_Error result - = doCdataSection(parser, parser->m_encoding, &start, end, endPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + enum XML_Error result = doCdataSection( + parser, parser->m_encoding, &start, end, endPtr, + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result != XML_ERROR_NONE) return result; if (start) { @@ -3555,7 +3749,8 @@ cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, */ static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, - const char *end, const char **nextPtr, XML_Bool haveMore) { + const char *end, const char **nextPtr, XML_Bool haveMore, + enum XML_Account account) { const char *s = *startPtr; const char **eventPP; const char **eventEndPP; @@ -3571,8 +3766,16 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, *startPtr = NULL; for (;;) { - const char *next; + const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */ int tok = XmlCdataSectionTok(enc, s, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#else + UNUSED_P(account); +#endif *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: @@ -3689,7 +3892,7 @@ ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end, static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore) { - const char *next; + const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */ int tok; const char *s = *startPtr; const char **eventPP; @@ -3717,6 +3920,13 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, *eventPP = s; *startPtr = NULL; tok = XmlIgnoreSectionTok(enc, s, end, &next); +# ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +# endif *eventEndPP = next; switch (tok) { case XML_TOK_IGNORE_SECT: @@ -3766,7 +3976,7 @@ initializeEncoding(XML_Parser parser) { const char *s; #ifdef XML_UNICODE char encodingBuf[128]; - /* See comments abount `protoclEncodingName` in parserInit() */ + /* See comments about `protoclEncodingName` in parserInit() */ if (! parser->m_protocolEncodingName) s = NULL; else { @@ -3801,6 +4011,15 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *versionend; const XML_Char *storedversion = NULL; int standalone = -1; + +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif + if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)( isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr, &version, &versionend, &encodingName, &newEncoding, &standalone)) { @@ -3950,6 +4169,10 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { tok = XmlPrologTok(parser->m_encoding, start, end, &next); + /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in: + - storeEntityValue + - processXmlDecl + */ parser->m_eventEndPtr = next; if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { @@ -3968,7 +4191,8 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, break; } /* found end of entity value - can store it now */ - return storeEntityValue(parser, parser->m_encoding, s, end); + return storeEntityValue(parser, parser->m_encoding, s, end, + XML_ACCOUNT_DIRECT); } else if (tok == XML_TOK_XML_DECL) { enum XML_Error result; result = processXmlDecl(parser, 0, start, next); @@ -3995,6 +4219,14 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, */ else if (tok == XML_TOK_BOM && next == end && ! parser->m_parsingStatus.finalBuffer) { +# ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +# endif + *nextPtr = next; return XML_ERROR_NONE; } @@ -4037,16 +4269,24 @@ externalParEntProcessor(XML_Parser parser, const char *s, const char *end, } /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. However, when parsing an external subset, doProlog will not accept a BOM - as valid, and report a syntax error, so we have to skip the BOM + as valid, and report a syntax error, so we have to skip the BOM, and + account for the BOM bytes. */ else if (tok == XML_TOK_BOM) { + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } + s = next; tok = XmlPrologTok(parser->m_encoding, s, end, &next); } parser->m_processor = prologProcessor; return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } static enum XML_Error PTRCALL @@ -4059,6 +4299,9 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { tok = XmlPrologTok(enc, start, end, &next); + /* Note: These bytes are accounted later in: + - storeEntityValue + */ if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; @@ -4076,7 +4319,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end, break; } /* found end of entity value - can store it now */ - return storeEntityValue(parser, enc, s, end); + return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT); } start = next; } @@ -4090,13 +4333,14 @@ prologProcessor(XML_Parser parser, const char *s, const char *end, const char *next = s; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, XML_Bool haveMore, - XML_Bool allowClosingDoctype) { + XML_Bool allowClosingDoctype, enum XML_Account account) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'}; #endif /* XML_DTD */ @@ -4123,6 +4367,10 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'}; static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'}; +#ifndef XML_DTD + UNUSED_P(account); +#endif + /* save one level of indirection */ DTD *const dtd = parser->m_dtd; @@ -4187,6 +4435,19 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, } } role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc); +#ifdef XML_DTD + switch (role) { + case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor + case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl + case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl + break; + default: + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } + } +#endif switch (role) { case XML_ROLE_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 0, s, next); @@ -4462,7 +4723,8 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, const XML_Char *attVal; enum XML_Error result = storeAttributeValue( parser, enc, parser->m_declAttributeIsCdata, - s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool); + s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool, + XML_ACCOUNT_NONE); if (result) return result; attVal = poolStart(&dtd->pool); @@ -4495,8 +4757,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, break; case XML_ROLE_ENTITY_VALUE: if (dtd->keepProcessing) { - enum XML_Error result = storeEntityValue( - parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); + enum XML_Error result + = storeEntityValue(parser, enc, s + enc->minBytesPerChar, + next - enc->minBytesPerChar, XML_ACCOUNT_NONE); if (parser->m_declEntity) { parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool); parser->m_declEntity->textLen @@ -4886,12 +5149,15 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; handleDefault = XML_FALSE; if (! dtd->paramEntityRead) { @@ -5089,6 +5355,13 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end, for (;;) { const char *next = NULL; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, + XML_ACCOUNT_DIRECT)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif parser->m_eventEndPtr = next; switch (tok) { /* report partial linebreak - it might be the last token */ @@ -5162,6 +5435,9 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { return XML_ERROR_NO_MEMORY; } entity->open = XML_TRUE; +#ifdef XML_DTD + entityTrackingOnOpen(parser, entity, __LINE__); +#endif entity->processed = 0; openEntity->next = parser->m_openInternalEntities; parser->m_openInternalEntities = openEntity; @@ -5170,8 +5446,8 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { openEntity->betweenDecl = betweenDecl; openEntity->internalEventPtr = NULL; openEntity->internalEventEndPtr = NULL; - textStart = (char *)entity->textPtr; - textEnd = (char *)(entity->textPtr + entity->textLen); + textStart = (const char *)entity->textPtr; + textEnd = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ next = textStart; @@ -5180,17 +5456,22 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, - tok, next, &next, XML_FALSE, XML_FALSE); + tok, next, &next, XML_FALSE, XML_FALSE, + XML_ACCOUNT_ENTITY_EXPANSION); } else #endif /* XML_DTD */ result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, - textStart, textEnd, &next, XML_FALSE); + textStart, textEnd, &next, XML_FALSE, + XML_ACCOUNT_ENTITY_EXPANSION); if (result == XML_ERROR_NONE) { if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { entity->processed = (int)(next - textStart); parser->m_processor = internalEntityProcessor; } else { +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif /* XML_DTD */ entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ @@ -5213,8 +5494,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, return XML_ERROR_UNEXPECTED_STATE; entity = openEntity->entity; - textStart = ((char *)entity->textPtr) + entity->processed; - textEnd = (char *)(entity->textPtr + entity->textLen); + textStart = ((const char *)entity->textPtr) + entity->processed; + textEnd = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ next = textStart; @@ -5223,20 +5504,24 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, - tok, next, &next, XML_FALSE, XML_TRUE); + tok, next, &next, XML_FALSE, XML_TRUE, + XML_ACCOUNT_ENTITY_EXPANSION); } else #endif /* XML_DTD */ result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding, textStart, textEnd, &next, - XML_FALSE); + XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); if (result != XML_ERROR_NONE) return result; else if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { - entity->processed = (int)(next - (char *)entity->textPtr); + entity->processed = (int)(next - (const char *)entity->textPtr); return result; } else { +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ @@ -5250,7 +5535,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, parser->m_processor = prologProcessor; tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, + XML_ACCOUNT_DIRECT); } else #endif /* XML_DTD */ { @@ -5258,7 +5544,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, /* see externalEntityContentProcessor vs contentProcessor */ return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer); + (XML_Bool)! parser->m_parsingStatus.finalBuffer, + XML_ACCOUNT_DIRECT); } } @@ -5273,9 +5560,10 @@ errorProcessor(XML_Parser parser, const char *s, const char *end, static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, - const char *ptr, const char *end, STRING_POOL *pool) { + const char *ptr, const char *end, STRING_POOL *pool, + enum XML_Account account) { enum XML_Error result - = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); + = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account); if (result) return result; if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) @@ -5287,11 +5575,23 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, - const char *ptr, const char *end, STRING_POOL *pool) { + const char *ptr, const char *end, STRING_POOL *pool, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ +#ifndef XML_DTD + UNUSED_P(account); +#endif + for (;;) { - const char *next; + const char *next + = ptr; /* XmlAttributeValueTok doesn't always set the last arg */ int tok = XmlAttributeValueTok(enc, ptr, end, &next); +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) { + accountingOnAbort(parser); + return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + } +#endif switch (tok) { case XML_TOK_NONE: return XML_ERROR_NONE; @@ -5351,6 +5651,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { +#ifdef XML_DTD + /* NOTE: We are replacing 4-6 characters original input for 1 character + * so there is no amplification and hence recording without + * protection. */ + accountingDiffTolerated(parser, tok, (char *)&ch, + ((char *)&ch) + sizeof(XML_Char), __LINE__, + XML_ACCOUNT_ENTITY_EXPANSION); +#endif /* XML_DTD */ if (! poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; break; @@ -5428,9 +5736,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, enum XML_Error result; const XML_Char *textEnd = entity->textPtr + entity->textLen; entity->open = XML_TRUE; +#ifdef XML_DTD + entityTrackingOnOpen(parser, entity, __LINE__); +#endif result = appendAttributeValue(parser, parser->m_internalEncoding, - isCdata, (char *)entity->textPtr, - (char *)textEnd, pool); + isCdata, (const char *)entity->textPtr, + (const char *)textEnd, pool, + XML_ACCOUNT_ENTITY_EXPANSION); +#ifdef XML_DTD + entityTrackingOnClose(parser, entity, __LINE__); +#endif entity->open = XML_FALSE; if (result) return result; @@ -5460,13 +5775,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, - const char *entityTextPtr, const char *entityTextEnd) { + const char *entityTextPtr, const char *entityTextEnd, + enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ STRING_POOL *pool = &(dtd->entityValuePool); enum XML_Error result = XML_ERROR_NONE; #ifdef XML_DTD int oldInEntityValue = parser->m_prologState.inEntityValue; parser->m_prologState.inEntityValue = 1; +#else + UNUSED_P(account); #endif /* XML_DTD */ /* never return Null for the value argument in EntityDeclHandler, since this would indicate an external entity; therefore we @@ -5477,8 +5795,19 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, } for (;;) { - const char *next; + const char *next + = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + +#ifdef XML_DTD + if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__, + account)) { + accountingOnAbort(parser); + result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH; + goto endEntityValue; + } +#endif + switch (tok) { case XML_TOK_PARAM_ENTITY_REF: #ifdef XML_DTD @@ -5514,13 +5843,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; goto endEntityValue; } + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (! dtd->paramEntityRead) dtd->keepProcessing = dtd->standalone; @@ -5528,9 +5860,12 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, dtd->keepProcessing = dtd->standalone; } else { entity->open = XML_TRUE; + entityTrackingOnOpen(parser, entity, __LINE__); result = storeEntityValue( - parser, parser->m_internalEncoding, (char *)entity->textPtr, - (char *)(entity->textPtr + entity->textLen)); + parser, parser->m_internalEncoding, (const char *)entity->textPtr, + (const char *)(entity->textPtr + entity->textLen), + XML_ACCOUNT_ENTITY_EXPANSION); + entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (result) goto endEntityValue; @@ -6485,7 +6820,7 @@ hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) { iter->p = table->v; - iter->end = iter->p + table->size; + iter->end = iter->p ? iter->p + table->size : NULL; } static NAMED *FASTCALL @@ -6891,3 +7226,755 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { memcpy(result, s, charsRequired * sizeof(XML_Char)); return result; } + +#ifdef XML_DTD + +static float +accountingGetCurrentAmplification(XML_Parser rootParser) { + const XmlBigCount countBytesOutput + = rootParser->m_accounting.countBytesDirect + + rootParser->m_accounting.countBytesIndirect; + const float amplificationFactor + = rootParser->m_accounting.countBytesDirect + ? (countBytesOutput + / (float)(rootParser->m_accounting.countBytesDirect)) + : 1.0f; + assert(! rootParser->m_parentParser); + return amplificationFactor; +} + +static void +accountingReportStats(XML_Parser originParser, const char *epilog) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + if (rootParser->m_accounting.debugLevel < 1) { + return; + } + + const float amplificationFactor + = accountingGetCurrentAmplification(rootParser); + fprintf(stderr, + "expat: Accounting(%p): Direct " EXPAT_FMT_ULL( + "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s", + (void *)rootParser, rootParser->m_accounting.countBytesDirect, + rootParser->m_accounting.countBytesIndirect, + (double)amplificationFactor, epilog); +} + +static void +accountingOnAbort(XML_Parser originParser) { + accountingReportStats(originParser, " ABORTING\n"); +} + +static void +accountingReportDiff(XML_Parser rootParser, + unsigned int levelsAwayFromRootParser, const char *before, + const char *after, ptrdiff_t bytesMore, int source_line, + enum XML_Account account) { + assert(! rootParser->m_parentParser); + + fprintf(stderr, + " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"", + bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP", + levelsAwayFromRootParser, source_line, 10, ""); + + const char ellipis[] = "[..]"; + const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1; + const unsigned int contextLength = 10; + + /* Note: Performance is of no concern here */ + const char *walker = before; + if ((rootParser->m_accounting.debugLevel >= 3) + || (after - before) + <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) { + for (; walker < after; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + } else { + for (; walker < before + contextLength; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + fprintf(stderr, ellipis); + walker = after - contextLength; + for (; walker < after; walker++) { + fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); + } + } + fprintf(stderr, "\"\n"); +} + +static XML_Bool +accountingDiffTolerated(XML_Parser originParser, int tok, const char *before, + const char *after, int source_line, + enum XML_Account account) { + /* Note: We need to check the token type *first* to be sure that + * we can even access variable , safely. + * E.g. for XML_TOK_NONE may hold an invalid pointer. */ + switch (tok) { + case XML_TOK_INVALID: + case XML_TOK_PARTIAL: + case XML_TOK_PARTIAL_CHAR: + case XML_TOK_NONE: + return XML_TRUE; + } + + if (account == XML_ACCOUNT_NONE) + return XML_TRUE; /* because these bytes have been accounted for, already */ + + unsigned int levelsAwayFromRootParser; + const XML_Parser rootParser + = getRootParserOf(originParser, &levelsAwayFromRootParser); + assert(! rootParser->m_parentParser); + + const int isDirect + = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser); + const ptrdiff_t bytesMore = after - before; + + XmlBigCount *const additionTarget + = isDirect ? &rootParser->m_accounting.countBytesDirect + : &rootParser->m_accounting.countBytesIndirect; + + /* Detect and avoid integer overflow */ + if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore) + return XML_FALSE; + *additionTarget += bytesMore; + + const XmlBigCount countBytesOutput + = rootParser->m_accounting.countBytesDirect + + rootParser->m_accounting.countBytesIndirect; + const float amplificationFactor + = accountingGetCurrentAmplification(rootParser); + const XML_Bool tolerated + = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes) + || (amplificationFactor + <= rootParser->m_accounting.maximumAmplificationFactor); + + if (rootParser->m_accounting.debugLevel >= 2) { + accountingReportStats(rootParser, ""); + accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after, + bytesMore, source_line, account); + } + + return tolerated; +} + +unsigned long long +testingAccountingGetCountBytesDirect(XML_Parser parser) { + if (! parser) + return 0; + return parser->m_accounting.countBytesDirect; +} + +unsigned long long +testingAccountingGetCountBytesIndirect(XML_Parser parser) { + if (! parser) + return 0; + return parser->m_accounting.countBytesIndirect; +} + +static void +entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity, + const char *action, int sourceLine) { + assert(! rootParser->m_parentParser); + if (rootParser->m_entity_stats.debugLevel < 1) + return; + +# if defined(XML_UNICODE) + const char *const entityName = "[..]"; +# else + const char *const entityName = entity->name; +# endif + + fprintf( + stderr, + "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n", + (void *)rootParser, rootParser->m_entity_stats.countEverOpened, + rootParser->m_entity_stats.currentDepth, + rootParser->m_entity_stats.maximumDepthSeen, + (rootParser->m_entity_stats.currentDepth - 1) * 2, "", + entity->is_param ? "%" : "&", entityName, action, entity->textLen, + sourceLine); +} + +static void +entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + rootParser->m_entity_stats.countEverOpened++; + rootParser->m_entity_stats.currentDepth++; + if (rootParser->m_entity_stats.currentDepth + > rootParser->m_entity_stats.maximumDepthSeen) { + rootParser->m_entity_stats.maximumDepthSeen++; + } + + entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine); +} + +static void +entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) { + const XML_Parser rootParser = getRootParserOf(originParser, NULL); + assert(! rootParser->m_parentParser); + + entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine); + rootParser->m_entity_stats.currentDepth--; +} + +static XML_Parser +getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { + XML_Parser rootParser = parser; + unsigned int stepsTakenUpwards = 0; + while (rootParser->m_parentParser) { + rootParser = rootParser->m_parentParser; + stepsTakenUpwards++; + } + assert(! rootParser->m_parentParser); + if (outLevelDiff != NULL) { + *outLevelDiff = stepsTakenUpwards; + } + return rootParser; +} + +const char * +unsignedCharToPrintable(unsigned char c) { + switch (c) { + case 0: + return "\\0"; + case 1: + return "\\x1"; + case 2: + return "\\x2"; + case 3: + return "\\x3"; + case 4: + return "\\x4"; + case 5: + return "\\x5"; + case 6: + return "\\x6"; + case 7: + return "\\x7"; + case 8: + return "\\x8"; + case 9: + return "\\t"; + case 10: + return "\\n"; + case 11: + return "\\xB"; + case 12: + return "\\xC"; + case 13: + return "\\r"; + case 14: + return "\\xE"; + case 15: + return "\\xF"; + case 16: + return "\\x10"; + case 17: + return "\\x11"; + case 18: + return "\\x12"; + case 19: + return "\\x13"; + case 20: + return "\\x14"; + case 21: + return "\\x15"; + case 22: + return "\\x16"; + case 23: + return "\\x17"; + case 24: + return "\\x18"; + case 25: + return "\\x19"; + case 26: + return "\\x1A"; + case 27: + return "\\x1B"; + case 28: + return "\\x1C"; + case 29: + return "\\x1D"; + case 30: + return "\\x1E"; + case 31: + return "\\x1F"; + case 32: + return " "; + case 33: + return "!"; + case 34: + return "\\\""; + case 35: + return "#"; + case 36: + return "$"; + case 37: + return "%"; + case 38: + return "&"; + case 39: + return "'"; + case 40: + return "("; + case 41: + return ")"; + case 42: + return "*"; + case 43: + return "+"; + case 44: + return ","; + case 45: + return "-"; + case 46: + return "."; + case 47: + return "/"; + case 48: + return "0"; + case 49: + return "1"; + case 50: + return "2"; + case 51: + return "3"; + case 52: + return "4"; + case 53: + return "5"; + case 54: + return "6"; + case 55: + return "7"; + case 56: + return "8"; + case 57: + return "9"; + case 58: + return ":"; + case 59: + return ";"; + case 60: + return "<"; + case 61: + return "="; + case 62: + return ">"; + case 63: + return "?"; + case 64: + return "@"; + case 65: + return "A"; + case 66: + return "B"; + case 67: + return "C"; + case 68: + return "D"; + case 69: + return "E"; + case 70: + return "F"; + case 71: + return "G"; + case 72: + return "H"; + case 73: + return "I"; + case 74: + return "J"; + case 75: + return "K"; + case 76: + return "L"; + case 77: + return "M"; + case 78: + return "N"; + case 79: + return "O"; + case 80: + return "P"; + case 81: + return "Q"; + case 82: + return "R"; + case 83: + return "S"; + case 84: + return "T"; + case 85: + return "U"; + case 86: + return "V"; + case 87: + return "W"; + case 88: + return "X"; + case 89: + return "Y"; + case 90: + return "Z"; + case 91: + return "["; + case 92: + return "\\\\"; + case 93: + return "]"; + case 94: + return "^"; + case 95: + return "_"; + case 96: + return "`"; + case 97: + return "a"; + case 98: + return "b"; + case 99: + return "c"; + case 100: + return "d"; + case 101: + return "e"; + case 102: + return "f"; + case 103: + return "g"; + case 104: + return "h"; + case 105: + return "i"; + case 106: + return "j"; + case 107: + return "k"; + case 108: + return "l"; + case 109: + return "m"; + case 110: + return "n"; + case 111: + return "o"; + case 112: + return "p"; + case 113: + return "q"; + case 114: + return "r"; + case 115: + return "s"; + case 116: + return "t"; + case 117: + return "u"; + case 118: + return "v"; + case 119: + return "w"; + case 120: + return "x"; + case 121: + return "y"; + case 122: + return "z"; + case 123: + return "{"; + case 124: + return "|"; + case 125: + return "}"; + case 126: + return "~"; + case 127: + return "\\x7F"; + case 128: + return "\\x80"; + case 129: + return "\\x81"; + case 130: + return "\\x82"; + case 131: + return "\\x83"; + case 132: + return "\\x84"; + case 133: + return "\\x85"; + case 134: + return "\\x86"; + case 135: + return "\\x87"; + case 136: + return "\\x88"; + case 137: + return "\\x89"; + case 138: + return "\\x8A"; + case 139: + return "\\x8B"; + case 140: + return "\\x8C"; + case 141: + return "\\x8D"; + case 142: + return "\\x8E"; + case 143: + return "\\x8F"; + case 144: + return "\\x90"; + case 145: + return "\\x91"; + case 146: + return "\\x92"; + case 147: + return "\\x93"; + case 148: + return "\\x94"; + case 149: + return "\\x95"; + case 150: + return "\\x96"; + case 151: + return "\\x97"; + case 152: + return "\\x98"; + case 153: + return "\\x99"; + case 154: + return "\\x9A"; + case 155: + return "\\x9B"; + case 156: + return "\\x9C"; + case 157: + return "\\x9D"; + case 158: + return "\\x9E"; + case 159: + return "\\x9F"; + case 160: + return "\\xA0"; + case 161: + return "\\xA1"; + case 162: + return "\\xA2"; + case 163: + return "\\xA3"; + case 164: + return "\\xA4"; + case 165: + return "\\xA5"; + case 166: + return "\\xA6"; + case 167: + return "\\xA7"; + case 168: + return "\\xA8"; + case 169: + return "\\xA9"; + case 170: + return "\\xAA"; + case 171: + return "\\xAB"; + case 172: + return "\\xAC"; + case 173: + return "\\xAD"; + case 174: + return "\\xAE"; + case 175: + return "\\xAF"; + case 176: + return "\\xB0"; + case 177: + return "\\xB1"; + case 178: + return "\\xB2"; + case 179: + return "\\xB3"; + case 180: + return "\\xB4"; + case 181: + return "\\xB5"; + case 182: + return "\\xB6"; + case 183: + return "\\xB7"; + case 184: + return "\\xB8"; + case 185: + return "\\xB9"; + case 186: + return "\\xBA"; + case 187: + return "\\xBB"; + case 188: + return "\\xBC"; + case 189: + return "\\xBD"; + case 190: + return "\\xBE"; + case 191: + return "\\xBF"; + case 192: + return "\\xC0"; + case 193: + return "\\xC1"; + case 194: + return "\\xC2"; + case 195: + return "\\xC3"; + case 196: + return "\\xC4"; + case 197: + return "\\xC5"; + case 198: + return "\\xC6"; + case 199: + return "\\xC7"; + case 200: + return "\\xC8"; + case 201: + return "\\xC9"; + case 202: + return "\\xCA"; + case 203: + return "\\xCB"; + case 204: + return "\\xCC"; + case 205: + return "\\xCD"; + case 206: + return "\\xCE"; + case 207: + return "\\xCF"; + case 208: + return "\\xD0"; + case 209: + return "\\xD1"; + case 210: + return "\\xD2"; + case 211: + return "\\xD3"; + case 212: + return "\\xD4"; + case 213: + return "\\xD5"; + case 214: + return "\\xD6"; + case 215: + return "\\xD7"; + case 216: + return "\\xD8"; + case 217: + return "\\xD9"; + case 218: + return "\\xDA"; + case 219: + return "\\xDB"; + case 220: + return "\\xDC"; + case 221: + return "\\xDD"; + case 222: + return "\\xDE"; + case 223: + return "\\xDF"; + case 224: + return "\\xE0"; + case 225: + return "\\xE1"; + case 226: + return "\\xE2"; + case 227: + return "\\xE3"; + case 228: + return "\\xE4"; + case 229: + return "\\xE5"; + case 230: + return "\\xE6"; + case 231: + return "\\xE7"; + case 232: + return "\\xE8"; + case 233: + return "\\xE9"; + case 234: + return "\\xEA"; + case 235: + return "\\xEB"; + case 236: + return "\\xEC"; + case 237: + return "\\xED"; + case 238: + return "\\xEE"; + case 239: + return "\\xEF"; + case 240: + return "\\xF0"; + case 241: + return "\\xF1"; + case 242: + return "\\xF2"; + case 243: + return "\\xF3"; + case 244: + return "\\xF4"; + case 245: + return "\\xF5"; + case 246: + return "\\xF6"; + case 247: + return "\\xF7"; + case 248: + return "\\xF8"; + case 249: + return "\\xF9"; + case 250: + return "\\xFA"; + case 251: + return "\\xFB"; + case 252: + return "\\xFC"; + case 253: + return "\\xFD"; + case 254: + return "\\xFE"; + case 255: + return "\\xFF"; + default: + assert(0); /* never gets here */ + return "dead code"; + } + assert(0); /* never gets here */ +} + +#endif /* XML_DTD */ + +static unsigned long +getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) { + const char *const valueOrNull = getenv(variableName); + if (valueOrNull == NULL) { + return defaultDebugLevel; + } + const char *const value = valueOrNull; + + errno = 0; + char *afterValue = (char *)value; + unsigned long debugLevel = strtoul(value, &afterValue, 10); + if ((errno != 0) || (afterValue[0] != '\0')) { + errno = 0; + return defaultDebugLevel; + } + + return debugLevel; +} diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c index 4d3e3e86e9e864..08173b0fd541d2 100644 --- a/Modules/expat/xmlrole.c +++ b/Modules/expat/xmlrole.c @@ -7,7 +7,14 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2002-2003 Fred L. Drake, Jr. + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -34,11 +41,9 @@ #ifdef _WIN32 # include "winconfig.h" -#else -# ifdef HAVE_EXPAT_CONFIG_H -# include -# endif -#endif /* ndef _WIN32 */ +#endif + +#include #include "expat_external.h" #include "internal.h" @@ -1220,6 +1225,8 @@ common(PROLOG_STATE *state, int tok) { #ifdef XML_DTD if (! state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) return XML_ROLE_INNER_PARAM_ENTITY_REF; +#else + UNUSED_P(tok); #endif state->handler = error; return XML_ROLE_ERROR; diff --git a/Modules/expat/xmlrole.h b/Modules/expat/xmlrole.h index 036aba64fd29c6..d6e1fa150a108a 100644 --- a/Modules/expat/xmlrole.h +++ b/Modules/expat/xmlrole.h @@ -7,7 +7,10 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Karl Waclawek + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c index 54cfedb85c28c4..5b935718743add 100644 --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -7,7 +7,19 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2001-2003 Fred L. Drake, Jr. + Copyright (c) 2002 Greg Stein + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2005-2009 Steven Solie + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016 Pascal Cuoq + Copyright (c) 2016 Don Lewis + Copyright (c) 2017 Rhodri James + Copyright (c) 2017 Alexander Bluhm + Copyright (c) 2017 Benbuck Nason + Copyright (c) 2017 José Gutiérrez de la Concha + Copyright (c) 2019 David Loffredo Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -32,23 +44,13 @@ #ifdef _WIN32 # include "winconfig.h" -#else -# ifdef HAVE_EXPAT_CONFIG_H -# include -# endif -#endif /* ndef _WIN32 */ +#endif + +#include #include #include /* memcpy */ - -#if defined(_MSC_VER) && (_MSC_VER <= 1700) -/* for vs2012/11.0/1700 and earlier Visual Studio compilers */ -# define bool int -# define false 0 -# define true 1 -#else -# include -#endif +#include #include "expat_external.h" #include "internal.h" @@ -269,8 +271,14 @@ sb_byteToAscii(const ENCODING *enc, const char *p) { #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p)) -#define IS_INVALID_CHAR(enc, p, n) \ - (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#ifdef XML_MIN_SIZE +# define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid##n \ + && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#else +# define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) +#endif #ifdef XML_MIN_SIZE # define IS_NAME_CHAR_MINBPC(enc, p) \ @@ -589,13 +597,13 @@ static const struct normal_encoding ascii_encoding static int PTRFASTCALL unicode_byte_type(char hi, char lo) { switch ((unsigned char)hi) { - /* 0xD800–0xDBFF first 16-bit code unit or high surrogate (W1) */ + /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */ case 0xD8: case 0xD9: case 0xDA: case 0xDB: return BT_LEAD4; - /* 0xDC00–0xDFFF second 16-bit code unit or low surrogate (W2) */ + /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */ case 0xDC: case 0xDD: case 0xDE: diff --git a/Modules/expat/xmltok.h b/Modules/expat/xmltok.h index 2adbf5307befae..6f630c2f9ba96d 100644 --- a/Modules/expat/xmltok.h +++ b/Modules/expat/xmltok.h @@ -7,7 +7,11 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2005 Karl Waclawek + Copyright (c) 2016-2017 Sebastian Pipping + Copyright (c) 2017 Rhodri James Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/xmltok_impl.c b/Modules/expat/xmltok_impl.c index c209221cd79d13..0430591b42636e 100644 --- a/Modules/expat/xmltok_impl.c +++ b/Modules/expat/xmltok_impl.c @@ -1,4 +1,4 @@ -/* This file is included! +/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)! __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -7,7 +7,15 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2016 Karl Waclawek + Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2017 Rhodri James + Copyright (c) 2018 Benjamin Peterson + Copyright (c) 2018 Anton Maklakov + Copyright (c) 2019 David Loffredo + Copyright (c) 2020 Boris Kolpackov Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -32,7 +40,7 @@ #ifdef XML_TOK_IMPL_C -# ifndef IS_INVALID_CHAR +# ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined # define IS_INVALID_CHAR(enc, ptr, n) (0) # endif @@ -1768,13 +1776,14 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, # define LEAD_CASE(n) \ case BT_LEAD##n: \ ptr += n; \ + pos->columnNumber++; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_LF: - pos->columnNumber = (XML_Size)-1; + pos->columnNumber = 0; pos->lineNumber++; ptr += MINBPC(enc); break; @@ -1783,13 +1792,13 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, ptr += MINBPC(enc); if (HAS_CHAR(enc, ptr, end) && BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); - pos->columnNumber = (XML_Size)-1; + pos->columnNumber = 0; break; default: ptr += MINBPC(enc); + pos->columnNumber++; break; } - pos->columnNumber++; } } diff --git a/Modules/expat/xmltok_impl.h b/Modules/expat/xmltok_impl.h index e925dbc7e2c833..c518aada013df2 100644 --- a/Modules/expat/xmltok_impl.h +++ b/Modules/expat/xmltok_impl.h @@ -7,7 +7,8 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2017-2019 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/expat/xmltok_ns.c b/Modules/expat/xmltok_ns.c index 919c74e9f97fe8..5fd83922359400 100644 --- a/Modules/expat/xmltok_ns.c +++ b/Modules/expat/xmltok_ns.c @@ -7,7 +7,11 @@ |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2000 Clark Cooper + Copyright (c) 2002 Greg Stein + Copyright (c) 2002 Fred L. Drake, Jr. + Copyright (c) 2002-2006 Karl Waclawek + Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/Modules/gc_weakref.txt b/Modules/gc_weakref.txt index 2f18402c02a51d..6d07cce1236431 100644 --- a/Modules/gc_weakref.txt +++ b/Modules/gc_weakref.txt @@ -47,10 +47,10 @@ soon as we execute Python code, threads other than the gc thread can run too, and they can do ordinary things with weakrefs that end up resurrecting CT while gc is running. - http://www.python.org/sf/1055820 + https://www.python.org/sf/1055820 shows how innocent it can be, and also how nasty. Variants of the three -focussed test cases attached to that bug report are now part of Python's +focused test cases attached to that bug report are now part of Python's standard Lib/test/test_gc.py. Jim Fulton gave the best nutshell summary of the new (in 2.4 and 2.3.5) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index e5e5aa3287b0d6..805a159d53d60f 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -2162,12 +2162,36 @@ _PyGC_DumpShutdownStats(PyInterpreterState *interp) } } + +static void +gc_fini_untrack(PyGC_Head *list) +{ + PyGC_Head *gc; + for (gc = GC_NEXT(list); gc != list; gc = GC_NEXT(list)) { + PyObject *op = FROM_GC(gc); + _PyObject_GC_UNTRACK(op); + } +} + + void _PyGC_Fini(PyInterpreterState *interp) { GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + + if (!_Py_IsMainInterpreter(interp)) { + // bpo-46070: Explicitly untrack all objects currently tracked by the + // GC. Otherwise, if an object is used later by another interpreter, + // calling PyObject_GC_UnTrack() on the object crashs if the previous + // or the next object of the PyGC_Head structure became a dangling + // pointer. + for (int i = 0; i < NUM_GENERATIONS; i++) { + PyGC_Head *gen = GEN_HEAD(gcstate, i); + gc_fini_untrack(gen); + } + } } /* for debugging */ diff --git a/Modules/getbuildinfo.c b/Modules/getbuildinfo.c index 5f941a26e1d54c..7cb7397a22c8ab 100644 --- a/Modules/getbuildinfo.c +++ b/Modules/getbuildinfo.c @@ -40,8 +40,9 @@ Py_GetBuildInfo(void) const char *revision = _Py_gitversion(); const char *sep = *revision ? ":" : ""; const char *gitid = _Py_gitidentifier(); - if (!(*gitid)) - gitid = "default"; + if (!(*gitid)) { + gitid = "main"; + } PyOS_snprintf(buildinfo, sizeof(buildinfo), "%s%s%s, %.20s, %.9s", gitid, sep, revision, DATE, TIME); diff --git a/Modules/getpath.c b/Modules/getpath.c index 44453f29df703a..ef6dd59a084d8d 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1263,6 +1263,7 @@ calculate_read_pyenv(PyCalculatePath *calculate) status = calculate_open_pyenv(calculate, &env_file); if (_PyStatus_EXCEPTION(status)) { + assert(env_file == NULL); return status; } if (env_file == NULL) { @@ -1504,7 +1505,7 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } /* If a pyvenv.cfg configure file is found, - argv0_path is overriden with its 'home' variable. */ + argv0_path is overridden with its 'home' variable. */ status = calculate_read_pyenv(calculate); if (_PyStatus_EXCEPTION(status)) { return status; diff --git a/Modules/hashlib.h b/Modules/hashlib.h index 978593e2f1a0c2..56ae7a5e50bf58 100644 --- a/Modules/hashlib.h +++ b/Modules/hashlib.h @@ -8,7 +8,7 @@ #define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \ if (PyUnicode_Check((obj))) { \ PyErr_SetString(PyExc_TypeError, \ - "Unicode-objects must be encoded before hashing");\ + "Strings must be encoded before hashing");\ erraction; \ } \ if (!PyObject_CheckBuffer((obj))) { \ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 293735a886428b..643f47b045046c 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -863,7 +863,7 @@ static PyObject * tee_fromiterable(PyObject *iterable) { teeobject *to; - PyObject *it = NULL; + PyObject *it; it = PyObject_GetIter(iterable); if (it == NULL) @@ -873,21 +873,22 @@ tee_fromiterable(PyObject *iterable) goto done; } - to = PyObject_GC_New(teeobject, &tee_type); - if (to == NULL) - goto done; - to->dataobj = (teedataobject *)teedataobject_newinternal(it); - if (!to->dataobj) { - PyObject_GC_Del(to); + PyObject *dataobj = teedataobject_newinternal(it); + if (!dataobj) { to = NULL; goto done; } - + to = PyObject_GC_New(teeobject, &tee_type); + if (to == NULL) { + Py_DECREF(dataobj); + goto done; + } + to->dataobj = (teedataobject *)dataobj; to->index = 0; to->weakreflist = NULL; PyObject_GC_Track(to); done: - Py_XDECREF(it); + Py_DECREF(it); return (PyObject *)to; } diff --git a/Modules/makesetup b/Modules/makesetup index fefe3fd129ee3b..1a767838c92be9 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -231,7 +231,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *) src='$(srcdir)/'"$srcdir/$src";; esac case $doconfig in - no) cc="$cc \$(CCSHARED) \$(PY_CFLAGS) \$(PY_CPPFLAGS)";; + no) cc="$cc \$(CCSHARED) \$(PY_CFLAGS_NODIST) \$(PY_CPPFLAGS)";; *) cc="$cc \$(PY_BUILTIN_MODULE_CFLAGS)";; esac diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index d0dd12d25966a1..4534176adce14b 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -845,13 +845,15 @@ math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs) Py_SETREF(res, PyNumber_Absolute(res)); return res; } + + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < nargs; i++) { x = _PyNumber_Index(args[i]); if (x == NULL) { Py_DECREF(res); return NULL; } - if (res == _PyLong_GetOne()) { + if (res == one) { /* Fast path: just check arguments. It is okay to use identity comparison here. */ Py_DECREF(x); @@ -918,13 +920,15 @@ math_lcm(PyObject *module, PyObject * const *args, Py_ssize_t nargs) Py_SETREF(res, PyNumber_Absolute(res)); return res; } + + PyObject *zero = _PyLong_GetZero(); // borrowed ref for (i = 1; i < nargs; i++) { x = PyNumber_Index(args[i]); if (x == NULL) { Py_DECREF(res); return NULL; } - if (res == _PyLong_GetZero()) { + if (res == zero) { /* Fast path: just check arguments. It is okay to use identity comparison here. */ Py_DECREF(x); @@ -973,9 +977,13 @@ is_error(double x) * On some platforms (Ubuntu/ia64) it seems that errno can be * set to ERANGE for subnormal results that do *not* underflow * to zero. So to be safe, we'll ignore ERANGE whenever the - * function result is less than one in absolute value. + * function result is less than 1.5 in absolute value. + * + * bpo-46018: Changed to 1.5 to ensure underflows in expm1() + * are correctly detected, since the function may underflow + * toward -1.0 rather than 0.0. */ - if (fabs(x) < 1.0) + if (fabs(x) < 1.5) result = 0; else PyErr_SetString(PyExc_OverflowError, @@ -3077,14 +3085,9 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start) } if (result == NULL) { - result = PyLong_FromLong(1); - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } else { - Py_INCREF(result); + result = _PyLong_GetOne(); } + Py_INCREF(result); #ifndef SLOW_PROD /* Fast paths for integers keeping temporary products in C. * Assumes all inputs are the same type. @@ -3100,7 +3103,7 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start) } /* Loop over all the items in the iterable until we finish, we overflow * or we found a non integer element */ - while(result == NULL) { + while (result == NULL) { item = PyIter_Next(iter); if (item == NULL) { Py_DECREF(iter); @@ -3293,10 +3296,10 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) goto done; } - factor = n; - Py_INCREF(factor); + factor = Py_NewRef(n); + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, _PyLong_GetOne())); + Py_SETREF(factor, PyNumber_Subtract(factor, one)); if (factor == NULL) { goto error; } @@ -3415,10 +3418,10 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) goto done; } - factor = n; - Py_INCREF(factor); + factor = Py_NewRef(n); + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, _PyLong_GetOne())); + Py_SETREF(factor, PyNumber_Subtract(factor, one)); if (factor == NULL) { goto error; } diff --git a/Modules/md5module.c b/Modules/md5module.c index 9067c27a1181ea..b50d2e5b0bdb71 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -333,16 +333,25 @@ md5_get_state(PyObject *module) static MD5object * newMD5object(MD5State * st) { - return (MD5object *)PyObject_New(MD5object, st->md5_type); + MD5object *md5 = (MD5object *)PyObject_GC_New(MD5object, st->md5_type); + PyObject_GC_Track(md5); + return md5; } /* Internal methods for a hash object */ +static int +MD5_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void MD5_dealloc(PyObject *ptr) { PyTypeObject *tp = Py_TYPE(ptr); - PyObject_Free(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); Py_DECREF(tp); } @@ -478,13 +487,15 @@ static PyType_Slot md5_type_slots[] = { {Py_tp_dealloc, MD5_dealloc}, {Py_tp_methods, MD5_methods}, {Py_tp_getset, MD5_getseters}, + {Py_tp_traverse, MD5_traverse}, {0,0} }; static PyType_Spec md5_type_spec = { .name = "_md5.md5", .basicsize = sizeof(MD5object), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = md5_type_slots }; diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 9a2542f824c5c4..6397b0d4b81095 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -126,10 +126,18 @@ get_mmap_state(PyObject *module) return state; } +static int +mmap_object_traverse(mmap_object *m_obj, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(m_obj)); + return 0; +} + static void mmap_object_dealloc(mmap_object *m_obj) { PyTypeObject *tp = Py_TYPE(m_obj); + PyObject_GC_UnTrack(m_obj); #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS @@ -1085,15 +1093,14 @@ To map anonymous memory, pass -1 as the fileno (both versions)."); static PyType_Slot mmap_object_slots[] = { {Py_tp_new, new_mmap_object}, - {Py_tp_alloc, PyType_GenericAlloc}, {Py_tp_dealloc, mmap_object_dealloc}, - {Py_tp_free, PyObject_Del}, {Py_tp_repr, mmap__repr__method}, {Py_tp_doc, (void *)mmap_doc}, {Py_tp_methods, mmap_object_methods}, {Py_tp_members, mmap_object_members}, {Py_tp_getset, mmap_object_getset}, {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mmap_object_traverse}, /* as sequence */ {Py_sq_length, mmap_length}, @@ -1114,7 +1121,8 @@ static PyType_Slot mmap_object_slots[] = { static PyType_Spec mmap_object_spec = { .name = "mmap.mmap", .basicsize = sizeof(mmap_object), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = mmap_object_slots, }; diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 38dd98f084849e..7c4570896bc591 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -1876,7 +1876,7 @@ static PyType_Slot overlapped_type_slots[] = { static PyType_Spec overlapped_type_spec = { .name = "_overlapped.Overlapped", .basicsize = sizeof(OverlappedObject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), .slots = overlapped_type_slots }; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 25ddc82cb893ab..03de4703239a7c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5930,6 +5930,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } +#ifdef HAVE_SIGSET_T if (setsigmask) { sigset_t set; if (!_Py_Sigset_Converter(setsigmask, &set)) { @@ -5955,6 +5956,13 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg } all_flags |= POSIX_SPAWN_SETSIGDEF; } +#else + if (setsigmask || setsigdef) { + PyErr_SetString(PyExc_NotImplementedError, + "sigset is not supported on this platform"); + goto fail; + } +#endif if (scheduler) { #ifdef POSIX_SPAWN_SETSCHEDULER @@ -10062,9 +10070,11 @@ os_isatty_impl(PyObject *module, int fd) /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ { int return_value; + Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH return_value = isatty(fd); _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS return return_value; } diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 711ac686934b02..5452ffbf17acfc 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -23,9 +23,7 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *); # define HAVE_SIGSET_T #endif -#ifdef HAVE_SIGSET_T PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); -#endif /* HAVE_SIGSET_T */ #endif /* Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 7f727a86f5f47d..b3d9bdda7e7ac5 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1182,19 +1182,34 @@ newxmlparseobject(pyexpat_state *state, const char *encoding, return (PyObject*)self; } +static int +xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) +{ + for (int i = 0; handler_info[i].name != NULL; i++) { + Py_VISIT(op->handlers[i]); + } + Py_VISIT(Py_TYPE(op)); + return 0; +} + +static int +xmlparse_clear(xmlparseobject *op) +{ + clear_handlers(op, 0); + Py_CLEAR(op->intern); + return 0; +} static void xmlparse_dealloc(xmlparseobject *self) { - int i; PyObject_GC_UnTrack(self); + (void)xmlparse_clear(self); if (self->itself != NULL) XML_ParserFree(self->itself); self->itself = NULL; if (self->handlers != NULL) { - for (i = 0; handler_info[i].name != NULL; i++) - Py_CLEAR(self->handlers[i]); PyMem_Free(self->handlers); self->handlers = NULL; } @@ -1202,7 +1217,6 @@ xmlparse_dealloc(xmlparseobject *self) PyMem_Free(self->buffer); self->buffer = NULL; } - Py_XDECREF(self->intern); PyTypeObject *tp = Py_TYPE(self); PyObject_GC_Del(self); Py_DECREF(tp); @@ -1473,23 +1487,6 @@ static PyGetSetDef xmlparse_getsetlist[] = { #undef XMLPARSE_GETTER_DEF #undef XMLPARSE_GETTER_SETTER_DEF -static int -xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) -{ - int i; - for (i = 0; handler_info[i].name != NULL; i++) - Py_VISIT(op->handlers[i]); - return 0; -} - -static int -xmlparse_clear(xmlparseobject *op) -{ - clear_handlers(op, 0); - Py_CLEAR(op->intern); - return 0; -} - PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); static PyType_Slot _xml_parse_type_spec_slots[] = { @@ -1507,7 +1504,7 @@ static PyType_Spec _xml_parse_type_spec = { .name = "pyexpat.xmlparser", .basicsize = sizeof(xmlparseobject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_DISALLOW_INSTANTIATION), + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), .slots = _xml_parse_type_spec_slots, }; diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 1d4bde2d3b67bb..d186aa460a07b1 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -269,7 +269,7 @@ sha1_done(struct sha1_state *sha1, unsigned char *out) sha1->curlen = 0; } - /* pad upto 56 bytes of zeroes */ + /* pad up to 56 bytes of zeroes */ while (sha1->curlen < 56) { sha1->buf[sha1->curlen++] = (unsigned char)0; } @@ -310,17 +310,26 @@ sha1_get_state(PyObject *module) static SHA1object * newSHA1object(SHA1State *st) { - return (SHA1object *)PyObject_New(SHA1object, st->sha1_type); + SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA1_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA1_dealloc(PyObject *ptr) { PyTypeObject *tp = Py_TYPE(ptr); - PyObject_Free(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); Py_DECREF(tp); } @@ -456,13 +465,15 @@ static PyType_Slot sha1_type_slots[] = { {Py_tp_dealloc, SHA1_dealloc}, {Py_tp_methods, SHA1_methods}, {Py_tp_getset, SHA1_getseters}, + {Py_tp_traverse, SHA1_traverse}, {0,0} }; static PyType_Spec sha1_type_spec = { .name = "_sha1.sha1", .basicsize = sizeof(SHA1object), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = sha1_type_slots }; diff --git a/Modules/sha256module.c b/Modules/sha256module.c index 1edb9dc0500298..fac7073d951d2d 100644 --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -382,22 +382,35 @@ sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) static SHAobject * newSHA224object(_sha256_state *state) { - return (SHAobject *)PyObject_New(SHAobject, state->sha224_type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, + state->sha224_type); + PyObject_GC_Track(sha); + return sha; } static SHAobject * newSHA256object(_sha256_state *state) { - return (SHAobject *)PyObject_New(SHAobject, state->sha256_type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, + state->sha256_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA_dealloc(PyObject *ptr) { PyTypeObject *tp = Py_TYPE(ptr); - PyObject_Free(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); Py_DECREF(tp); } @@ -538,20 +551,23 @@ static PyType_Slot sha256_types_slots[] = { {Py_tp_methods, SHA_methods}, {Py_tp_members, SHA_members}, {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, {0,0} }; static PyType_Spec sha224_type_spec = { .name = "_sha256.sha224", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = sha256_types_slots }; static PyType_Spec sha256_type_spec = { .name = "_sha256.sha256", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = sha256_types_slots }; diff --git a/Modules/sha512module.c b/Modules/sha512module.c index 2bae0ce78774c1..4ea2fc16de0526 100644 --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -438,22 +438,33 @@ sha512_get_state(PyObject *module) static SHAobject * newSHA384object(SHA512State *st) { - return (SHAobject *)PyObject_New(SHAobject, st->sha384_type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, st->sha384_type); + PyObject_GC_Track(sha); + return sha; } static SHAobject * newSHA512object(SHA512State *st) { - return (SHAobject *)PyObject_New(SHAobject, st->sha512_type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, st->sha512_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA512_dealloc(PyObject *ptr) { PyTypeObject *tp = Py_TYPE(ptr); - PyObject_Free(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); Py_DECREF(tp); } @@ -596,13 +607,15 @@ static PyType_Slot sha512_sha384_type_slots[] = { {Py_tp_methods, SHA_methods}, {Py_tp_members, SHA_members}, {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, {0,0} }; static PyType_Spec sha512_sha384_type_spec = { .name = "_sha512.sha384", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = sha512_sha384_type_slots }; @@ -611,6 +624,7 @@ static PyType_Slot sha512_sha512_type_slots[] = { {Py_tp_methods, SHA_methods}, {Py_tp_members, SHA_members}, {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, {0,0} }; @@ -619,7 +633,8 @@ static PyType_Slot sha512_sha512_type_slots[] = { static PyType_Spec sha512_sha512_type_spec = { .name = "_sha512.sha512", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), .slots = sha512_sha512_type_slots }; diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index a4eeec9807c919..96881d4a49f105 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -58,6 +58,8 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +#ifdef HAVE_SETSIG_T + /*[python input] class sigset_t_converter(CConverter): @@ -66,6 +68,7 @@ class sigset_t_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ +#endif /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -930,6 +933,7 @@ signal_getitimer_impl(PyObject *module, int which) #endif // HAVE_GETITIMER +#ifdef HAVE_SIGSET_T #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -1061,9 +1065,9 @@ signal_sigwait_impl(PyObject *module, sigset_t sigset) } #endif /* #ifdef HAVE_SIGWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ - -#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) +#if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) /*[clinic input] signal.valid_signals @@ -1101,7 +1105,8 @@ signal_valid_signals_impl(PyObject *module) #endif } -#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ +#endif /* #if (defined(HAVE_SIGFILLSET) && defined(HAVE_SIGSET_T)) || defined(MS_WINDOWS) */ + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) @@ -1166,6 +1171,7 @@ fill_siginfo(siginfo_t *si) } #endif +#ifdef HAVE_SIGSET_T #ifdef HAVE_SIGWAITINFO /*[clinic input] @@ -1268,6 +1274,7 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, } #endif /* #ifdef HAVE_SIGTIMEDWAIT */ +#endif /* #ifdef HAVE_SIGSET_T */ #if defined(HAVE_PTHREAD_KILL) @@ -1594,7 +1601,7 @@ signal_get_set_handlers(signal_state_t *state, PyObject *mod_dict) Py_XDECREF(old_func); } - // Instal Python SIGINT handler which raises KeyboardInterrupt + // Install Python SIGINT handler which raises KeyboardInterrupt PyObject* sigint_func = get_handler(SIGINT); if (sigint_func == state->default_handler) { PyObject *int_handler = PyMapping_GetItemString(mod_dict, diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 79559c04d5104d..ab8618b3415447 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -45,7 +45,7 @@ Module interface: - socket.if_nameindex() -> list of tuples (if_index, if_name) - socket.if_nametoindex(name) -> corresponding interface index - socket.if_indextoname(index) -> corresponding interface name -- an Internet socket address is a pair (hostname, port) +- an internet socket address is a pair (hostname, port) where hostname can be anything recognized by gethostbyname() (including the dd.dd.dd.dd notation) and port is in host byte order - where a hostname is returned, the dd.dd.dd.dd notation is used @@ -151,9 +151,6 @@ getblocking() -- return True if socket is blocking, False if non-blocking\n\ setsockopt(level, optname, value[, optlen]) -- set socket options\n\ settimeout(None | float) -- set or clear the timeout\n\ shutdown(how) -- shut down traffic in one or both directions\n\ -if_nameindex() -- return all network interface indices and names\n\ -if_nametoindex(name) -- return the corresponding interface index\n\ -if_indextoname(index) -- return the corresponding interface name\n\ \n\ [*] not available on all platforms!"); @@ -930,7 +927,7 @@ sock_call_ex(PySocketSockObject *s, reading, but the data then discarded by the OS because of a wrong checksum. - Loop on select() to recheck for socket readyness. */ + Loop on select() to recheck for socket readiness. */ continue; } @@ -1516,10 +1513,10 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) #ifdef CAN_J1939 case CAN_J1939: { - return Py_BuildValue("O&KkB", PyUnicode_DecodeFSDefault, + return Py_BuildValue("O&KIB", PyUnicode_DecodeFSDefault, ifname, - a->can_addr.j1939.name, - a->can_addr.j1939.pgn, + (unsigned long long)a->can_addr.j1939.name, + (unsigned int)a->can_addr.j1939.pgn, a->can_addr.j1939.addr); } #endif /* CAN_J1939 */ @@ -2210,13 +2207,13 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, PyObject *interfaceName; struct ifreq ifr; Py_ssize_t len; - uint64_t j1939_name; - uint32_t j1939_pgn; + unsigned long long j1939_name; /* at least 64 bits */ + unsigned int j1939_pgn; /* at least 32 bits */ uint8_t j1939_addr; struct sockaddr_can *addr = &addrbuf->can; - if (!PyArg_ParseTuple(args, "O&KkB", PyUnicode_FSConverter, + if (!PyArg_ParseTuple(args, "O&KIB", PyUnicode_FSConverter, &interfaceName, &j1939_name, &j1939_pgn, @@ -2244,8 +2241,8 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, addr->can_family = AF_CAN; addr->can_ifindex = ifr.ifr_ifindex; - addr->can_addr.j1939.name = j1939_name; - addr->can_addr.j1939.pgn = j1939_pgn; + addr->can_addr.j1939.name = (uint64_t)j1939_name; + addr->can_addr.j1939.pgn = (uint32_t)j1939_pgn; addr->can_addr.j1939.addr = j1939_addr; *len_ret = sizeof(*addr); @@ -8024,6 +8021,9 @@ PyInit__socket(void) #ifdef IP_RECVRETOPTS PyModule_AddIntMacro(m, IP_RECVRETOPTS); #endif +#ifdef IP_RECVTOS + PyModule_AddIntMacro(m, IP_RECVTOS); +#endif #ifdef IP_RECVDSTADDR PyModule_AddIntMacro(m, IP_RECVDSTADDR); #endif @@ -8155,6 +8155,10 @@ PyInit__socket(void) #endif #ifdef TCP_KEEPIDLE PyModule_AddIntMacro(m, TCP_KEEPIDLE); +#endif + /* TCP_KEEPALIVE is OSX's TCP_KEEPIDLE equivalent */ +#if defined(__APPLE__) && defined(TCP_KEEPALIVE) + PyModule_AddIntMacro(m, TCP_KEEPALIVE); #endif #ifdef TCP_KEEPINTVL PyModule_AddIntMacro(m, TCP_KEEPINTVL); diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index cdc94a60a373d7..0f2fea15b3a6f0 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -183,7 +183,7 @@ syslog_syslog(PyObject * self, PyObject * args) PyObject *openargs; /* Continue even if PyTuple_New fails, because openlog(3) is optional. - * So, we can still do loggin in the unlikely event things are so hosed + * So, we can still do logging in the unlikely event things are so hosed * that we can't do this tuple. */ if ((openargs = PyTuple_New(0))) { diff --git a/Modules/termios.c b/Modules/termios.c index a6649598ec1710..fdfe589eb80c1a 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -1004,7 +1004,7 @@ static void termiosmodule_free(void *m) { termiosmodule_clear((PyObject *)m); } -static int +static int termios_exec(PyObject *mod) { struct constant *constant = termios_constants; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 1a41e1c2c527f4..f87eb608798919 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -102,12 +102,13 @@ new_previous_version(PyTypeObject *ucd_type, Py_UCS4 (*normalization)(Py_UCS4)) { PreviousDBVersion *self; - self = PyObject_New(PreviousDBVersion, ucd_type); + self = PyObject_GC_New(PreviousDBVersion, ucd_type); if (self == NULL) return NULL; self->name = name; self->getrecord = getrecord; self->normalization = normalization; + PyObject_GC_Track(self); return (PyObject*)self; } @@ -1435,16 +1436,25 @@ static PyMethodDef unicodedata_functions[] = { {NULL, NULL} /* sentinel */ }; +static int +ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void ucd_dealloc(PreviousDBVersion *self) { PyTypeObject *tp = Py_TYPE(self); - PyObject_Free(self); + PyObject_GC_UnTrack(self); + PyObject_GC_Del(self); Py_DECREF(tp); } static PyType_Slot ucd_type_slots[] = { {Py_tp_dealloc, ucd_dealloc}, + {Py_tp_traverse, ucd_traverse}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_methods, unicodedata_functions}, {Py_tp_members, DB_members}, @@ -1454,7 +1464,8 @@ static PyType_Slot ucd_type_slots[] = { static PyType_Spec ucd_type_spec = { .name = "unicodedata.UCD", .basicsize = sizeof(PreviousDBVersion), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), .slots = ucd_type_slots }; diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index c3d98d34eb5915..9bd9a5407d43c4 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -106,6 +106,13 @@ Xxo_traverse(XxoObject *self, visitproc visit, void *arg) return 0; } +static int +Xxo_clear(XxoObject *self) +{ + Py_CLEAR(self->x_attr); + return 0; +} + static void Xxo_finalize(XxoObject *self) { @@ -214,6 +221,7 @@ PyDoc_STRVAR(Xxo_doc, static PyType_Slot Xxo_Type_slots[] = { {Py_tp_doc, (char *)Xxo_doc}, {Py_tp_traverse, Xxo_traverse}, + {Py_tp_clear, Xxo_clear}, {Py_tp_finalize, Xxo_finalize}, {Py_tp_dealloc, Xxo_dealloc}, {Py_tp_getattro, Xxo_getattro}, diff --git a/Modules/xxlimited_35.c b/Modules/xxlimited_35.c index 5e93854f68571b..647abf6721276c 100644 --- a/Modules/xxlimited_35.c +++ b/Modules/xxlimited_35.c @@ -43,6 +43,13 @@ Xxo_traverse(XxoObject *self, visitproc visit, void *arg) return 0; } +static int +Xxo_clear(XxoObject *self) +{ + Py_CLEAR(self->x_attr); + return 0; +} + static void Xxo_finalize(XxoObject *self) { @@ -108,6 +115,7 @@ Xxo_setattr(XxoObject *self, const char *name, PyObject *v) static PyType_Slot Xxo_Type_slots[] = { {Py_tp_doc, "The Xxo type"}, {Py_tp_traverse, Xxo_traverse}, + {Py_tp_clear, Xxo_clear}, {Py_tp_finalize, Xxo_finalize}, {Py_tp_getattro, Xxo_getattro}, {Py_tp_setattr, Xxo_setattr}, diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index fe06094b0027a6..a6940f2fd43a3f 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -30,28 +30,6 @@ OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length, return allocated; } -/* On success, return value >= 0 - On failure, return -1 */ -static inline Py_ssize_t -OutputBuffer_InitWithSize(_BlocksOutputBuffer *buffer, Py_ssize_t init_size, - Bytef **next_out, uint32_t *avail_out) -{ - Py_ssize_t allocated; - - if (init_size >= 0 && // ensure (size_t) cast is safe - (size_t)init_size > UINT32_MAX) - { - /* In 32-bit build, never reach this conditional branch. - The maximum block size accepted by zlib is UINT32_MAX. */ - init_size = UINT32_MAX; - } - - allocated = _BlocksOutputBuffer_InitWithSize( - buffer, init_size, (void**) next_out); - *avail_out = (uint32_t) allocated; - return allocated; -} - /* On success, return value >= 0 On failure, return -1 */ static inline Py_ssize_t @@ -84,6 +62,106 @@ OutputBuffer_OnError(_BlocksOutputBuffer *buffer) _BlocksOutputBuffer_OnError(buffer); } +/* The max buffer size accepted by zlib is UINT32_MAX, the initial buffer size + `init_size` may > it in 64-bit build. These wrapper functions maintain an + UINT32_MAX sliding window for the first block: + 1. OutputBuffer_WindowInitWithSize() + 2. OutputBuffer_WindowGrow() + 3. OutputBuffer_WindowFinish() + 4. OutputBuffer_WindowOnError() + + ==== is the sliding window: + 1. ====------ + ^ next_posi, left_bytes is 6 + 2. ----====-- + ^ next_posi, left_bytes is 2 + 3. --------== + ^ next_posi, left_bytes is 0 */ +typedef struct { + Py_ssize_t left_bytes; + Bytef *next_posi; +} _Uint32Window; + +/* Initialize the buffer with an initial buffer size. + + On success, return value >= 0 + On failure, return value < 0 */ +static inline Py_ssize_t +OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer *buffer, _Uint32Window *window, + Py_ssize_t init_size, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated = _BlocksOutputBuffer_InitWithSize( + buffer, init_size, (void**) next_out); + + if (allocated >= 0) { + // the UINT32_MAX sliding window + Py_ssize_t window_size = Py_MIN((size_t)allocated, UINT32_MAX); + *avail_out = (uint32_t) window_size; + + window->left_bytes = allocated - window_size; + window->next_posi = *next_out + window_size; + } + return allocated; +} + +/* Grow the buffer. + + On success, return value >= 0 + On failure, return value < 0 */ +static inline Py_ssize_t +OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, _Uint32Window *window, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + /* ensure no gaps in the data. + if inlined, this check could be optimized away.*/ + if (*avail_out != 0) { + PyErr_SetString(PyExc_SystemError, + "*avail_out != 0 in OutputBuffer_WindowGrow()."); + return -1; + } + + // slide the UINT32_MAX sliding window + if (window->left_bytes > 0) { + Py_ssize_t window_size = Py_MIN((size_t)window->left_bytes, UINT32_MAX); + + *next_out = window->next_posi; + *avail_out = (uint32_t) window_size; + + window->left_bytes -= window_size; + window->next_posi += window_size; + + return window_size; + } + assert(window->left_bytes == 0); + + // only the first block may > UINT32_MAX + allocated = _BlocksOutputBuffer_Grow( + buffer, (void**) next_out, (Py_ssize_t) *avail_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +/* Finish the buffer. + + On success, return a bytes object + On failure, return NULL */ +static inline PyObject * +OutputBuffer_WindowFinish(_BlocksOutputBuffer *buffer, _Uint32Window *window, + uint32_t avail_out) +{ + Py_ssize_t real_avail_out = (Py_ssize_t) avail_out + window->left_bytes; + return _BlocksOutputBuffer_Finish(buffer, real_avail_out); +} + +static inline void +OutputBuffer_WindowOnError(_BlocksOutputBuffer *buffer, _Uint32Window *window) +{ + _BlocksOutputBuffer_OnError(buffer); +} + #define ENTER_ZLIB(obj) do { \ if (!PyThread_acquire_lock((obj)->lock, 0)) { \ @@ -344,6 +422,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, int err, flush; z_stream zst; _BlocksOutputBuffer buffer = {.list = NULL}; + _Uint32Window window; // output buffer's UINT32_MAX sliding window zlibstate *state = get_zlib_state(module); @@ -354,7 +433,8 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, bufsize = 1; } - if (OutputBuffer_InitWithSize(&buffer, bufsize, &zst.next_out, &zst.avail_out) < 0) { + if (OutputBuffer_WindowInitWithSize(&buffer, &window, bufsize, + &zst.next_out, &zst.avail_out) < 0) { goto error; } @@ -387,7 +467,8 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, do { if (zst.avail_out == 0) { - if (OutputBuffer_Grow(&buffer, &zst.next_out, &zst.avail_out) < 0) { + if (OutputBuffer_WindowGrow(&buffer, &window, + &zst.next_out, &zst.avail_out) < 0) { inflateEnd(&zst); goto error; } @@ -430,13 +511,13 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, goto error; } - RetVal = OutputBuffer_Finish(&buffer, zst.avail_out); + RetVal = OutputBuffer_WindowFinish(&buffer, &window, zst.avail_out); if (RetVal != NULL) { return RetVal; } error: - OutputBuffer_OnError(&buffer); + OutputBuffer_WindowOnError(&buffer, &window); return NULL; } @@ -1171,6 +1252,7 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, PyObject *RetVal; Py_ssize_t ibuflen; _BlocksOutputBuffer buffer = {.list = NULL}; + _Uint32Window window; // output buffer's UINT32_MAX sliding window PyObject *module = PyType_GetModule(cls); if (module == NULL) { @@ -1184,16 +1266,18 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, return NULL; } + ENTER_ZLIB(self); + if (PyObject_GetBuffer(self->unconsumed_tail, &data, PyBUF_SIMPLE) == -1) { + LEAVE_ZLIB(self); return NULL; } - ENTER_ZLIB(self); - self->zst.next_in = data.buf; ibuflen = data.len; - if (OutputBuffer_InitWithSize(&buffer, length, &self->zst.next_out, &self->zst.avail_out) < 0) { + if (OutputBuffer_WindowInitWithSize(&buffer, &window, length, + &self->zst.next_out, &self->zst.avail_out) < 0) { goto abort; } @@ -1203,7 +1287,8 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, do { if (self->zst.avail_out == 0) { - if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) { + if (OutputBuffer_WindowGrow(&buffer, &window, + &self->zst.next_out, &self->zst.avail_out) < 0) { goto abort; } } @@ -1248,13 +1333,13 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, } } - RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out); + RetVal = OutputBuffer_WindowFinish(&buffer, &window, self->zst.avail_out); if (RetVal != NULL) { goto success; } abort: - OutputBuffer_OnError(&buffer); + OutputBuffer_WindowOnError(&buffer, &window); RetVal = NULL; success: PyBuffer_Release(&data); @@ -1420,7 +1505,7 @@ PyDoc_STRVAR(zlib_module_documentation, "compressobj([level[, ...]]) -- Return a compressor object.\n" "crc32(string[, start]) -- Compute a CRC-32 checksum.\n" "decompress(string,[wbits],[bufsize]) -- Decompresses a compressed string.\n" -"decompressobj([wbits[, zdict]]]) -- Return a decompressor object.\n" +"decompressobj([wbits[, zdict]]) -- Return a decompressor object.\n" "\n" "'wbits' is window buffer size and container format.\n" "Compressor objects support compress() and flush() methods; decompressor\n" diff --git a/Objects/abstract.c b/Objects/abstract.c index fcfe2dbe483f4f..3ac85544defbdd 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -6,7 +6,7 @@ #include "pycore_object.h" // _Py_CheckSlotResult() #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_unionobject.h" // _Py_UnionType && _Py_Union() +#include "pycore_unionobject.h" // _PyUnion_Check() #include #include // offsetof() #include "longintrepr.h" @@ -293,6 +293,85 @@ PyObject_CheckBuffer(PyObject *obj) } +/* We release the buffer right after use of this function which could + cause issues later on. Don't use these functions in new code. + */ +int +PyObject_CheckReadBuffer(PyObject *obj) +{ + PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer; + Py_buffer view; + + if (pb == NULL || + pb->bf_getbuffer == NULL) + return 0; + if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE) == -1) { + PyErr_Clear(); + return 0; + } + PyBuffer_Release(&view); + return 1; +} + +static int +as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len) +{ + Py_buffer view; + + if (obj == NULL || buffer == NULL || buffer_len == NULL) { + null_error(); + return -1; + } + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) + return -1; + + *buffer = view.buf; + *buffer_len = view.len; + PyBuffer_Release(&view); + return 0; +} + +int +PyObject_AsCharBuffer(PyObject *obj, + const char **buffer, + Py_ssize_t *buffer_len) +{ + return as_read_buffer(obj, (const void **)buffer, buffer_len); +} + +int PyObject_AsReadBuffer(PyObject *obj, + const void **buffer, + Py_ssize_t *buffer_len) +{ + return as_read_buffer(obj, buffer, buffer_len); +} + +int PyObject_AsWriteBuffer(PyObject *obj, + void **buffer, + Py_ssize_t *buffer_len) +{ + PyBufferProcs *pb; + Py_buffer view; + + if (obj == NULL || buffer == NULL || buffer_len == NULL) { + null_error(); + return -1; + } + pb = Py_TYPE(obj)->tp_as_buffer; + if (pb == NULL || + pb->bf_getbuffer == NULL || + ((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) { + PyErr_SetString(PyExc_TypeError, + "expected a writable bytes-like object"); + return -1; + } + + *buffer = view.buf; + *buffer_len = view.len; + PyBuffer_Release(&view); + return 0; +} + /* Buffer C-API for Python 3.0 */ int @@ -2478,14 +2557,22 @@ abstract_issubclass(PyObject *derived, PyObject *cls) derived = PyTuple_GET_ITEM(bases, 0); continue; } - for (i = 0; i < n; i++) { - r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); - if (r != 0) - break; - } + break; + } + assert(n >= 2); + if (Py_EnterRecursiveCall(" in __issubclass__")) { Py_DECREF(bases); - return r; + return -1; } + for (i = 0; i < n; i++) { + r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); + if (r != 0) { + break; + } + } + Py_LeaveRecursiveCall(); + Py_DECREF(bases); + return r; } static int @@ -2529,7 +2616,7 @@ object_isinstance(PyObject *inst, PyObject *cls) } else { if (!check_class(cls, - "isinstance() arg 2 must be a type, a tuple of types or a union")) + "isinstance() arg 2 must be a type, a tuple of types, or a union")) return -1; retval = _PyObject_LookupAttrId(inst, &PyId___class__, &icls); if (icls != NULL) { @@ -2623,11 +2710,9 @@ recursive_issubclass(PyObject *derived, PyObject *cls) "issubclass() arg 1 must be a class")) return -1; - PyTypeObject *type = Py_TYPE(cls); - int is_union = (PyType_Check(type) && type == &_Py_UnionType); - if (!is_union && !check_class(cls, + if (!_PyUnion_Check(cls) && !check_class(cls, "issubclass() arg 2 must be a class," - " a tuple of classes, or a union.")) { + " a tuple of classes, or a union")) { return -1; } @@ -2739,18 +2824,18 @@ PyObject_GetIter(PyObject *o) } PyObject * -PyObject_GetAiter(PyObject *o) { +PyObject_GetAIter(PyObject *o) { PyTypeObject *t = Py_TYPE(o); unaryfunc f; if (t->tp_as_async == NULL || t->tp_as_async->am_aiter == NULL) { - return type_error("'%.200s' object is not an AsyncIterable", o); + return type_error("'%.200s' object is not an async iterable", o); } f = t->tp_as_async->am_aiter; PyObject *it = (*f)(o); - if (it != NULL && !PyAiter_Check(it)) { + if (it != NULL && !PyAIter_Check(it)) { PyErr_Format(PyExc_TypeError, - "aiter() returned non-AsyncIterator of type '%.100s'", + "aiter() returned not an async iterator of type '%.100s'", Py_TYPE(it)->tp_name); Py_DECREF(it); it = NULL; @@ -2767,12 +2852,10 @@ PyIter_Check(PyObject *obj) } int -PyAiter_Check(PyObject *obj) +PyAIter_Check(PyObject *obj) { PyTypeObject *tp = Py_TYPE(obj); return (tp->tp_as_async != NULL && - tp->tp_as_async->am_aiter != NULL && - tp->tp_as_async->am_aiter != &_PyObject_NextNotImplemented && tp->tp_as_async->am_anext != NULL && tp->tp_as_async->am_anext != &_PyObject_NextNotImplemented); } @@ -2806,9 +2889,7 @@ PyIter_Send(PyObject *iter, PyObject *arg, PyObject **result) _Py_IDENTIFIER(send); assert(arg != NULL); assert(result != NULL); - if (PyType_HasFeature(Py_TYPE(iter), Py_TPFLAGS_HAVE_AM_SEND)) { - assert (Py_TYPE(iter)->tp_as_async != NULL); - assert (Py_TYPE(iter)->tp_as_async->am_send != NULL); + if (Py_TYPE(iter)->tp_as_async && Py_TYPE(iter)->tp_as_async->am_send) { PySendResult res = Py_TYPE(iter)->tp_as_async->am_send(iter, arg, result); assert(_Py_CheckSlotResult(iter, "am_send", res != PYGEN_ERROR)); return res; diff --git a/Objects/classobject.c b/Objects/classobject.c index fd9f8757f84ab4..af73be3d262411 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -462,7 +462,7 @@ instancemethod_traverse(PyObject *self, visitproc visit, void *arg) { static PyObject * instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw) { - return PyObject_Call(PyMethod_GET_FUNCTION(self), arg, kw); + return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw); } static PyObject * diff --git a/Objects/codeobject.c b/Objects/codeobject.c index c76ac900b3a5e8..976cec584e9f39 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -294,7 +294,7 @@ _PyCode_InitOpcache(PyCodeObject *co) return -1; } - _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code); + const _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code); Py_ssize_t opts = 0; for (Py_ssize_t i = 0; i < co_size;) { @@ -1255,7 +1255,7 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq) } void -PyLineTable_InitAddressRange(char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) +PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) { range->opaque.lo_next = linetable; range->opaque.limit = range->opaque.lo_next + length; @@ -1268,7 +1268,7 @@ PyLineTable_InitAddressRange(char *linetable, Py_ssize_t length, int firstlineno int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds) { - char *linetable = PyBytes_AS_STRING(co->co_linetable); + const char *linetable = PyBytes_AS_STRING(co->co_linetable); Py_ssize_t length = PyBytes_GET_SIZE(co->co_linetable); PyLineTable_InitAddressRange(linetable, length, co->co_firstlineno, bounds); return bounds->ar_line; diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 91e06a8c2c2ab7..3e479497cfcc31 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -172,14 +172,7 @@ c_powu(Py_complex x, long n) static Py_complex c_powi(Py_complex x, long n) { - Py_complex cn; - - if (n > 100 || n < -100) { - cn.real = (double) n; - cn.imag = 0.; - return _Py_c_pow(x,cn); - } - else if (n > 0) + if (n > 0) return c_powu(x,n); else return _Py_c_quot(c_1, c_powu(x,-n)); @@ -514,8 +507,6 @@ static PyObject * complex_pow(PyObject *v, PyObject *w, PyObject *z) { Py_complex p; - Py_complex exponent; - long int_exponent; Py_complex a, b; TO_COMPLEX(v, a); TO_COMPLEX(w, b); @@ -525,12 +516,14 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z) return NULL; } errno = 0; - exponent = b; - int_exponent = (long)exponent.real; - if (exponent.imag == 0. && exponent.real == int_exponent) - p = c_powi(a, int_exponent); - else - p = _Py_c_pow(a, exponent); + // Check whether the exponent has a small integer value, and if so use + // a faster and more accurate algorithm. + if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) { + p = c_powi(a, (long)b.real); + } + else { + p = _Py_c_pow(a, b); + } Py_ADJUST_ERANGE2(p.real, p.imag); if (errno == EDOM) { diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 57a9607d10c31a..97669bef368da8 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -72,13 +72,8 @@ wrapperdescr_repr(PyWrapperDescrObject *descr) } static int -descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres) +descr_check(PyDescrObject *descr, PyObject *obj) { - if (obj == NULL) { - Py_INCREF(descr); - *pres = (PyObject *)descr; - return 1; - } if (!PyObject_TypeCheck(obj, descr->d_type)) { PyErr_Format(PyExc_TypeError, "descriptor '%V' for '%.100s' objects " @@ -86,8 +81,7 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres) descr_name((PyDescrObject *)descr), "?", descr->d_type->tp_name, Py_TYPE(obj)->tp_name); - *pres = NULL; - return 1; + return -1; } return 0; } @@ -137,10 +131,12 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) static PyObject * method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) { - PyObject *res; - - if (descr_check((PyDescrObject *)descr, obj, &res)) - return res; + if (obj == NULL) { + return Py_NewRef(descr); + } + if (descr_check((PyDescrObject *)descr, obj) < 0) { + return NULL; + } if (descr->d_method->ml_flags & METH_METHOD) { if (PyType_Check(type)) { return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type); @@ -159,10 +155,12 @@ method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type) static PyObject * member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) { - PyObject *res; - - if (descr_check((PyDescrObject *)descr, obj, &res)) - return res; + if (obj == NULL) { + return Py_NewRef(descr); + } + if (descr_check((PyDescrObject *)descr, obj) < 0) { + return NULL; + } if (descr->d_member->flags & PY_AUDIT_READ) { if (PySys_Audit("object.__getattr__", "Os", @@ -177,10 +175,12 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) static PyObject * getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) { - PyObject *res; - - if (descr_check((PyDescrObject *)descr, obj, &res)) - return res; + if (obj == NULL) { + return Py_NewRef(descr); + } + if (descr_check((PyDescrObject *)descr, obj) < 0) { + return NULL; + } if (descr->d_getset->get != NULL) return descr->d_getset->get(obj, descr->d_getset->closure); PyErr_Format(PyExc_AttributeError, @@ -193,16 +193,17 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) static PyObject * wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type) { - PyObject *res; - - if (descr_check((PyDescrObject *)descr, obj, &res)) - return res; + if (obj == NULL) { + return Py_NewRef(descr); + } + if (descr_check((PyDescrObject *)descr, obj) < 0) { + return NULL; + } return PyWrapper_New((PyObject *)descr, obj); } static int -descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, - int *pres) +descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value) { assert(obj != NULL); if (!PyObject_TypeCheck(obj, descr->d_type)) { @@ -212,8 +213,7 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, descr_name(descr), "?", descr->d_type->tp_name, Py_TYPE(obj)->tp_name); - *pres = -1; - return 1; + return -1; } return 0; } @@ -221,23 +221,22 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value, static int member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) { - int res; - - if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) - return res; + if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { + return -1; + } return PyMember_SetOne((char *)obj, descr->d_member, value); } static int getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) { - int res; - - if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) - return res; - if (descr->d_getset->set != NULL) + if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) { + return -1; + } + if (descr->d_getset->set != NULL) { return descr->d_getset->set(obj, value, descr->d_getset->closure); + } PyErr_Format(PyExc_AttributeError, "attribute '%V' of '%.100s' objects is not writable", descr_name((PyDescrObject *)descr), "?", @@ -264,8 +263,7 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj return -1; } PyObject *self = args[0]; - PyObject *dummy; - if (descr_check((PyDescrObject *)func, self, &dummy)) { + if (descr_check((PyDescrObject *)func, self) < 0) { return -1; } if (kwnames && PyTuple_GET_SIZE(kwnames)) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 9e2c12229df802..24973c07b1d488 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -4826,7 +4826,7 @@ static PySequenceMethods dictitems_as_sequence = { (objobjproc)dictitems_contains, /* sq_contains */ }; -static PyObject* dictitems_reversed(_PyDictViewObject *dv); +static PyObject* dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reversed_items_doc, "Return a reverse iterator over the dict items."); @@ -4834,7 +4834,7 @@ PyDoc_STRVAR(reversed_items_doc, static PyMethodDef dictitems_methods[] = { {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, isdisjoint_doc}, - {"__reversed__", (PyCFunction)(void(*)(void))dictitems_reversed, METH_NOARGS, + {"__reversed__", (PyCFunction)dictitems_reversed, METH_NOARGS, reversed_items_doc}, {NULL, NULL} /* sentinel */ }; @@ -4879,7 +4879,7 @@ dictitems_new(PyObject *dict, PyObject *Py_UNUSED(ignored)) } static PyObject * -dictitems_reversed(_PyDictViewObject *dv) +dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; @@ -4909,13 +4909,13 @@ static PySequenceMethods dictvalues_as_sequence = { (objobjproc)0, /* sq_contains */ }; -static PyObject* dictvalues_reversed(_PyDictViewObject *dv); +static PyObject* dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)); PyDoc_STRVAR(reversed_values_doc, "Return a reverse iterator over the dict values."); static PyMethodDef dictvalues_methods[] = { - {"__reversed__", (PyCFunction)(void(*)(void))dictvalues_reversed, METH_NOARGS, + {"__reversed__", (PyCFunction)dictvalues_reversed, METH_NOARGS, reversed_values_doc}, {NULL, NULL} /* sentinel */ }; @@ -4960,7 +4960,7 @@ dictvalues_new(PyObject *dict, PyObject *Py_UNUSED(ignored)) } static PyObject * -dictvalues_reversed(_PyDictViewObject *dv) +dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored)) { if (dv->dv_dict == NULL) { Py_RETURN_NONE; diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 95e6f21ae82175..6537a7ccd1e3c6 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1475,9 +1475,6 @@ ComplexExtendsException(PyExc_Exception, AttributeError, * SyntaxError extends Exception */ -/* Helper function to customize error message for some syntax errors */ -static int _report_missing_parentheses(PySyntaxErrorObject *self); - static int SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) { @@ -1506,7 +1503,7 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) &self->end_lineno, &self->end_offset)) { Py_DECREF(info); return -1; - } + } Py_INCREF(self->filename); Py_INCREF(self->lineno); @@ -1520,18 +1517,6 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) PyErr_SetString(PyExc_TypeError, "end_offset must be provided when end_lineno is provided"); return -1; } - - /* - * Issue #21669: Custom error for 'print' & 'exec' as statements - * - * Only applies to SyntaxError instances, not to subclasses such - * as TabError or IndentationError (see issue #31161) - */ - if (Py_IS_TYPE(self, (PyTypeObject *)PyExc_SyntaxError) && - self->text && PyUnicode_Check(self->text) && - _report_missing_parentheses(self) < 0) { - return -1; - } } return 0; } @@ -3052,189 +3037,3 @@ _PyErr_TrySetFromCause(const char *format, ...) PyErr_Restore(new_exc, new_val, new_tb); return new_val; } - - -/* To help with migration from Python 2, SyntaxError.__init__ applies some - * heuristics to try to report a more meaningful exception when print and - * exec are used like statements. - * - * The heuristics are currently expected to detect the following cases: - * - top level statement - * - statement in a nested suite - * - trailing section of a one line complex statement - * - * They're currently known not to trigger: - * - after a semi-colon - * - * The error message can be a bit odd in cases where the "arguments" are - * completely illegal syntactically, but that isn't worth the hassle of - * fixing. - * - * We also can't do anything about cases that are legal Python 3 syntax - * but mean something entirely different from what they did in Python 2 - * (omitting the arguments entirely, printing items preceded by a unary plus - * or minus, using the stream redirection syntax). - */ - - -// Static helper for setting legacy print error message -static int -_set_legacy_print_statement_msg(PySyntaxErrorObject *self, Py_ssize_t start) -{ - // PRINT_OFFSET is to remove the `print ` prefix from the data. - const int PRINT_OFFSET = 6; - const int STRIP_BOTH = 2; - Py_ssize_t start_pos = start + PRINT_OFFSET; - Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text); - Py_UCS4 semicolon = ';'; - Py_ssize_t end_pos = PyUnicode_FindChar(self->text, semicolon, - start_pos, text_len, 1); - if (end_pos < -1) { - return -1; - } else if (end_pos == -1) { - end_pos = text_len; - } - - PyObject *data = PyUnicode_Substring(self->text, start_pos, end_pos); - if (data == NULL) { - return -1; - } - - PyObject *strip_sep_obj = PyUnicode_FromString(" \t\r\n"); - if (strip_sep_obj == NULL) { - Py_DECREF(data); - return -1; - } - - PyObject *new_data = _PyUnicode_XStrip(data, STRIP_BOTH, strip_sep_obj); - Py_DECREF(data); - Py_DECREF(strip_sep_obj); - if (new_data == NULL) { - return -1; - } - // gets the modified text_len after stripping `print ` - text_len = PyUnicode_GET_LENGTH(new_data); - const char *maybe_end_arg = ""; - if (text_len > 0 && PyUnicode_READ_CHAR(new_data, text_len-1) == ',') { - maybe_end_arg = " end=\" \""; - } - PyObject *error_msg = PyUnicode_FromFormat( - "Missing parentheses in call to 'print'. Did you mean print(%U%s)?", - new_data, maybe_end_arg - ); - Py_DECREF(new_data); - if (error_msg == NULL) - return -1; - - Py_XSETREF(self->msg, error_msg); - return 1; -} - -static int -_check_for_legacy_statements(PySyntaxErrorObject *self, Py_ssize_t start) -{ - /* Return values: - * -1: an error occurred - * 0: nothing happened - * 1: the check triggered & the error message was changed - */ - static PyObject *print_prefix = NULL; - static PyObject *exec_prefix = NULL; - Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text), match; - int kind = PyUnicode_KIND(self->text); - const void *data = PyUnicode_DATA(self->text); - - /* Ignore leading whitespace */ - while (start < text_len) { - Py_UCS4 ch = PyUnicode_READ(kind, data, start); - if (!Py_UNICODE_ISSPACE(ch)) - break; - start++; - } - /* Checking against an empty or whitespace-only part of the string */ - if (start == text_len) { - return 0; - } - - /* Check for legacy print statements */ - if (print_prefix == NULL) { - print_prefix = PyUnicode_InternFromString("print "); - if (print_prefix == NULL) { - return -1; - } - } - match = PyUnicode_Tailmatch(self->text, print_prefix, - start, text_len, -1); - if (match == -1) { - return -1; - } - if (match) { - return _set_legacy_print_statement_msg(self, start); - } - - /* Check for legacy exec statements */ - if (exec_prefix == NULL) { - exec_prefix = PyUnicode_InternFromString("exec "); - if (exec_prefix == NULL) { - return -1; - } - } - match = PyUnicode_Tailmatch(self->text, exec_prefix, start, text_len, -1); - if (match == -1) { - return -1; - } - if (match) { - PyObject *msg = PyUnicode_FromString("Missing parentheses in call " - "to 'exec'"); - if (msg == NULL) { - return -1; - } - Py_XSETREF(self->msg, msg); - return 1; - } - /* Fall back to the default error message */ - return 0; -} - -static int -_report_missing_parentheses(PySyntaxErrorObject *self) -{ - Py_UCS4 left_paren = 40; - Py_ssize_t left_paren_index; - Py_ssize_t text_len = PyUnicode_GET_LENGTH(self->text); - int legacy_check_result = 0; - - /* Skip entirely if there is an opening parenthesis */ - left_paren_index = PyUnicode_FindChar(self->text, left_paren, - 0, text_len, 1); - if (left_paren_index < -1) { - return -1; - } - if (left_paren_index != -1) { - /* Use default error message for any line with an opening paren */ - return 0; - } - /* Handle the simple statement case */ - legacy_check_result = _check_for_legacy_statements(self, 0); - if (legacy_check_result < 0) { - return -1; - - } - if (legacy_check_result == 0) { - /* Handle the one-line complex statement case */ - Py_UCS4 colon = 58; - Py_ssize_t colon_index; - colon_index = PyUnicode_FindChar(self->text, colon, - 0, text_len, 1); - if (colon_index < -1) { - return -1; - } - if (colon_index >= 0 && colon_index < text_len) { - /* Check again, starting from just after the colon */ - if (_check_for_legacy_statements(self, colon_index+1) < 0) { - return -1; - } - } - } - return 0; -} diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 7e78132c01ca27..e4ce7e74d2c57f 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1463,8 +1463,8 @@ float_fromhex(PyTypeObject *type, PyObject *string) bits lsb, lsb-2, lsb-3, lsb-4, ... is 1. */ if ((digit & half_eps) != 0) { round_up = 0; - if ((digit & (3*half_eps-1)) != 0 || - (half_eps == 8 && (HEX_DIGIT(key_digit+1) & 1) != 0)) + if ((digit & (3*half_eps-1)) != 0 || (half_eps == 8 && + key_digit+1 < ndigits && (HEX_DIGIT(key_digit+1) & 1) != 0)) round_up = 1; else for (i = key_digit-1; i >= 0; i--) @@ -2350,7 +2350,7 @@ _PyFloat_Pack8(double x, unsigned char *p, int le) flo = 0; ++fhi; if (fhi >> 28) { - /* And it also progagated out of the next 28 bits. */ + /* And it also propagated out of the next 28 bits. */ fhi = 0; ++e; if (e >= 2047) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 034b908ade31cc..d02cf9d3ba9f06 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -46,7 +46,7 @@ PyFrame_GetLineNumber(PyFrameObject *f) return f->f_lineno; } else { - return PyCode_Addr2Line(f->f_code, f->f_lasti*2); + return PyCode_Addr2Line(f->f_code, f->f_lasti*sizeof(_Py_CODEUNIT)); } } @@ -68,7 +68,7 @@ frame_getlasti(PyFrameObject *f, void *closure) if (f->f_lasti < 0) { return PyLong_FromLong(-1); } - return PyLong_FromLong(f->f_lasti*2); + return PyLong_FromLong(f->f_lasti*sizeof(_Py_CODEUNIT)); } @@ -275,8 +275,8 @@ marklines(PyCodeObject *code, int len) } while (PyLineTable_NextAddressRange(&bounds)) { - assert(bounds.ar_start/2 < len); - linestarts[bounds.ar_start/2] = bounds.ar_line; + assert(bounds.ar_start/(int)sizeof(_Py_CODEUNIT) < len); + linestarts[bounds.ar_start/sizeof(_Py_CODEUNIT)] = bounds.ar_line; } return linestarts; } @@ -581,7 +581,7 @@ frame_dealloc(PyFrameObject *f) _PyObject_GC_UNTRACK(f); } - Py_TRASHCAN_SAFE_BEGIN(f) + Py_TRASHCAN_BEGIN(f, frame_dealloc); /* Kill all local variables */ PyObject **valuestack = f->f_valuestack; for (PyObject **p = f->f_localsplus; p < valuestack; p++) { @@ -621,7 +621,7 @@ frame_dealloc(PyFrameObject *f) } Py_DECREF(co); - Py_TRASHCAN_SAFE_END(f) + Py_TRASHCAN_END; } static inline Py_ssize_t diff --git a/Objects/funcobject.c b/Objects/funcobject.c index f0b0b673d4fa40..801478ade22f6b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -221,6 +221,37 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) return 0; } +static PyObject * +func_get_annotation_dict(PyFunctionObject *op) +{ + if (op->func_annotations == NULL) { + return NULL; + } + if (PyTuple_CheckExact(op->func_annotations)) { + PyObject *ann_tuple = op->func_annotations; + PyObject *ann_dict = PyDict_New(); + if (ann_dict == NULL) { + return NULL; + } + + assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0); + + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) { + int err = PyDict_SetItem(ann_dict, + PyTuple_GET_ITEM(ann_tuple, i), + PyTuple_GET_ITEM(ann_tuple, i + 1)); + + if (err < 0) { + return NULL; + } + } + Py_SETREF(op->func_annotations, ann_dict); + } + Py_INCREF(op->func_annotations); + assert(PyDict_Check(op->func_annotations)); + return op->func_annotations; +} + PyObject * PyFunction_GetAnnotations(PyObject *op) { @@ -228,7 +259,7 @@ PyFunction_GetAnnotations(PyObject *op) PyErr_BadInternalCall(); return NULL; } - return ((PyFunctionObject *) op) -> func_annotations; + return func_get_annotation_dict((PyFunctionObject *)op); } int @@ -443,27 +474,7 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored)) if (op->func_annotations == NULL) return NULL; } - if (PyTuple_CheckExact(op->func_annotations)) { - PyObject *ann_tuple = op->func_annotations; - PyObject *ann_dict = PyDict_New(); - if (ann_dict == NULL) { - return NULL; - } - - assert(PyTuple_GET_SIZE(ann_tuple) % 2 == 0); - - for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(ann_tuple); i += 2) { - int err = PyDict_SetItem(ann_dict, - PyTuple_GET_ITEM(ann_tuple, i), - PyTuple_GET_ITEM(ann_tuple, i + 1)); - - if (err < 0) - return NULL; - } - Py_SETREF(op->func_annotations, ann_dict); - } - Py_INCREF(op->func_annotations); - return op->func_annotations; + return func_get_annotation_dict(op); } static int @@ -825,7 +836,7 @@ cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) type = (PyObject *)(Py_TYPE(obj)); if (Py_TYPE(cm->cm_callable)->tp_descr_get != NULL) { return Py_TYPE(cm->cm_callable)->tp_descr_get(cm->cm_callable, type, - NULL); + type); } return PyMethod_New(cm->cm_callable, type); } diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 756a7ce474aee9..dbe5d89b739629 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -2,7 +2,7 @@ #include "Python.h" #include "pycore_object.h" -#include "pycore_unionobject.h" // _Py_union_as_number +#include "pycore_unionobject.h" // _Py_union_type_or, _PyGenericAlias_Check #include "structmember.h" // PyMemberDef typedef struct { @@ -198,8 +198,8 @@ tuple_add(PyObject *self, Py_ssize_t len, PyObject *item) return 0; } -static PyObject * -make_parameters(PyObject *args) +PyObject * +_Py_make_parameters(PyObject *args) { Py_ssize_t nargs = PyTuple_GET_SIZE(args); Py_ssize_t len = nargs; @@ -294,18 +294,10 @@ subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems) return obj; } -static PyObject * -ga_getitem(PyObject *self, PyObject *item) +PyObject * +_Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item) { - gaobject *alias = (gaobject *)self; - // do a lookup for __parameters__ so it gets populated (if not already) - if (alias->parameters == NULL) { - alias->parameters = make_parameters(alias->args); - if (alias->parameters == NULL) { - return NULL; - } - } - Py_ssize_t nparams = PyTuple_GET_SIZE(alias->parameters); + Py_ssize_t nparams = PyTuple_GET_SIZE(parameters); if (nparams == 0) { return PyErr_Format(PyExc_TypeError, "There are no type variables left in %R", @@ -320,32 +312,32 @@ ga_getitem(PyObject *self, PyObject *item) nitems > nparams ? "many" : "few", self); } - /* Replace all type variables (specified by alias->parameters) + /* Replace all type variables (specified by parameters) with corresponding values specified by argitems. t = list[T]; t[int] -> newargs = [int] t = dict[str, T]; t[int] -> newargs = [str, int] t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]] */ - Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args); + Py_ssize_t nargs = PyTuple_GET_SIZE(args); PyObject *newargs = PyTuple_New(nargs); if (newargs == NULL) { return NULL; } for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { - PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg); + PyObject *arg = PyTuple_GET_ITEM(args, iarg); int typevar = is_typevar(arg); if (typevar < 0) { Py_DECREF(newargs); return NULL; } if (typevar) { - Py_ssize_t iparam = tuple_index(alias->parameters, nparams, arg); + Py_ssize_t iparam = tuple_index(parameters, nparams, arg); assert(iparam >= 0); arg = argitems[iparam]; Py_INCREF(arg); } else { - arg = subs_tvars(arg, alias->parameters, argitems); + arg = subs_tvars(arg, parameters, argitems); if (arg == NULL) { Py_DECREF(newargs); return NULL; @@ -354,6 +346,26 @@ ga_getitem(PyObject *self, PyObject *item) PyTuple_SET_ITEM(newargs, iarg, arg); } + return newargs; +} + +static PyObject * +ga_getitem(PyObject *self, PyObject *item) +{ + gaobject *alias = (gaobject *)self; + // Populate __parameters__ if needed. + if (alias->parameters == NULL) { + alias->parameters = _Py_make_parameters(alias->args); + if (alias->parameters == NULL) { + return NULL; + } + } + + PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item); + if (newargs == NULL) { + return NULL; + } + PyObject *res = Py_GenericAlias(alias->origin, newargs); Py_DECREF(newargs); @@ -406,6 +418,8 @@ static const char* const attr_exceptions[] = { "__mro_entries__", "__reduce_ex__", // needed so we don't look up object.__reduce_ex__ "__reduce__", + "__copy__", + "__deepcopy__", NULL, }; @@ -429,8 +443,7 @@ ga_getattro(PyObject *self, PyObject *name) static PyObject * ga_richcompare(PyObject *a, PyObject *b, int op) { - if (!PyObject_TypeCheck(a, &Py_GenericAliasType) || - !PyObject_TypeCheck(b, &Py_GenericAliasType) || + if (!_PyGenericAlias_Check(b) || (op != Py_EQ && op != Py_NE)) { Py_RETURN_NOTIMPLEMENTED; @@ -550,7 +563,7 @@ ga_parameters(PyObject *self, void *unused) { gaobject *alias = (gaobject *)self; if (alias->parameters == NULL) { - alias->parameters = make_parameters(alias->args); + alias->parameters = _Py_make_parameters(alias->args); if (alias->parameters == NULL) { return NULL; } @@ -565,7 +578,7 @@ static PyGetSetDef ga_properties[] = { }; /* A helper function to create GenericAlias' args tuple and set its attributes. - * Returns 1 on success, 0 on failure. + * Returns 1 on success, 0 on failure. */ static inline int setup_ga(gaobject *alias, PyObject *origin, PyObject *args) { @@ -603,14 +616,14 @@ ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } if (!setup_ga(self, origin, arguments)) { - type->tp_free((PyObject *)self); + Py_DECREF(self); return NULL; } return (PyObject *)self; } static PyNumberMethods ga_as_number = { - .nb_or = (binaryfunc)_Py_union_type_or, // Add __or__ function + .nb_or = _Py_union_type_or, // Add __or__ function }; // TODO: @@ -646,14 +659,14 @@ PyTypeObject Py_GenericAliasType = { PyObject * Py_GenericAlias(PyObject *origin, PyObject *args) { - gaobject *alias = PyObject_GC_New(gaobject, &Py_GenericAliasType); + gaobject *alias = (gaobject*) PyType_GenericAlloc( + (PyTypeObject *)&Py_GenericAliasType, 0); if (alias == NULL) { return NULL; } if (!setup_ga(alias, origin, args)) { - PyObject_GC_Del((PyObject *)alias); + Py_DECREF(alias); return NULL; } - _PyObject_GC_TRACK(alias); return (PyObject *)alias; } diff --git a/Objects/genobject.c b/Objects/genobject.c index 1889df1d137786..33fc4a592492a8 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -145,6 +145,19 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyObject *result; *presult = NULL; + if (f != NULL && f->f_lasti < 0 && arg && arg != Py_None) { + const char *msg = "can't send non-None value to a " + "just-started generator"; + if (PyCoro_CheckExact(gen)) { + msg = NON_INIT_CORO_MSG; + } + else if (PyAsyncGen_CheckExact(gen)) { + msg = "can't send non-None value to a " + "just-started async generator"; + } + PyErr_SetString(PyExc_TypeError, msg); + return PYGEN_ERROR; + } if (f != NULL && _PyFrame_IsExecuting(f)) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { @@ -782,8 +795,7 @@ PyTypeObject PyGen_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gen_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -1030,8 +1042,7 @@ PyTypeObject PyCoro_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)gen_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -1415,8 +1426,7 @@ PyTypeObject PyAsyncGen_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_AM_SEND, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)async_gen_traverse, /* tp_traverse */ 0, /* tp_clear */ diff --git a/Objects/iterobject.c b/Objects/iterobject.c index 6961fc3b4a9497..e493e41131b70c 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -313,6 +313,36 @@ anextawaitable_traverse(anextawaitableobject *obj, visitproc visit, void *arg) return 0; } +static PyObject * +anextawaitable_getiter(anextawaitableobject *obj) +{ + assert(obj->wrapped != NULL); + PyObject *awaitable = _PyCoro_GetAwaitableIter(obj->wrapped); + if (awaitable == NULL) { + return NULL; + } + if (Py_TYPE(awaitable)->tp_iternext == NULL) { + /* _PyCoro_GetAwaitableIter returns a Coroutine, a Generator, + * or an iterator. Of these, only coroutines lack tp_iternext. + */ + assert(PyCoro_CheckExact(awaitable)); + unaryfunc getter = Py_TYPE(awaitable)->tp_as_async->am_await; + PyObject *new_awaitable = getter(awaitable); + if (new_awaitable == NULL) { + Py_DECREF(awaitable); + return NULL; + } + Py_SETREF(awaitable, new_awaitable); + if (!PyIter_Check(awaitable)) { + PyErr_SetString(PyExc_TypeError, + "__await__ returned a non-iterable"); + Py_DECREF(awaitable); + return NULL; + } + } + return awaitable; +} + static PyObject * anextawaitable_iternext(anextawaitableobject *obj) { @@ -336,30 +366,10 @@ anextawaitable_iternext(anextawaitableobject *obj) * Then `await anext(gen)` can just call * gen.__anext__().__next__() */ - assert(obj->wrapped != NULL); - PyObject *awaitable = _PyCoro_GetAwaitableIter(obj->wrapped); + PyObject *awaitable = anextawaitable_getiter(obj); if (awaitable == NULL) { return NULL; } - if (Py_TYPE(awaitable)->tp_iternext == NULL) { - /* _PyCoro_GetAwaitableIter returns a Coroutine, a Generator, - * or an iterator. Of these, only coroutines lack tp_iternext. - */ - assert(PyCoro_CheckExact(awaitable)); - unaryfunc getter = Py_TYPE(awaitable)->tp_as_async->am_await; - PyObject *new_awaitable = getter(awaitable); - if (new_awaitable == NULL) { - Py_DECREF(awaitable); - return NULL; - } - Py_SETREF(awaitable, new_awaitable); - if (Py_TYPE(awaitable)->tp_iternext == NULL) { - PyErr_SetString(PyExc_TypeError, - "__await__ returned a non-iterable"); - Py_DECREF(awaitable); - return NULL; - } - } PyObject *result = (*Py_TYPE(awaitable)->tp_iternext)(awaitable); Py_DECREF(awaitable); if (result != NULL) { @@ -371,6 +381,70 @@ anextawaitable_iternext(anextawaitableobject *obj) return NULL; } + +static PyObject * +anextawaitable_proxy(anextawaitableobject *obj, char *meth, PyObject *arg) { + PyObject *awaitable = anextawaitable_getiter(obj); + if (awaitable == NULL) { + return NULL; + } + PyObject *ret = PyObject_CallMethod(awaitable, meth, "O", arg); + Py_DECREF(awaitable); + if (ret != NULL) { + return ret; + } + if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) { + /* `anextawaitableobject` is only used by `anext()` when + * a default value is provided. So when we have a StopAsyncIteration + * exception we replace it with a `StopIteration(default)`, as if + * it was the return value of `__anext__()` coroutine. + */ + _PyGen_SetStopIterationValue(obj->default_value); + } + return NULL; +} + + +static PyObject * +anextawaitable_send(anextawaitableobject *obj, PyObject *arg) { + return anextawaitable_proxy(obj, "send", arg); +} + + +static PyObject * +anextawaitable_throw(anextawaitableobject *obj, PyObject *arg) { + return anextawaitable_proxy(obj, "throw", arg); +} + + +static PyObject * +anextawaitable_close(anextawaitableobject *obj, PyObject *arg) { + return anextawaitable_proxy(obj, "close", arg); +} + + +PyDoc_STRVAR(send_doc, +"send(arg) -> send 'arg' into the wrapped iterator,\n\ +return next yielded value or raise StopIteration."); + + +PyDoc_STRVAR(throw_doc, +"throw(typ[,val[,tb]]) -> raise exception in the wrapped iterator,\n\ +return next yielded value or raise StopIteration."); + + +PyDoc_STRVAR(close_doc, +"close() -> raise GeneratorExit inside generator."); + + +static PyMethodDef anextawaitable_methods[] = { + {"send",(PyCFunction)anextawaitable_send, METH_O, send_doc}, + {"throw",(PyCFunction)anextawaitable_throw, METH_VARARGS, throw_doc}, + {"close",(PyCFunction)anextawaitable_close, METH_VARARGS, close_doc}, + {NULL, NULL} /* Sentinel */ +}; + + static PyAsyncMethods anextawaitable_as_async = { PyObject_SelfIter, /* am_await */ 0, /* am_aiter */ @@ -407,7 +481,7 @@ PyTypeObject _PyAnextAwaitable_Type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (unaryfunc)anextawaitable_iternext, /* tp_iternext */ - 0, /* tp_methods */ + anextawaitable_methods, /* tp_methods */ }; PyObject * diff --git a/Objects/listobject.c b/Objects/listobject.c index 6eb7dce759cf86..533ee7436d3113 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -180,9 +180,10 @@ PyList_New(Py_ssize_t size) static PyObject * list_new_prealloc(Py_ssize_t size) { + assert(size > 0); PyListObject *op = (PyListObject *) PyList_New(0); - if (size == 0 || op == NULL) { - return (PyObject *) op; + if (op == NULL) { + return NULL; } assert(op->ob_item == NULL); op->ob_item = PyMem_New(PyObject *, size); @@ -459,6 +460,9 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) PyObject **src, **dest; Py_ssize_t i, len; len = ihigh - ilow; + if (len <= 0) { + return PyList_New(0); + } np = (PyListObject *) list_new_prealloc(len); if (np == NULL) return NULL; @@ -512,6 +516,9 @@ list_concat(PyListObject *a, PyObject *bb) #define b ((PyListObject *)bb) assert((size_t)Py_SIZE(a) + (size_t)Py_SIZE(b) < PY_SSIZE_T_MAX); size = Py_SIZE(a) + Py_SIZE(b); + if (size == 0) { + return PyList_New(0); + } np = (PyListObject *) list_new_prealloc(size); if (np == NULL) { return NULL; @@ -2017,7 +2024,7 @@ safe_object_compare(PyObject *v, PyObject *w, MergeState *ms) return PyObject_RichCompareBool(v, w, Py_LT); } -/* Homogeneous compare: safe for any two compareable objects of the same type. +/* Homogeneous compare: safe for any two comparable objects of the same type. * (ms->key_richcompare is set to ob_type->tp_richcompare in the * pre-sort check.) */ diff --git a/Objects/listsort.txt b/Objects/listsort.txt index 174777a2658dc6..42809d71bc44a4 100644 --- a/Objects/listsort.txt +++ b/Objects/listsort.txt @@ -758,6 +758,6 @@ OPTIMIZATION OF INDIVIDUAL COMPARISONS As noted above, even the simplest Python comparison triggers a large pile of C-level pointer dereferences, conditionals, and function calls. This can be partially mitigated by pre-scanning the data to determine whether the data is -homogenous with respect to type. If so, it is sometimes possible to +homogeneous with respect to type. If so, it is sometimes possible to substitute faster type-specific comparisons for the slower, generic PyObject_RichCompareBool. diff --git a/Objects/longobject.c b/Objects/longobject.c index e1c1191e648dae..685bd56096f486 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4185,6 +4185,7 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) goto Error; Py_DECREF(a); a = temp; + temp = NULL; } /* Reduce base by modulus in some cases: diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 7b430416c5a048..2df63cfdf6a818 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -160,7 +160,10 @@ PyCMethod_GetClass(PyObject *op) static void meth_dealloc(PyCFunctionObject *m) { - _PyObject_GC_UNTRACK(m); + // The Py_TRASHCAN mechanism requires that we be able to + // call PyObject_GC_UnTrack twice on an object. + PyObject_GC_UnTrack(m); + Py_TRASHCAN_BEGIN(m, meth_dealloc); if (m->m_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*) m); } @@ -170,6 +173,7 @@ meth_dealloc(PyCFunctionObject *m) Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); PyObject_GC_Del(m); + Py_TRASHCAN_END; } static PyObject * diff --git a/Objects/object.c b/Objects/object.c index 854cc85b1cfa46..ff816cd5b9a605 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -11,7 +11,7 @@ #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntry_Type -#include "pycore_unionobject.h" // _Py_UnionType +#include "pycore_unionobject.h" // _PyUnion_Type #include "frameobject.h" #include "interpreteridobject.h" @@ -1880,7 +1880,7 @@ _PyTypes_Init(void) INIT_TYPE(_PyWeakref_CallableProxyType); INIT_TYPE(_PyWeakref_ProxyType); INIT_TYPE(_PyWeakref_RefType); - INIT_TYPE(_Py_UnionType); + INIT_TYPE(_PyUnion_Type); return _PyStatus_OK(); #undef INIT_TYPE diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index c1c12797aba111..615703a963ede6 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -836,7 +836,7 @@ static int running_on_valgrind = -1; /* * Alignment of addresses returned to the user. 8-bytes alignment works - * on most current architectures (with 32-bit or 64-bit address busses). + * on most current architectures (with 32-bit or 64-bit address buses). * The alignment value is also used for grouping small requests in size * classes spaced ALIGNMENT bytes apart. * @@ -1328,7 +1328,7 @@ _Py_GetAllocatedBlocks(void) #define MAP_TOP_BITS INTERIOR_BITS #define MAP_TOP_LENGTH (1 << MAP_TOP_BITS) -#define MAP_TOP_MASK (MAP_BOT_LENGTH - 1) +#define MAP_TOP_MASK (MAP_TOP_LENGTH - 1) #define MAP_MID_BITS INTERIOR_BITS #define MAP_MID_LENGTH (1 << MAP_MID_BITS) @@ -3035,7 +3035,7 @@ _PyObject_DebugMallocStats(FILE *out) fputc('\n', out); - /* Account for what all of those arena bytes are being used for. */ + /* Account for what all of those arena bytes are being used for. */ total = printone(out, "# bytes in allocated blocks", allocated_bytes); total += printone(out, "# bytes in available blocks", available_bytes); diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 6c7f1175cd652c..c0ccb16bc3d2eb 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1288,6 +1288,7 @@ PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)"); #define _odict_ITER_REVERSED 1 #define _odict_ITER_KEYS 2 #define _odict_ITER_VALUES 4 +#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES) /* forward */ static PyObject * odictiter_new(PyODictObject *, int); @@ -1705,7 +1706,7 @@ odictiter_dealloc(odictiterobject *di) _PyObject_GC_UNTRACK(di); Py_XDECREF(di->di_odict); Py_XDECREF(di->di_current); - if (di->kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)) { + if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { Py_DECREF(di->di_result); } PyObject_GC_Del(di); @@ -1911,15 +1912,16 @@ odictiter_new(PyODictObject *od, int kind) if (di == NULL) return NULL; - if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES)){ + if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) { di->di_result = PyTuple_Pack(2, Py_None, Py_None); if (di->di_result == NULL) { Py_DECREF(di); return NULL; } } - else + else { di->di_result = NULL; + } di->kind = kind; node = reversed ? _odict_LAST(od) : _odict_FIRST(od); diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 3e05707b1cee69..a848d67a65152e 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -813,7 +813,7 @@ rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) if (range == NULL) goto err; /* return the result */ - return Py_BuildValue("N(N)i", _PyEval_GetBuiltinId(&PyId_iter), + return Py_BuildValue("N(N)l", _PyEval_GetBuiltinId(&PyId_iter), range, r->index); err: Py_XDECREF(start); @@ -915,22 +915,14 @@ get_len_of_range(long lo, long hi, long step) is not representable as a C long, OverflowError is raised. */ static PyObject * -fast_range_iter(long start, long stop, long step) +fast_range_iter(long start, long stop, long step, long len) { rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); - unsigned long ulen; if (it == NULL) return NULL; it->start = start; it->step = step; - ulen = get_len_of_range(start, stop, step); - if (ulen > (unsigned long)LONG_MAX) { - Py_DECREF(it); - PyErr_SetString(PyExc_OverflowError, - "range too large to represent as a range_iterator"); - return NULL; - } - it->len = (long)ulen; + it->len = len; it->index = 0; return (PyObject *)it; } @@ -1092,7 +1084,7 @@ range_iter(PyObject *seq) rangeobject *r = (rangeobject *)seq; longrangeiterobject *it; long lstart, lstop, lstep; - PyObject *int_it; + unsigned long ulen; assert(PyRange_Check(seq)); @@ -1113,12 +1105,22 @@ range_iter(PyObject *seq) PyErr_Clear(); goto long_range; } - int_it = fast_range_iter(lstart, lstop, lstep); - if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { - PyErr_Clear(); + ulen = get_len_of_range(lstart, lstop, lstep); + if (ulen > (unsigned long)LONG_MAX) { goto long_range; } - return (PyObject *)int_it; + /* check for potential overflow of lstart + ulen * lstep */ + if (ulen) { + if (lstep > 0) { + if (lstop > LONG_MAX - (lstep - 1)) + goto long_range; + } + else { + if (lstop < LONG_MIN + (-1 - lstep)) + goto long_range; + } + } + return fast_range_iter(lstart, lstop, lstep, (long)ulen); long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); @@ -1204,7 +1206,7 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); - return fast_range_iter(new_start, new_stop, -lstep); + return fast_range_iter(new_start, new_stop, -lstep, (long)ulen); long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); diff --git a/Objects/setobject.c b/Objects/setobject.c index caff85c9e38939..6524963b8abc37 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -16,7 +16,7 @@ reduces the cost of hash collisions because consecutive memory accesses tend to be much cheaper than scattered probes. After LINEAR_PROBES steps, we then use more of the upper bits from the hash value and apply a simple - linear congruential random number genearator. This helps break-up long + linear congruential random number generator. This helps break-up long chains of collisions. All arithmetic on hash should ignore overflow. @@ -1407,7 +1407,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other) /* Optimization: When the other set is more than 8 times larger than the base set, replace the other set with - interesection of the two sets. + intersection of the two sets. */ if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) { other = set_intersection(so, other); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e511cf9ebfc7e8..b23e36a420fa0c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -8,7 +8,7 @@ #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_unionobject.h" // _Py_Union(), _Py_union_type_or +#include "pycore_unionobject.h" // _Py_union_type_or #include "frameobject.h" #include "structmember.h" // PyMemberDef @@ -50,6 +50,11 @@ typedef struct PySlot_Offset { } PySlot_Offset; +/* bpo-40521: Interned strings are shared by all subinterpreters */ +#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS +# define INTERN_NAME_STRINGS +#endif + /* alphabetical order */ _Py_IDENTIFIER(__abstractmethods__); _Py_IDENTIFIER(__annotations__); @@ -316,10 +321,6 @@ PyType_Modified(PyTypeObject *type) Invariants: - - Py_TPFLAGS_VALID_VERSION_TAG is never set if - Py_TPFLAGS_HAVE_VERSION_TAG is not set (in case of a - bizarre MRO, see type_mro_modified()). - - before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type, it must first be set on all super types. @@ -371,9 +372,6 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { PyObject *mro_meth = NULL; PyObject *type_mro_meth = NULL; - if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG)) - return; - if (custom) { mro_meth = lookup_maybe_method( (PyObject *)type, &PyId_mro, &unbound); @@ -396,8 +394,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { assert(PyType_Check(b)); cls = (PyTypeObject *)b; - if (!_PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) || - !PyType_IsSubtype(type, cls)) { + if (!PyType_IsSubtype(type, cls)) { goto clear; } } @@ -405,8 +402,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { clear: Py_XDECREF(mro_meth); Py_XDECREF(type_mro_meth); - type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG| - Py_TPFLAGS_VALID_VERSION_TAG); + type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; type->tp_version_tag = 0; /* 0 is not a valid version tag */ } @@ -423,8 +419,6 @@ assign_version_tag(struct type_cache *cache, PyTypeObject *type) if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) return 1; - if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG)) - return 0; if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) return 0; @@ -1344,14 +1338,22 @@ subtype_dealloc(PyObject *self) /* Extract the type again; tp_del may have changed it */ type = Py_TYPE(self); + // Don't read type memory after calling basedealloc() since basedealloc() + // can deallocate the type and free its memory. + int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + /* Call the base tp_dealloc() */ assert(basedealloc); basedealloc(self); - /* Only decref if the base type is not already a heap allocated type. - Otherwise, basedealloc should have decref'd it already */ - if (type->tp_flags & Py_TPFLAGS_HEAPTYPE && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)) + /* Can't reference self beyond this point. It's possible tp_del switched + our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about + reference counting. Only decref if the base type is not already a heap + allocated type. Otherwise, basedealloc should have decref'd it already */ + if (type_needs_decref) { Py_DECREF(type); + } /* Done */ return; @@ -1446,6 +1448,12 @@ subtype_dealloc(PyObject *self) if (_PyType_IS_GC(base)) { _PyObject_GC_TRACK(self); } + + // Don't read type memory after calling basedealloc() since basedealloc() + // can deallocate the type and free its memory. + int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE + && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); + assert(basedealloc); basedealloc(self); @@ -1453,8 +1461,9 @@ subtype_dealloc(PyObject *self) our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about reference counting. Only decref if the base type is not already a heap allocated type. Otherwise, basedealloc should have decref'd it already */ - if (type->tp_flags & Py_TPFLAGS_HEAPTYPE && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)) - Py_DECREF(type); + if (type_needs_decref) { + Py_DECREF(type); + } endlabel: Py_TRASHCAN_END @@ -3249,6 +3258,9 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) if (winner->tp_new != type_new) { /* Pass it to the winner */ *type = winner->tp_new(winner, ctx->args, ctx->kwds); + if (*type == NULL) { + return -1; + } return 1; } @@ -3300,6 +3312,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) PyObject *type = NULL; int res = type_new_get_bases(&ctx, &type); if (res < 0) { + assert(PyErr_Occurred()); return NULL; } if (res == 1) { @@ -3609,6 +3622,14 @@ PyType_FromSpec(PyType_Spec *spec) return PyType_FromSpecWithBases(spec, NULL); } +/* private in 3.10 and 3.9.8+; public in 3.11 */ +PyObject * +_PyType_GetQualName(PyTypeObject *type) +{ + return type_qualname(type, NULL); +} + + void * PyType_GetSlot(PyTypeObject *type, int slot) { @@ -3972,6 +3993,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) if (name == NULL) return -1; } +#ifdef INTERN_NAME_STRINGS if (!PyUnicode_CHECK_INTERNED(name)) { PyUnicode_InternInPlace(&name); if (!PyUnicode_CHECK_INTERNED(name)) { @@ -3981,6 +4003,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) return -1; } } +#endif } else { /* Will fail in _PyObject_GenericSetAttrWithDict. */ @@ -4205,10 +4228,8 @@ static PyMethodDef type_methods[] = { }; PyDoc_STRVAR(type_doc, -/* this text signature cannot be accurate yet. will fix. --larry */ -"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" -"type(name, bases, dict) -> a new type"); +"type(name, bases, dict, **kwds) -> a new type"); static int type_traverse(PyTypeObject *type, visitproc visit, void *arg) @@ -5949,14 +5970,6 @@ type_ready_checks(PyTypeObject *type) _PyObject_ASSERT((PyObject *)type, type->tp_call != NULL); } - /* Consistency check for Py_TPFLAGS_HAVE_AM_SEND - flag requires - * type->tp_as_async->am_send to be present. - */ - if (type->tp_flags & Py_TPFLAGS_HAVE_AM_SEND) { - _PyObject_ASSERT((PyObject *)type, type->tp_as_async != NULL); - _PyObject_ASSERT((PyObject *)type, type->tp_as_async->am_send != NULL); - } - /* Consistency checks for pattern matching * Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING are mutually exclusive */ _PyObject_ASSERT((PyObject *)type, (type->tp_flags & COLLECTION_FLAGS) != COLLECTION_FLAGS); @@ -8338,10 +8351,17 @@ _PyTypes_InitSlotDefs(void) for (slotdef *p = slotdefs; p->name; p++) { /* Slots must be ordered by their offset in the PyHeapTypeObject. */ assert(!p[1].name || p->offset <= p[1].offset); +#ifdef INTERN_NAME_STRINGS p->name_strobj = PyUnicode_InternFromString(p->name); if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) { return _PyStatus_NO_MEMORY(); } +#else + p->name_strobj = PyUnicode_FromString(p->name); + if (!p->name_strobj) { + return _PyStatus_NO_MEMORY(); + } +#endif } slotdefs_initialized = 1; return _PyStatus_OK(); @@ -8366,16 +8386,24 @@ update_slot(PyTypeObject *type, PyObject *name) int offset; assert(PyUnicode_CheckExact(name)); +#ifdef INTERN_NAME_STRINGS assert(PyUnicode_CHECK_INTERNED(name)); +#endif assert(slotdefs_initialized); pp = ptrs; for (p = slotdefs; p->name; p++) { assert(PyUnicode_CheckExact(p->name_strobj)); assert(PyUnicode_CheckExact(name)); +#ifdef INTERN_NAME_STRINGS if (p->name_strobj == name) { *pp++ = p; } +#else + if (p->name_strobj == name || _PyUnicode_EQ(p->name_strobj, name)) { + *pp++ = p; + } +#endif } *pp = NULL; for (pp = ptrs; *pp; pp++) { @@ -8420,7 +8448,8 @@ update_all_slots(PyTypeObject* type) } -/* Call __set_name__ on all descriptors in a newly generated type */ +/* Call __set_name__ on all attributes (including descriptors) + in a newly generated type */ static int type_new_set_names(PyTypeObject *type) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index bfd5c881215dee..077cf8d7f45605 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -211,6 +211,22 @@ extern "C" { # define OVERALLOCATE_FACTOR 4 #endif +/* bpo-40521: Interned strings are shared by all interpreters. */ +#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS +# define INTERNED_STRINGS +#endif + +/* This dictionary holds all interned unicode strings. Note that references + to strings in this dictionary are *not* counted in the string's ob_refcnt. + When the interned string reaches a refcnt of 0 the string deallocation + function will delete the reference from this dictionary. + + Another way to look at this is that to say that the actual reference + count of a string is: s->ob_refcnt + (s->state ? 2 : 0) +*/ +#ifdef INTERNED_STRINGS +static PyObject *interned = NULL; +#endif static struct _Py_unicode_state* get_unicode_state(void) @@ -658,7 +674,7 @@ unicode_result_ready(PyObject *unicode) if (length == 1) { int kind = PyUnicode_KIND(unicode); if (kind == PyUnicode_1BYTE_KIND) { - Py_UCS1 *data = PyUnicode_1BYTE_DATA(unicode); + const Py_UCS1 *data = PyUnicode_1BYTE_DATA(unicode); Py_UCS1 ch = data[0]; struct _Py_unicode_state *state = get_unicode_state(); PyObject *latin1_char = state->latin1[ch]; @@ -1936,7 +1952,7 @@ unicode_dealloc(PyObject *unicode) case SSTATE_INTERNED_MORTAL: { - struct _Py_unicode_state *state = get_unicode_state(); +#ifdef INTERNED_STRINGS /* Revive the dead object temporarily. PyDict_DelItem() removes two references (key and value) which were ignored by PyUnicode_InternInPlace(). Use refcnt=3 rather than refcnt=2 @@ -1944,12 +1960,13 @@ unicode_dealloc(PyObject *unicode) PyDict_DelItem(). */ assert(Py_REFCNT(unicode) == 0); Py_SET_REFCNT(unicode, 3); - if (PyDict_DelItem(state->interned, unicode) != 0) { + if (PyDict_DelItem(interned, unicode) != 0) { _PyErr_WriteUnraisableMsg("deletion of interned string failed", NULL); } assert(Py_REFCNT(unicode) == 1); Py_SET_REFCNT(unicode, 0); +#endif break; } @@ -6408,9 +6425,10 @@ PyUnicode_AsUTF16String(PyObject *unicode) static _PyUnicode_Name_CAPI *ucnhash_capi = NULL; PyObject * -_PyUnicode_DecodeUnicodeEscape(const char *s, +_PyUnicode_DecodeUnicodeEscapeInternal(const char *s, Py_ssize_t size, const char *errors, + Py_ssize_t *consumed, const char **first_invalid_escape) { const char *starts = s; @@ -6423,6 +6441,9 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, *first_invalid_escape = NULL; if (size == 0) { + if (consumed) { + *consumed = 0; + } _Py_RETURN_UNICODE_EMPTY(); } /* Escaped strings will always be longer than the resulting @@ -6441,8 +6462,6 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, unsigned char c = (unsigned char) *s++; Py_UCS4 ch; int count; - Py_ssize_t startinpos; - Py_ssize_t endinpos; const char *message; #define WRITE_ASCII_CHAR(ch) \ @@ -6469,11 +6488,11 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, continue; } - startinpos = s - starts - 1; + Py_ssize_t startinpos = s - starts - 1; /* \ - Escapes */ if (s >= end) { message = "\\ at end of string"; - goto error; + goto incomplete; } c = (unsigned char) *s++; @@ -6527,7 +6546,10 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, count = 8; message = "truncated \\UXXXXXXXX escape"; hexescape: - for (ch = 0; count && s < end; ++s, --count) { + for (ch = 0; count; ++s, --count) { + if (s >= end) { + goto incomplete; + } c = (unsigned char)*s; ch <<= 4; if (c >= '0' && c <= '9') { @@ -6540,12 +6562,9 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, ch += c - ('A' - 10); } else { - break; + goto error; } } - if (count) { - goto error; - } /* when we get here, ch is a 32-bit unicode character */ if (ch > MAX_UNICODE) { @@ -6572,14 +6591,20 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, } message = "malformed \\N character escape"; - if (s < end && *s == '{') { + if (s >= end) { + goto incomplete; + } + if (*s == '{') { const char *start = ++s; size_t namelen; /* look for the closing brace */ while (s < end && *s != '}') s++; + if (s >= end) { + goto incomplete; + } namelen = s - start; - if (namelen && s < end) { + if (namelen) { /* found a name. look it up in the unicode database */ s++; ch = 0xffffffff; /* in case 'getcode' messes up */ @@ -6605,8 +6630,13 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, continue; } - error: - endinpos = s-starts; + incomplete: + if (consumed) { + *consumed = startinpos; + break; + } + error:; + Py_ssize_t endinpos = s-starts; writer.min_length = end - s + writer.pos; if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, @@ -6633,12 +6663,14 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, } PyObject * -PyUnicode_DecodeUnicodeEscape(const char *s, +_PyUnicode_DecodeUnicodeEscapeStateful(const char *s, Py_ssize_t size, - const char *errors) + const char *errors, + Py_ssize_t *consumed) { const char *first_invalid_escape; - PyObject *result = _PyUnicode_DecodeUnicodeEscape(s, size, errors, + PyObject *result = _PyUnicode_DecodeUnicodeEscapeInternal(s, size, errors, + consumed, &first_invalid_escape); if (result == NULL) return NULL; @@ -6653,6 +6685,14 @@ PyUnicode_DecodeUnicodeEscape(const char *s, return result; } +PyObject * +PyUnicode_DecodeUnicodeEscape(const char *s, + Py_ssize_t size, + const char *errors) +{ + return _PyUnicode_DecodeUnicodeEscapeStateful(s, size, errors, NULL); +} + /* Return a Unicode-Escape string version of the Unicode object. */ PyObject * @@ -6791,9 +6831,10 @@ PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s, /* --- Raw Unicode Escape Codec ------------------------------------------- */ PyObject * -PyUnicode_DecodeRawUnicodeEscape(const char *s, - Py_ssize_t size, - const char *errors) +_PyUnicode_DecodeRawUnicodeEscapeStateful(const char *s, + Py_ssize_t size, + const char *errors, + Py_ssize_t *consumed) { const char *starts = s; _PyUnicodeWriter writer; @@ -6802,6 +6843,9 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, PyObject *exc = NULL; if (size == 0) { + if (consumed) { + *consumed = 0; + } _Py_RETURN_UNICODE_EMPTY(); } @@ -6820,8 +6864,6 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, unsigned char c = (unsigned char) *s++; Py_UCS4 ch; int count; - Py_ssize_t startinpos; - Py_ssize_t endinpos; const char *message; #define WRITE_CHAR(ch) \ @@ -6836,11 +6878,21 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, } while(0) /* Non-escape characters are interpreted as Unicode ordinals */ - if (c != '\\' || s >= end) { + if (c != '\\' || (s >= end && !consumed)) { WRITE_CHAR(c); continue; } + Py_ssize_t startinpos = s - starts - 1; + /* \ - Escapes */ + if (s >= end) { + assert(consumed); + // Set message to silent compiler warning. + // Actually it is never used. + message = "\\ at end of string"; + goto incomplete; + } + c = (unsigned char) *s++; if (c == 'u') { count = 4; @@ -6856,10 +6908,12 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, WRITE_CHAR(c); continue; } - startinpos = s - starts - 2; /* \uHHHH with 4 hex digits, \U00HHHHHH with 8 */ - for (ch = 0; count && s < end; ++s, --count) { + for (ch = 0; count; ++s, --count) { + if (s >= end) { + goto incomplete; + } c = (unsigned char)*s; ch <<= 4; if (c >= '0' && c <= '9') { @@ -6872,18 +6926,23 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, ch += c - ('A' - 10); } else { - break; + goto error; } } - if (!count) { - if (ch <= MAX_UNICODE) { - WRITE_CHAR(ch); - continue; - } + if (ch > MAX_UNICODE) { message = "\\Uxxxxxxxx out of range"; + goto error; } + WRITE_CHAR(ch); + continue; - endinpos = s-starts; + incomplete: + if (consumed) { + *consumed = startinpos; + break; + } + error:; + Py_ssize_t endinpos = s-starts; writer.min_length = end - s + writer.pos; if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, @@ -6905,7 +6964,14 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; +} +PyObject * +PyUnicode_DecodeRawUnicodeEscape(const char *s, + Py_ssize_t size, + const char *errors) +{ + return _PyUnicode_DecodeRawUnicodeEscapeStateful(s, size, errors, NULL); } @@ -7473,7 +7539,7 @@ PyUnicode_AsASCIIString(PyObject *unicode) #endif /* INT_MAX is the theoretical largest chunk (or INT_MAX / 2 when - transcoding from UTF-16), but INT_MAX / 4 perfoms better in + transcoding from UTF-16), but INT_MAX / 4 performs better in both cases also and avoids partial characters overrunning the length limit in MultiByteToWideChar on Windows */ #define DECODING_CHUNK_SIZE (INT_MAX/4) @@ -11023,7 +11089,7 @@ replace(PyObject *self, PyObject *str1, release1 = 1; } /* new_size = PyUnicode_GET_LENGTH(self) + n * (PyUnicode_GET_LENGTH(str2) - - PyUnicode_GET_LENGTH(str1))); */ + PyUnicode_GET_LENGTH(str1)); */ if (len1 < len2 && len2 - len1 > (PY_SSIZE_T_MAX - slen) / n) { PyErr_SetString(PyExc_OverflowError, "replace string is too long"); @@ -11551,11 +11617,13 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right) if (PyUnicode_CHECK_INTERNED(left)) return 0; +#ifdef INTERNED_STRINGS assert(_PyUnicode_HASH(right_uni) != -1); Py_hash_t hash = _PyUnicode_HASH(left); if (hash != -1 && hash != _PyUnicode_HASH(right_uni)) { return 0; } +#endif return unicode_compare_eq(left, right_uni); } @@ -15784,21 +15852,21 @@ PyUnicode_InternInPlace(PyObject **p) return; } +#ifdef INTERNED_STRINGS if (PyUnicode_READY(s) == -1) { PyErr_Clear(); return; } - struct _Py_unicode_state *state = get_unicode_state(); - if (state->interned == NULL) { - state->interned = PyDict_New(); - if (state->interned == NULL) { + if (interned == NULL) { + interned = PyDict_New(); + if (interned == NULL) { PyErr_Clear(); /* Don't leave an exception */ return; } } - PyObject *t = PyDict_SetDefault(state->interned, s, s); + PyObject *t = PyDict_SetDefault(interned, s, s); if (t == NULL) { PyErr_Clear(); return; @@ -15815,9 +15883,13 @@ PyUnicode_InternInPlace(PyObject **p) this. */ Py_SET_REFCNT(s, Py_REFCNT(s) - 2); _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL; +#else + // PyDict expects that interned strings have their hash + // (PyASCIIObject.hash) already computed. + (void)unicode_hash(s); +#endif } - void PyUnicode_InternImmortal(PyObject **p) { @@ -15851,11 +15923,15 @@ PyUnicode_InternFromString(const char *cp) void _PyUnicode_ClearInterned(PyInterpreterState *interp) { - struct _Py_unicode_state *state = &interp->unicode; - if (state->interned == NULL) { + if (!_Py_IsMainInterpreter(interp)) { + // interned dict is shared by all interpreters return; } - assert(PyDict_CheckExact(state->interned)); + + if (interned == NULL) { + return; + } + assert(PyDict_CheckExact(interned)); /* Interned unicode strings are not forcibly deallocated; rather, we give them their stolen references back, and then clear and DECREF the @@ -15863,13 +15939,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) #ifdef INTERNED_STATS fprintf(stderr, "releasing %zd interned strings\n", - PyDict_GET_SIZE(state->interned)); + PyDict_GET_SIZE(interned)); Py_ssize_t immortal_size = 0, mortal_size = 0; #endif Py_ssize_t pos = 0; PyObject *s, *ignored_value; - while (PyDict_Next(state->interned, &pos, &s, &ignored_value)) { + while (PyDict_Next(interned, &pos, &s, &ignored_value)) { assert(PyUnicode_IS_READY(s)); switch (PyUnicode_CHECK_INTERNED(s)) { @@ -15900,8 +15976,8 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) mortal_size, immortal_size); #endif - PyDict_Clear(state->interned); - Py_CLEAR(state->interned); + PyDict_Clear(interned); + Py_CLEAR(interned); } @@ -16149,7 +16225,7 @@ init_fs_codec(PyInterpreterState *interp) _Py_error_handler error_handler; error_handler = get_error_handler_wide(config->filesystem_errors); if (error_handler == _Py_ERROR_UNKNOWN) { - PyErr_SetString(PyExc_RuntimeError, "unknow filesystem error handler"); + PyErr_SetString(PyExc_RuntimeError, "unknown filesystem error handler"); return -1; } @@ -16273,8 +16349,10 @@ _PyUnicode_Fini(PyInterpreterState *interp) { struct _Py_unicode_state *state = &interp->unicode; - // _PyUnicode_ClearInterned() must be called before - assert(state->interned == NULL); + if (_Py_IsMainInterpreter(interp)) { + // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() + assert(interned == NULL); + } _PyUnicode_FiniEncodings(&state->fs_codec); diff --git a/Objects/unionobject.c b/Objects/unionobject.c index 05350363eed63f..80c70389ab30d6 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -1,12 +1,17 @@ -// types.Union -- used to represent e.g. Union[int, str], int | str +// types.UnionType -- used to represent e.g. Union[int, str], int | str #include "Python.h" +#include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK #include "pycore_unionobject.h" #include "structmember.h" +static PyObject *make_union(PyObject *); + + typedef struct { PyObject_HEAD PyObject *args; + PyObject *parameters; } unionobject; static void @@ -14,27 +19,42 @@ unionobject_dealloc(PyObject *self) { unionobject *alias = (unionobject *)self; + _PyObject_GC_UNTRACK(self); + Py_XDECREF(alias->args); + Py_XDECREF(alias->parameters); Py_TYPE(self)->tp_free(self); } +static int +union_traverse(PyObject *self, visitproc visit, void *arg) +{ + unionobject *alias = (unionobject *)self; + Py_VISIT(alias->args); + Py_VISIT(alias->parameters); + return 0; +} + static Py_hash_t union_hash(PyObject *self) { unionobject *alias = (unionobject *)self; - Py_hash_t h1 = PyObject_Hash(alias->args); - if (h1 == -1) { - return -1; + PyObject *args = PyFrozenSet_New(alias->args); + if (args == NULL) { + return (Py_hash_t)-1; } - return h1; + Py_hash_t hash = PyObject_Hash(args); + Py_DECREF(args); + return hash; } static int -is_generic_alias_in_args(PyObject *args) { +is_generic_alias_in_args(PyObject *args) +{ Py_ssize_t nargs = PyTuple_GET_SIZE(args); for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { PyObject *arg = PyTuple_GET_ITEM(args, iarg); - if (PyObject_TypeCheck(arg, &Py_GenericAliasType)) { + if (_PyGenericAlias_Check(arg)) { return 0; } } @@ -53,11 +73,14 @@ union_instancecheck(PyObject *self, PyObject *instance) } for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg); - if (arg == Py_None) { - arg = (PyObject *)&_PyNone_Type; - } - if (PyType_Check(arg) && PyObject_IsInstance(instance, arg) != 0) { - Py_RETURN_TRUE; + if (PyType_Check(arg)) { + int res = PyObject_IsInstance(instance, arg); + if (res < 0) { + return NULL; + } + if (res) { + Py_RETURN_TRUE; + } } } Py_RETURN_FALSE; @@ -79,100 +102,38 @@ union_subclasscheck(PyObject *self, PyObject *instance) Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args); for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg); - if (PyType_Check(arg) && (PyType_IsSubtype((PyTypeObject *)instance, (PyTypeObject *)arg) != 0)) { - Py_RETURN_TRUE; + if (PyType_Check(arg)) { + int res = PyObject_IsSubclass(instance, arg); + if (res < 0) { + return NULL; + } + if (res) { + Py_RETURN_TRUE; + } } } - Py_RETURN_FALSE; -} - -static int -is_typing_module(PyObject *obj) { - PyObject *module = PyObject_GetAttrString(obj, "__module__"); - if (module == NULL) { - return -1; - } - int is_typing = PyUnicode_Check(module) && _PyUnicode_EqualToASCIIString(module, "typing"); - Py_DECREF(module); - return is_typing; -} - -static int -is_typing_name(PyObject *obj, char *name) -{ - PyTypeObject *type = Py_TYPE(obj); - if (strcmp(type->tp_name, name) != 0) { - return 0; - } - return is_typing_module(obj); + Py_RETURN_FALSE; } static PyObject * union_richcompare(PyObject *a, PyObject *b, int op) { - PyObject *result = NULL; - if (op != Py_EQ && op != Py_NE) { - result = Py_NotImplemented; - Py_INCREF(result); - return result; + if (!_PyUnion_Check(b) || (op != Py_EQ && op != Py_NE)) { + Py_RETURN_NOTIMPLEMENTED; } - PyTypeObject *type = Py_TYPE(b); - - PyObject* a_set = PySet_New(((unionobject*)a)->args); + PyObject *a_set = PySet_New(((unionobject*)a)->args); if (a_set == NULL) { return NULL; } - PyObject* b_set = PySet_New(NULL); + PyObject *b_set = PySet_New(((unionobject*)b)->args); if (b_set == NULL) { - goto exit; - } - - // Populate b_set with the data from the right object - int is_typing_union = is_typing_name(b, "_UnionGenericAlias"); - if (is_typing_union < 0) { - goto exit; - } - if (is_typing_union) { - PyObject *b_args = PyObject_GetAttrString(b, "__args__"); - if (b_args == NULL) { - goto exit; - } - if (!PyTuple_CheckExact(b_args)) { - Py_DECREF(b_args); - PyErr_SetString(PyExc_TypeError, "__args__ argument of typing.Union object is not a tuple"); - goto exit; - } - Py_ssize_t b_arg_length = PyTuple_GET_SIZE(b_args); - for (Py_ssize_t i = 0; i < b_arg_length; i++) { - PyObject* arg = PyTuple_GET_ITEM(b_args, i); - if (arg == (PyObject *)&_PyNone_Type) { - arg = Py_None; - } - if (PySet_Add(b_set, arg) == -1) { - Py_DECREF(b_args); - goto exit; - } - } - Py_DECREF(b_args); - } else if (type == &_Py_UnionType) { - PyObject* args = ((unionobject*) b)->args; - Py_ssize_t arg_length = PyTuple_GET_SIZE(args); - for (Py_ssize_t i = 0; i < arg_length; i++) { - PyObject* arg = PyTuple_GET_ITEM(args, i); - if (PySet_Add(b_set, arg) == -1) { - goto exit; - } - } - } else { - if (PySet_Add(b_set, b) == -1) { - goto exit; - } + Py_DECREF(a_set); + return NULL; } - result = PyObject_RichCompare(a_set, b_set, op); -exit: - Py_XDECREF(a_set); - Py_XDECREF(b_set); + PyObject *result = PyObject_RichCompare(a_set, b_set, op); + Py_DECREF(b_set); + Py_DECREF(a_set); return result; } @@ -184,8 +145,7 @@ flatten_args(PyObject* args) // Get number of total args once it's flattened. for (Py_ssize_t i = 0; i < arg_length; i++) { PyObject *arg = PyTuple_GET_ITEM(args, i); - PyTypeObject* arg_type = Py_TYPE(arg); - if (arg_type == &_Py_UnionType) { + if (_PyUnion_Check(arg)) { total_args += PyTuple_GET_SIZE(((unionobject*) arg)->args); } else { total_args++; @@ -199,8 +159,7 @@ flatten_args(PyObject* args) Py_ssize_t pos = 0; for (Py_ssize_t i = 0; i < arg_length; i++) { PyObject *arg = PyTuple_GET_ITEM(args, i); - PyTypeObject* arg_type = Py_TYPE(arg); - if (arg_type == &_Py_UnionType) { + if (_PyUnion_Check(arg)) { PyObject* nested_args = ((unionobject*)arg)->args; Py_ssize_t nested_arg_length = PyTuple_GET_SIZE(nested_args); for (Py_ssize_t j = 0; j < nested_arg_length; j++) { @@ -210,11 +169,15 @@ flatten_args(PyObject* args) pos++; } } else { + if (arg == Py_None) { + arg = (PyObject *)&_PyNone_Type; + } Py_INCREF(arg); PyTuple_SET_ITEM(flattened_args, pos, arg); pos++; } } + assert(pos == total_args); return flattened_args; } @@ -228,6 +191,7 @@ dedup_and_flatten_args(PyObject* args) Py_ssize_t arg_length = PyTuple_GET_SIZE(args); PyObject *new_args = PyTuple_New(arg_length); if (new_args == NULL) { + Py_DECREF(args); return NULL; } // Add unique elements to an array. @@ -235,10 +199,10 @@ dedup_and_flatten_args(PyObject* args) for (Py_ssize_t i = 0; i < arg_length; i++) { int is_duplicate = 0; PyObject* i_element = PyTuple_GET_ITEM(args, i); - for (Py_ssize_t j = i + 1; j < arg_length; j++) { - PyObject* j_element = PyTuple_GET_ITEM(args, j); - int is_ga = PyObject_TypeCheck(i_element, &Py_GenericAliasType) && - PyObject_TypeCheck(j_element, &Py_GenericAliasType); + for (Py_ssize_t j = 0; j < added_items; j++) { + PyObject* j_element = PyTuple_GET_ITEM(new_args, j); + int is_ga = _PyGenericAlias_Check(i_element) && + _PyGenericAlias_Check(j_element); // RichCompare to also deduplicate GenericAlias types (slower) is_duplicate = is_ga ? PyObject_RichCompareBool(i_element, j_element, Py_EQ) : i_element == j_element; @@ -262,52 +226,28 @@ dedup_and_flatten_args(PyObject* args) return new_args; } -static int -is_typevar(PyObject *obj) -{ - return is_typing_name(obj, "TypeVar"); -} - -static int -is_special_form(PyObject *obj) -{ - return is_typing_name(obj, "_SpecialForm"); -} - -static int -is_new_type(PyObject *obj) -{ - PyTypeObject *type = Py_TYPE(obj); - if (type != &PyFunction_Type) { - return 0; - } - return is_typing_module(obj); -} - static int is_unionable(PyObject *obj) { - if (obj == Py_None) { - return 1; - } - PyTypeObject *type = Py_TYPE(obj); - return ( - is_typevar(obj) || - is_new_type(obj) || - is_special_form(obj) || + return (obj == Py_None || PyType_Check(obj) || - PyObject_TypeCheck(obj, &Py_GenericAliasType) || - type == &_Py_UnionType); + _PyGenericAlias_Check(obj) || + _PyUnion_Check(obj)); } PyObject * -_Py_union_type_or(PyObject* self, PyObject* param) +_Py_union_type_or(PyObject* self, PyObject* other) { - PyObject *tuple = PyTuple_Pack(2, self, param); + if (!is_unionable(self) || !is_unionable(other)) { + Py_RETURN_NOTIMPLEMENTED; + } + + PyObject *tuple = PyTuple_Pack(2, self, other); if (tuple == NULL) { return NULL; } - PyObject *new_union = _Py_Union(tuple); + + PyObject *new_union = make_union(tuple); Py_DECREF(tuple); return new_union; } @@ -325,6 +265,10 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p) PyObject *r = NULL; int err; + if (p == (PyObject *)&_PyNone_Type) { + return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4); + } + if (_PyObject_LookupAttrId(p, &PyId___origin__, &tmp) < 0) { goto exit; } @@ -413,63 +357,140 @@ static PyMethodDef union_methods[] = { {"__subclasscheck__", union_subclasscheck, METH_O}, {0}}; + +static PyObject * +union_getitem(PyObject *self, PyObject *item) +{ + unionobject *alias = (unionobject *)self; + // Populate __parameters__ if needed. + if (alias->parameters == NULL) { + alias->parameters = _Py_make_parameters(alias->args); + if (alias->parameters == NULL) { + return NULL; + } + } + + PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item); + if (newargs == NULL) { + return NULL; + } + + PyObject *res; + Py_ssize_t nargs = PyTuple_GET_SIZE(newargs); + if (nargs == 0) { + res = make_union(newargs); + } + else { + res = PyTuple_GET_ITEM(newargs, 0); + Py_INCREF(res); + for (Py_ssize_t iarg = 1; iarg < nargs; iarg++) { + PyObject *arg = PyTuple_GET_ITEM(newargs, iarg); + Py_SETREF(res, PyNumber_Or(res, arg)); + if (res == NULL) { + break; + } + } + } + Py_DECREF(newargs); + return res; +} + +static PyMappingMethods union_as_mapping = { + .mp_subscript = union_getitem, +}; + +static PyObject * +union_parameters(PyObject *self, void *Py_UNUSED(unused)) +{ + unionobject *alias = (unionobject *)self; + if (alias->parameters == NULL) { + alias->parameters = _Py_make_parameters(alias->args); + if (alias->parameters == NULL) { + return NULL; + } + } + Py_INCREF(alias->parameters); + return alias->parameters; +} + +static PyGetSetDef union_properties[] = { + {"__parameters__", union_parameters, (setter)NULL, "Type variables in the types.UnionType.", NULL}, + {0} +}; + static PyNumberMethods union_as_number = { .nb_or = _Py_union_type_or, // Add __or__ function }; -PyTypeObject _Py_UnionType = { +static const char* const cls_attrs[] = { + "__module__", // Required for compatibility with typing module + NULL, +}; + +static PyObject * +union_getattro(PyObject *self, PyObject *name) +{ + unionobject *alias = (unionobject *)self; + if (PyUnicode_Check(name)) { + for (const char * const *p = cls_attrs; ; p++) { + if (*p == NULL) { + break; + } + if (_PyUnicode_EqualToASCIIString(name, *p)) { + return PyObject_GetAttr((PyObject *) Py_TYPE(alias), name); + } + } + } + return PyObject_GenericGetAttr(self, name); +} + +PyTypeObject _PyUnion_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - .tp_name = "types.Union", + .tp_name = "types.UnionType", .tp_doc = "Represent a PEP 604 union type\n" "\n" "E.g. for int | str", .tp_basicsize = sizeof(unionobject), .tp_dealloc = unionobject_dealloc, .tp_alloc = PyType_GenericAlloc, - .tp_free = PyObject_Del, - .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_free = PyObject_GC_Del, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .tp_traverse = union_traverse, .tp_hash = union_hash, - .tp_getattro = PyObject_GenericGetAttr, + .tp_getattro = union_getattro, .tp_members = union_members, .tp_methods = union_methods, .tp_richcompare = union_richcompare, + .tp_as_mapping = &union_as_mapping, .tp_as_number = &union_as_number, .tp_repr = union_repr, + .tp_getset = union_properties, }; -PyObject * -_Py_Union(PyObject *args) +static PyObject * +make_union(PyObject *args) { assert(PyTuple_CheckExact(args)); - unionobject* result = NULL; - - // Check arguments are unionable. - Py_ssize_t nargs = PyTuple_GET_SIZE(args); - for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { - PyObject *arg = PyTuple_GET_ITEM(args, iarg); - if (arg == NULL) { - return NULL; - } - int is_arg_unionable = is_unionable(arg); - if (is_arg_unionable < 0) { - return NULL; - } - if (!is_arg_unionable) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } + args = dedup_and_flatten_args(args); + if (args == NULL) { + return NULL; + } + if (PyTuple_GET_SIZE(args) == 1) { + PyObject *result1 = PyTuple_GET_ITEM(args, 0); + Py_INCREF(result1); + Py_DECREF(args); + return result1; } - result = PyObject_New(unionobject, &_Py_UnionType); + unionobject *result = PyObject_GC_New(unionobject, &_PyUnion_Type); if (result == NULL) { + Py_DECREF(args); return NULL; } - result->args = dedup_and_flatten_args(args); - if (result->args == NULL) { - Py_DECREF(result); - return NULL; - } + result->parameters = NULL; + result->args = args; + _PyObject_GC_TRACK(result); return (PyObject*)result; } diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 313e8abab5a25f..bb56c7dbdb8322 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -657,6 +657,12 @@ proxy_iternext(PyWeakReference *proxy) return NULL; PyObject *obj = PyWeakref_GET_OBJECT(proxy); + if (!PyIter_Check(obj)) { + PyErr_Format(PyExc_TypeError, + "Weakref proxy referenced a non-iterator '%.200s' object", + Py_TYPE(obj)->tp_name); + return NULL; + } Py_INCREF(obj); PyObject* res = PyIter_Next(obj); Py_DECREF(obj); @@ -732,21 +738,6 @@ static PyMappingMethods proxy_as_mapping = { }; -static Py_hash_t -proxy_hash(PyObject *self) -{ - PyWeakReference *proxy = (PyWeakReference *)self; - if (!proxy_checkref(proxy)) { - return -1; - } - PyObject *obj = PyWeakref_GET_OBJECT(proxy); - Py_INCREF(obj); - Py_hash_t res = PyObject_Hash(obj); - Py_DECREF(obj); - return res; -} - - PyTypeObject _PyWeakref_ProxyType = { PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -763,7 +754,8 @@ _PyWeakref_ProxyType = { &proxy_as_number, /* tp_as_number */ &proxy_as_sequence, /* tp_as_sequence */ &proxy_as_mapping, /* tp_as_mapping */ - proxy_hash, /* tp_hash */ +// Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies). + 0, /* tp_hash */ 0, /* tp_call */ proxy_str, /* tp_str */ proxy_getattr, /* tp_getattro */ diff --git a/PC/getpathp.c b/PC/getpathp.c index 53da3a6d05faee..7c0eeab5dbab4a 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -29,7 +29,7 @@ - If we DO have a Python Home: The relevant sub-directories (Lib, DLLs, etc) are based on the Python Home - If we DO NOT have a Python Home, the core Python Path is - loaded from the registry. This is the main PythonPath key, + loaded from the registry. (This is the main PythonPath key, and both HKLM and HKCU are combined to form the path) * Iff - we can not locate the Python Home, have not had a PYTHONPATH @@ -91,7 +91,6 @@ #include #include -#include #ifdef HAVE_SYS_TYPES_H #include @@ -332,7 +331,7 @@ extern const char *PyWin_DLLVersionString; Returns NULL, or a pointer that should be freed. XXX - this code is pretty strange, as it used to also - work on Win16, where the buffer sizes werent available + work on Win16, where the buffer sizes were not available in advance. It could be simplied now Win16/Win32s is dead! */ static wchar_t * diff --git a/PC/launcher.c b/PC/launcher.c index f5b225ac08cfe1..734e7533398b14 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -344,7 +344,7 @@ _locate_pythons_for_key(HKEY root, LPCWSTR subkey, REGSAM flags, int bits, } else if (attrs & FILE_ATTRIBUTE_DIRECTORY) { debug(L"locate_pythons_for_key: '%ls' is a directory\n", - ip->executable, attrs); + ip->executable); } else if (find_existing_python(ip->executable)) { debug(L"locate_pythons_for_key: %ls: already found\n", @@ -542,8 +542,17 @@ find_python_by_version(wchar_t const * wanted_ver) } for (i = 0; i < num_installed_pythons; i++, ip++) { n = wcslen(ip->version); - if (n > wlen) + /* + * If wlen is greater than 1, we're probably trying to find a specific + * version and thus want an exact match: 3.1 != 3.10. Otherwise, we + * just want a prefix match. + */ + if ((wlen > 1) && (n != wlen)) { + continue; + } + if (n > wlen) { n = wlen; + } if ((wcsncmp(ip->version, wanted_ver, n) == 0) && /* bits == 0 => don't care */ ((bits == 0) || (ip->bits == bits))) { diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py index 747c97a00699dd..15119b02a802a7 100644 --- a/PC/layout/support/appxmanifest.py +++ b/PC/layout/support/appxmanifest.py @@ -430,7 +430,7 @@ def get_appxmanifest(ns): ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], PYTHON_VE_DATA, "console", - ("python.file", [".py"], '"%1"', "Python File", PY_PNG), + ("python.file", [".py"], '"%1" %*', "Python File", PY_PNG), ) add_application( @@ -441,7 +441,7 @@ def get_appxmanifest(ns): ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], PYTHONW_VE_DATA, "windows", - ("python.windowedfile", [".pyw"], '"%1"', "Python File (no console)", PY_PNG), + ("python.windowedfile", [".pyw"], '"%1" %*', "Python File (no console)", PY_PNG), ) if ns.include_pip and ns.include_launchers: diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index 92987af7138dd3..ff7e71e0fdb4e1 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -2,9 +2,13 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" #if defined(PY_ICON) diff --git a/PC/pyshellext.rc b/PC/pyshellext.rc index e5924a42dabe29..af797ce95d5077 100644 --- a/PC/pyshellext.rc +++ b/PC/pyshellext.rc @@ -2,9 +2,14 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/python3dll.c b/PC/python3dll.c index 574d4dcad9f75b..08d3c524e49575 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -55,9 +55,7 @@ EXPORT_FUNC(Py_Exit) EXPORT_FUNC(Py_FatalError) EXPORT_FUNC(Py_Finalize) EXPORT_FUNC(Py_FinalizeEx) -EXPORT_FUNC(Py_FrozenMain) EXPORT_FUNC(Py_GenericAlias) -EXPORT_FUNC(Py_GenericAliasType) EXPORT_FUNC(Py_GetArgcArgv) EXPORT_FUNC(Py_GetBuildInfo) EXPORT_FUNC(Py_GetCompiler) @@ -92,7 +90,7 @@ EXPORT_FUNC(Py_SetPythonHome) EXPORT_FUNC(Py_SetRecursionLimit) EXPORT_FUNC(Py_VaBuildValue) EXPORT_FUNC(Py_XNewRef) -EXPORT_FUNC(PyAiter_Check) +EXPORT_FUNC(PyAIter_Check) EXPORT_FUNC(PyArg_Parse) EXPORT_FUNC(PyArg_ParseTuple) EXPORT_FUNC(PyArg_ParseTupleAndKeywords) @@ -156,6 +154,7 @@ EXPORT_FUNC(PyCodec_ReplaceErrors) EXPORT_FUNC(PyCodec_StreamReader) EXPORT_FUNC(PyCodec_StreamWriter) EXPORT_FUNC(PyCodec_StrictErrors) +EXPORT_FUNC(PyCodec_Unregister) EXPORT_FUNC(PyCodec_XMLCharRefReplaceErrors) EXPORT_FUNC(PyComplex_FromDoubles) EXPORT_FUNC(PyComplex_ImagAsDouble) @@ -418,8 +417,11 @@ EXPORT_FUNC(PyNumber_Subtract) EXPORT_FUNC(PyNumber_ToBase) EXPORT_FUNC(PyNumber_TrueDivide) EXPORT_FUNC(PyNumber_Xor) +EXPORT_FUNC(PyObject_AsCharBuffer) EXPORT_FUNC(PyObject_ASCII) EXPORT_FUNC(PyObject_AsFileDescriptor) +EXPORT_FUNC(PyObject_AsReadBuffer) +EXPORT_FUNC(PyObject_AsWriteBuffer) EXPORT_FUNC(PyObject_Bytes) EXPORT_FUNC(PyObject_Call) EXPORT_FUNC(PyObject_CallFunction) @@ -429,6 +431,7 @@ EXPORT_FUNC(PyObject_CallMethodObjArgs) EXPORT_FUNC(PyObject_CallNoArgs) EXPORT_FUNC(PyObject_CallObject) EXPORT_FUNC(PyObject_Calloc) +EXPORT_FUNC(PyObject_CheckReadBuffer) EXPORT_FUNC(PyObject_ClearWeakRefs) EXPORT_FUNC(PyObject_DelItem) EXPORT_FUNC(PyObject_DelItemString) @@ -444,7 +447,7 @@ EXPORT_FUNC(PyObject_GenericGetAttr) EXPORT_FUNC(PyObject_GenericGetDict) EXPORT_FUNC(PyObject_GenericSetAttr) EXPORT_FUNC(PyObject_GenericSetDict) -EXPORT_FUNC(PyObject_GetAiter) +EXPORT_FUNC(PyObject_GetAIter) EXPORT_FUNC(PyObject_GetAttr) EXPORT_FUNC(PyObject_GetAttrString) EXPORT_FUNC(PyObject_GetItem) @@ -722,6 +725,7 @@ EXPORT_DATA(_PyWeakref_ProxyType) EXPORT_DATA(_PyWeakref_RefType) EXPORT_DATA(Py_FileSystemDefaultEncodeErrors) EXPORT_DATA(Py_FileSystemDefaultEncoding) +EXPORT_DATA(Py_GenericAliasType) EXPORT_DATA(Py_HasFileSystemDefaultEncoding) EXPORT_DATA(Py_UTF8Mode) EXPORT_DATA(PyBaseObject_Type) @@ -734,7 +738,6 @@ EXPORT_DATA(PyCallIter_Type) EXPORT_DATA(PyCapsule_Type) EXPORT_DATA(PyCFunction_Type) EXPORT_DATA(PyClassMethodDescr_Type) -EXPORT_DATA(PyCodec_Unregister) EXPORT_DATA(PyComplex_Type) EXPORT_DATA(PyDict_Type) EXPORT_DATA(PyDictItems_Type) diff --git a/PC/python_exe.rc b/PC/python_exe.rc index ae0b029b8070a4..c3d3bff019895e 100644 --- a/PC/python_exe.rc +++ b/PC/python_exe.rc @@ -2,9 +2,14 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\python.ico" diff --git a/PC/python_nt.rc b/PC/python_nt.rc index b5fb58f26b2028..ae64fbd217af74 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -2,9 +2,14 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/python_ver_rc.h b/PC/python_ver_rc.h index 90fc6ba1a1460c..e6c1d243704154 100644 --- a/PC/python_ver_rc.h +++ b/PC/python_ver_rc.h @@ -5,7 +5,7 @@ #include "winver.h" #define PYTHON_COMPANY "Python Software Foundation" -#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2021 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC." +#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2022 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC." #define MS_WINDOWS #include "modsupport.h" diff --git a/PC/pythonw_exe.rc b/PC/pythonw_exe.rc index 88bf3592e18124..38570b74fa3e02 100644 --- a/PC/pythonw_exe.rc +++ b/PC/pythonw_exe.rc @@ -2,9 +2,14 @@ #include "python_ver_rc.h" +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. -#include 1 RT_MANIFEST "python.manifest" 1 ICON DISCARDABLE "icons\pythonw.ico" diff --git a/PC/sqlite3.rc b/PC/sqlite3.rc index 84bd87d9d575d6..9ae2aa0f6f2f2c 100644 --- a/PC/sqlite3.rc +++ b/PC/sqlite3.rc @@ -2,9 +2,14 @@ #include +#ifndef RT_MANIFEST +// bpo-45220: Cannot reliably #include RT_MANIFEST from +// anywhere, so we hardcode it +#define RT_MANIFEST 24 +#endif + // Include the manifest file that indicates we support all // current versions of Windows. -#include 2 RT_MANIFEST "python.manifest" ///////////////////////////////////////////////////////////////////////////// diff --git a/PC/store_info.txt b/PC/store_info.txt index 8c20412a5f0711..f6a85cb8ebec1f 100644 --- a/PC/store_info.txt +++ b/PC/store_info.txt @@ -82,7 +82,7 @@ Python Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms. -The Python interpreter and the extensive standard library are freely available in source or binary form for all major platforms from the Python Web site, https://www.python.org/, and may be freely distributed. The same site also contains distributions of and pointers to many free third party Python modules, programs and tools, and additional documentation. +The Python interpreter and the extensive standard library are freely available in source or binary form for all major platforms from the Python web site, https://www.python.org/, and may be freely distributed. The same site also contains distributions of and pointers to many free third party Python modules, programs and tools, and additional documentation. The Python interpreter is easily extended with new functions and data types implemented in C or C++ (or other languages callable from C). Python is also suitable as an extension language for customizable applications. diff --git a/PCbuild/Directory.Build.props b/PCbuild/Directory.Build.props new file mode 100644 index 00000000000000..3d2fe55078450a --- /dev/null +++ b/PCbuild/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/Directory.Build.targets b/PCbuild/Directory.Build.targets new file mode 100644 index 00000000000000..3d2fe55078450a --- /dev/null +++ b/PCbuild/Directory.Build.targets @@ -0,0 +1,4 @@ + + + + diff --git a/PCbuild/_freeze_importlib.vcxproj b/PCbuild/_freeze_importlib.vcxproj index 52d8f1a64bb6b9..e437412a161ce5 100644 --- a/PCbuild/_freeze_importlib.vcxproj +++ b/PCbuild/_freeze_importlib.vcxproj @@ -123,6 +123,11 @@ $(IntDir)importlib_zipimport.g.h $(PySourcePath)Python\importlib_zipimport.h + + hello + $(IntDir)frozen_hello.g.h + $(PySourcePath)Python\frozen_hello.h + @@ -130,11 +135,6 @@ - - <_OldContent Condition="Exists($(OutTargetPath))"> - <_NewContent Condition="Exists($(IntTargetPath))">$([System.IO.File]::ReadAllText($(IntTargetPath)).Replace(` `, ` `)) - - @@ -153,9 +153,7 @@ - - - + diff --git a/PCbuild/get_external.py b/PCbuild/get_external.py index a682d3849f14c6..4ecc8925349c93 100755 --- a/PCbuild/get_external.py +++ b/PCbuild/get_external.py @@ -3,6 +3,8 @@ import argparse import os import pathlib +import sys +import time import zipfile from urllib.request import urlretrieve @@ -53,7 +55,22 @@ def main(): verbose=args.verbose, ) final_name = args.externals_dir / args.tag - extract_zip(args.externals_dir, zip_path).replace(final_name) + extracted = extract_zip(args.externals_dir, zip_path) + for wait in [1, 2, 3, 5, 8, 0]: + try: + extracted.replace(final_name) + break + except PermissionError as ex: + retry = f" Retrying in {wait}s..." if wait else "" + print(f"Encountered permission error '{ex}'.{retry}", file=sys.stderr) + time.sleep(wait) + else: + print( + f"ERROR: Failed to extract {final_name}.", + "You may need to restart your build", + file=sys.stderr, + ) + sys.exit(1) if __name__ == '__main__': diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 63e3bb47672cc9..2d12abcda7139d 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -52,11 +52,11 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 -if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1k +if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m set libraries=%libraries% sqlite-3.35.5.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.11.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.11.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -76,9 +76,9 @@ for %%e in (%libraries%) do ( echo.Fetching external binaries... set binaries= -if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1k-1 -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.11.0 +if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1m +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/lib.pyproj b/PCbuild/lib.pyproj index eba4d7591568dd..c826ffa080c504 100644 --- a/PCbuild/lib.pyproj +++ b/PCbuild/lib.pyproj @@ -1429,7 +1429,6 @@ - @@ -1441,7 +1440,6 @@ - diff --git a/PCbuild/prepare_libffi.bat b/PCbuild/prepare_libffi.bat index 922a47565c8da5..7e7842a2fc97a4 100644 --- a/PCbuild/prepare_libffi.bat +++ b/PCbuild/prepare_libffi.bat @@ -38,6 +38,7 @@ set BUILD_ARM32= set BUILD_ARM64= set BUILD_PDB= set BUILD_NOOPT= +set COPY_LICENSE= set INSTALL_CYGWIN= :CheckOpts @@ -49,6 +50,7 @@ if /I "%1"=="-arm32" (set BUILD_ARM32=1) & shift & goto :CheckOpts if /I "%1"=="-arm64" (set BUILD_ARM64=1) & shift & goto :CheckOpts if /I "%1"=="-pdb" (set BUILD_PDB=-g) & shift & goto :CheckOpts if /I "%1"=="-noopt" (set BUILD_NOOPT=CFLAGS='-Od -warn all') & shift & goto :CheckOpts +if /I "%1"=="-license" (set COPY_LICENSE=1) & shift & goto :CheckOpts if /I "%1"=="-?" goto :Usage if /I "%1"=="--install-cygwin" (set INSTALL_CYGWIN=1) & shift & goto :CheckOpts goto :Usage @@ -60,6 +62,7 @@ if NOT DEFINED BUILD_X64 if NOT DEFINED BUILD_X86 if NOT DEFINED BUILD_ARM32 if set BUILD_X86=1 set BUILD_ARM32=1 set BUILD_ARM64=1 + set COPY_LICENSE=1 ) if "%INSTALL_CYGWIN%"=="1" call :InstallCygwin @@ -98,9 +101,14 @@ if not exist Makefile.in ( ) if "%BUILD_X64%"=="1" call :BuildOne x64 x86_64-w64-cygwin x86_64-w64-cygwin +if errorlevel 1 exit /B %ERRORLEVEL% if "%BUILD_X86%"=="1" call :BuildOne x86 i686-pc-cygwin i686-pc-cygwin +if errorlevel 1 exit /B %ERRORLEVEL% if "%BUILD_ARM32%"=="1" call :BuildOne x86_arm i686-pc-cygwin arm-w32-cygwin +if errorlevel 1 exit /B %ERRORLEVEL% if "%BUILD_ARM64%"=="1" call :BuildOne x86_arm64 i686-pc-cygwin aarch64-w64-cygwin +if errorlevel 1 exit /B %ERRORLEVEL% +if "%COPY_LICENSE%"=="1" copy /y "%LIBFFI_SOURCE%\LICENSE" "%LIBFFI_OUT%\LICENSE" popd endlocal @@ -179,11 +187,11 @@ if "%LIBFFI_TEST%" EQU "1" ( echo copying files to %_LIBFFI_OUT% if not exist %_LIBFFI_OUT%\include (md %_LIBFFI_OUT%\include) -copy %ARTIFACTS%\.libs\libffi-7.dll %_LIBFFI_OUT% -copy %ARTIFACTS%\.libs\libffi-7.lib %_LIBFFI_OUT% -copy %ARTIFACTS%\.libs\libffi-7.pdb %_LIBFFI_OUT% -copy %ARTIFACTS%\fficonfig.h %_LIBFFI_OUT%\include -copy %ARTIFACTS%\include\*.h %_LIBFFI_OUT%\include +copy %ARTIFACTS%\.libs\libffi-*.dll %_LIBFFI_OUT% || exit /B 1 +copy %ARTIFACTS%\.libs\libffi-*.lib %_LIBFFI_OUT% || exit /B 1 +copy %ARTIFACTS%\.libs\libffi-*.pdb %_LIBFFI_OUT% +copy %ARTIFACTS%\fficonfig.h %_LIBFFI_OUT%\include || exit /B 1 +copy %ARTIFACTS%\include\*.h %_LIBFFI_OUT%\include || exit /B 1 endlocal exit /b diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 834b27c86d42c8..d492b71dfbaa3d 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -44,11 +44,11 @@ Default true true - OnlyExplicitInline - OnlyExplicitInline + $(EnableControlFlowGuard) /utf-8 %(AdditionalOptions) + OnlyExplicitInline Disabled false MultiThreadedDebugDLL diff --git a/PCbuild/python.props b/PCbuild/python.props index 419d5ebe84c2d1..5bf1f61e08c5f2 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -11,7 +11,8 @@ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored. --> - v142 + v142 + v142 v141 v140 v120 @@ -59,11 +60,11 @@ $(ExternalsDir)sqlite-3.35.5.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ - $(ExternalsDir)libffi\ - $(ExternalsDir)libffi\$(ArchName)\ + $(ExternalsDir)libffi-3.3.0\ + $(ExternalsDir)libffi-3.3.0\$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1k\ - $(ExternalsDir)openssl-bin-1.1.1k-1\$(ArchName)\ + $(ExternalsDir)openssl-1.1.1m\ + $(ExternalsDir)openssl-bin-1.1.1m\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.11\ @@ -108,9 +109,18 @@ 10.0.10586.0 - $(_RegistryVersion) + $(_RegistryVersion) - + + + + <_Message>Failed to locate a Windows SDK installation. + <_Message>$(_Message) If the build fails, please use the Visual Studio Installer to install the Windows SDK. + <_Message>$(_Message) (Ignore the version number specified in the error message and select the latest.) + + + + $(DefaultWindowsSDKVersion) @@ -175,7 +185,7 @@ 11 12 - + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber) $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)$(ReleaseLevelName) diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index 2094420a8df395..b58945a4d19b6c 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -114,7 +114,9 @@ + + ucrtbase @@ -145,23 +147,4 @@ $(_PGOPath) - - - - - <_LicenseFiles Include="@(LicenseFiles)"> - $([System.IO.File]::ReadAllText(%(FullPath))) - - - - - diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 0382977d6c367a..c39ba3e1a9f412 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -106,7 +106,7 @@ _Py_HAVE_ZLIB;%(PreprocessorDefinitions) - version.lib;shlwapi.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) + version.lib;ws2_32.lib;pathcch.lib;%(AdditionalDependencies) diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 4d386cfa5f387f..08ace5707c6a89 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -73,12 +73,42 @@ - + - - + + + + + + <_LicenseSources Include="$(PySourcePath)LICENSE; + $(PySourcePath)PC\crtlicense.txt; + $(bz2Dir)LICENSE; + $(opensslOutDir)LICENSE; + $(libffiDir)LICENSE;" /> + <_LicenseSources Include="$(tcltkDir)tcllicense.terms; + $(tcltkDir)tklicense.terms; + $(tcltkDir)tixlicense.terms" Condition="$(IncludeTkinter)" /> + + + + + <_Text1 Include="@(_LicenseSources)"> + $([System.IO.File]::ReadAllText(%(FullPath))) + + <_Text Include="@(_Text1->'%(Content)')" /> + + + + + + + + diff --git a/PCbuild/sqlite3.vcxproj b/PCbuild/sqlite3.vcxproj index 39f10c5abd69de..e39e2d9c226ca1 100644 --- a/PCbuild/sqlite3.vcxproj +++ b/PCbuild/sqlite3.vcxproj @@ -98,7 +98,7 @@ $(sqlite3Dir);%(AdditionalIncludeDirectories) - SQLITE_ENABLE_JSON1;SQLITE_ENABLE_FTS4;SQLITE_ENABLE_FTS5;SQLITE_ENABLE_RTREE;SQLITE_API=__declspec(dllexport);%(PreprocessorDefinitions) + SQLITE_ENABLE_MATH_FUNCTIONS;SQLITE_ENABLE_JSON1;SQLITE_ENABLE_FTS4;SQLITE_ENABLE_FTS5;SQLITE_ENABLE_RTREE;SQLITE_API=__declspec(dllexport);%(PreprocessorDefinitions) Level1 diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index 1101796bb3604a..16dc35d45ebd5c 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 11 + 12 0 $(TclMajorVersion) $(TclMinorVersion) diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 85225fc88c5a54..32fdc01a7e0e6e 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -74,7 +74,7 @@ module Python -- x < 4 < 3 and (x < 4) < 3 | Compare(expr left, cmpop* ops, expr* comparators) | Call(expr func, expr* args, keyword* keywords) - | FormattedValue(expr value, int? conversion, expr? format_spec) + | FormattedValue(expr value, int conversion, expr? format_spec) | JoinedStr(expr* values) | Constant(constant value, string? kind) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index b71565c53fc010..4e5c5c8f7f7093 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -6,6 +6,7 @@ import textwrap from argparse import ArgumentParser +from contextlib import contextmanager from pathlib import Path import asdl @@ -421,6 +422,14 @@ def visitProduct(self, prod, name): class Obj2ModVisitor(PickleVisitor): + @contextmanager + def recursive_call(self, node, level): + self.emit('if (Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False) + self.emit('goto failed;', level + 1) + self.emit('}', level) + yield + self.emit('Py_LeaveRecursiveCall();', level) + def funcHeader(self, name): ctype = get_c_type(name) self.emit("int", 0) @@ -596,8 +605,9 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("%s val;" % ctype, depth+2) self.emit("PyObject *tmp2 = PyList_GET_ITEM(tmp, i);", depth+2) self.emit("Py_INCREF(tmp2);", depth+2) - self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % - field.type, depth+2, reflow=False) + with self.recursive_call(name, depth+2): + self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % + field.type, 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) @@ -610,8 +620,9 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("asdl_seq_SET(%s, i, val);" % field.name, depth+2) self.emit("}", depth+1) else: - self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % - (field.type, field.name), depth+1) + with self.recursive_call(name, depth+1): + self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % + (field.type, field.name), depth+1) self.emit("if (res != 0) goto failed;", depth+1) self.emit("Py_CLEAR(tmp);", depth+1) diff --git a/Parser/parser.c b/Parser/parser.c index 6958963dfa39cf..7e6f04898e1e3e 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -1,4 +1,4 @@ -// @generated by pegen.py from ./Grammar/python.gram +// @generated by pegen.py from python.gram #include "pegen.h" #if defined(Py_DEBUG) && defined(Py_BUILD_CORE) @@ -6,6 +6,8 @@ #else # define D(x) #endif + +# define MAXSTACK 6000 static const int n_keyword_lists = 9; static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, @@ -170,8 +172,8 @@ static char *soft_keywords[] = { #define star_expression_type 1096 #define star_named_expressions_type 1097 #define star_named_expression_type 1098 -#define named_expression_type 1099 -#define direct_named_expression_type 1100 +#define assignment_expression_type 1099 +#define named_expression_type 1100 #define annotated_rhs_type 1101 #define expressions_type 1102 #define expression_type 1103 @@ -247,251 +249,257 @@ static char *soft_keywords[] = { #define del_targets_type 1173 #define del_target_type 1174 #define del_t_atom_type 1175 -#define targets_type 1176 -#define target_type 1177 -#define t_primary_type 1178 // Left-recursive -#define t_lookahead_type 1179 -#define t_atom_type 1180 -#define invalid_arguments_type 1181 -#define invalid_kwarg_type 1182 -#define invalid_expression_type 1183 -#define invalid_named_expression_type 1184 -#define invalid_assignment_type 1185 -#define invalid_ann_assign_target_type 1186 -#define invalid_del_stmt_type 1187 -#define invalid_block_type 1188 -#define invalid_primary_type 1189 // Left-recursive -#define invalid_comprehension_type 1190 -#define invalid_dict_comprehension_type 1191 -#define invalid_parameters_type 1192 -#define invalid_parameters_helper_type 1193 -#define invalid_lambda_parameters_type 1194 -#define invalid_lambda_parameters_helper_type 1195 -#define invalid_star_etc_type 1196 -#define invalid_lambda_star_etc_type 1197 -#define invalid_double_type_comments_type 1198 -#define invalid_with_item_type 1199 -#define invalid_for_target_type 1200 -#define invalid_group_type 1201 -#define invalid_import_from_targets_type 1202 -#define invalid_with_stmt_type 1203 -#define invalid_with_stmt_indent_type 1204 -#define invalid_try_stmt_type 1205 -#define invalid_except_stmt_type 1206 -#define invalid_finally_stmt_type 1207 -#define invalid_except_stmt_indent_type 1208 -#define invalid_match_stmt_type 1209 -#define invalid_case_block_type 1210 -#define invalid_if_stmt_type 1211 -#define invalid_elif_stmt_type 1212 -#define invalid_else_stmt_type 1213 -#define invalid_while_stmt_type 1214 -#define invalid_for_stmt_type 1215 -#define invalid_def_raw_type 1216 -#define invalid_class_def_raw_type 1217 -#define invalid_double_starred_kvpairs_type 1218 -#define invalid_kvpair_type 1219 -#define _loop0_1_type 1220 -#define _loop0_2_type 1221 -#define _loop0_4_type 1222 -#define _gather_3_type 1223 -#define _loop0_6_type 1224 -#define _gather_5_type 1225 -#define _loop0_8_type 1226 -#define _gather_7_type 1227 -#define _loop0_10_type 1228 -#define _gather_9_type 1229 -#define _loop1_11_type 1230 -#define _loop0_13_type 1231 -#define _gather_12_type 1232 -#define _tmp_14_type 1233 -#define _tmp_15_type 1234 -#define _tmp_16_type 1235 -#define _tmp_17_type 1236 -#define _tmp_18_type 1237 -#define _tmp_19_type 1238 -#define _tmp_20_type 1239 -#define _tmp_21_type 1240 -#define _loop1_22_type 1241 -#define _tmp_23_type 1242 -#define _tmp_24_type 1243 -#define _loop0_26_type 1244 -#define _gather_25_type 1245 -#define _loop0_28_type 1246 -#define _gather_27_type 1247 -#define _tmp_29_type 1248 -#define _tmp_30_type 1249 -#define _loop0_31_type 1250 -#define _loop1_32_type 1251 -#define _loop0_34_type 1252 -#define _gather_33_type 1253 -#define _tmp_35_type 1254 -#define _loop0_37_type 1255 -#define _gather_36_type 1256 -#define _tmp_38_type 1257 -#define _loop0_40_type 1258 -#define _gather_39_type 1259 -#define _loop0_42_type 1260 -#define _gather_41_type 1261 -#define _loop0_44_type 1262 -#define _gather_43_type 1263 -#define _loop0_46_type 1264 -#define _gather_45_type 1265 -#define _tmp_47_type 1266 -#define _loop1_48_type 1267 -#define _tmp_49_type 1268 -#define _loop1_50_type 1269 -#define _loop0_52_type 1270 -#define _gather_51_type 1271 -#define _tmp_53_type 1272 -#define _tmp_54_type 1273 -#define _tmp_55_type 1274 -#define _tmp_56_type 1275 -#define _loop0_58_type 1276 -#define _gather_57_type 1277 -#define _loop0_60_type 1278 -#define _gather_59_type 1279 -#define _tmp_61_type 1280 -#define _loop0_63_type 1281 -#define _gather_62_type 1282 -#define _loop0_65_type 1283 -#define _gather_64_type 1284 -#define _tmp_66_type 1285 -#define _tmp_67_type 1286 -#define _tmp_68_type 1287 -#define _tmp_69_type 1288 -#define _loop0_70_type 1289 -#define _loop0_71_type 1290 -#define _loop0_72_type 1291 -#define _loop1_73_type 1292 -#define _loop0_74_type 1293 -#define _loop1_75_type 1294 -#define _loop1_76_type 1295 -#define _loop1_77_type 1296 -#define _loop0_78_type 1297 -#define _loop1_79_type 1298 -#define _loop0_80_type 1299 -#define _loop1_81_type 1300 -#define _loop0_82_type 1301 -#define _loop1_83_type 1302 -#define _loop1_84_type 1303 -#define _tmp_85_type 1304 -#define _loop1_86_type 1305 -#define _loop0_88_type 1306 -#define _gather_87_type 1307 -#define _loop1_89_type 1308 -#define _loop0_90_type 1309 -#define _loop0_91_type 1310 -#define _loop0_92_type 1311 -#define _loop1_93_type 1312 -#define _loop0_94_type 1313 -#define _loop1_95_type 1314 -#define _loop1_96_type 1315 -#define _loop1_97_type 1316 -#define _loop0_98_type 1317 -#define _loop1_99_type 1318 -#define _loop0_100_type 1319 -#define _loop1_101_type 1320 -#define _loop0_102_type 1321 -#define _loop1_103_type 1322 -#define _loop1_104_type 1323 -#define _loop1_105_type 1324 -#define _loop1_106_type 1325 -#define _tmp_107_type 1326 -#define _loop0_109_type 1327 -#define _gather_108_type 1328 -#define _tmp_110_type 1329 -#define _tmp_111_type 1330 -#define _tmp_112_type 1331 -#define _tmp_113_type 1332 -#define _loop1_114_type 1333 -#define _tmp_115_type 1334 -#define _tmp_116_type 1335 -#define _loop0_118_type 1336 -#define _gather_117_type 1337 -#define _loop1_119_type 1338 -#define _loop0_120_type 1339 -#define _loop0_121_type 1340 -#define _loop0_123_type 1341 -#define _gather_122_type 1342 -#define _tmp_124_type 1343 -#define _loop0_126_type 1344 -#define _gather_125_type 1345 -#define _loop0_128_type 1346 -#define _gather_127_type 1347 -#define _loop0_130_type 1348 -#define _gather_129_type 1349 -#define _loop0_132_type 1350 -#define _gather_131_type 1351 +#define t_primary_type 1176 // Left-recursive +#define t_lookahead_type 1177 +#define invalid_arguments_type 1178 +#define invalid_kwarg_type 1179 +#define expression_without_invalid_type 1180 +#define invalid_legacy_expression_type 1181 +#define invalid_expression_type 1182 +#define invalid_named_expression_type 1183 +#define invalid_assignment_type 1184 +#define invalid_ann_assign_target_type 1185 +#define invalid_del_stmt_type 1186 +#define invalid_block_type 1187 +#define invalid_comprehension_type 1188 +#define invalid_dict_comprehension_type 1189 +#define invalid_parameters_type 1190 +#define invalid_parameters_helper_type 1191 +#define invalid_lambda_parameters_type 1192 +#define invalid_lambda_parameters_helper_type 1193 +#define invalid_star_etc_type 1194 +#define invalid_lambda_star_etc_type 1195 +#define invalid_double_type_comments_type 1196 +#define invalid_with_item_type 1197 +#define invalid_for_target_type 1198 +#define invalid_group_type 1199 +#define invalid_import_from_targets_type 1200 +#define invalid_with_stmt_type 1201 +#define invalid_with_stmt_indent_type 1202 +#define invalid_try_stmt_type 1203 +#define invalid_except_stmt_type 1204 +#define invalid_finally_stmt_type 1205 +#define invalid_except_stmt_indent_type 1206 +#define invalid_match_stmt_type 1207 +#define invalid_case_block_type 1208 +#define invalid_as_pattern_type 1209 +#define invalid_class_pattern_type 1210 +#define invalid_class_argument_pattern_type 1211 +#define invalid_if_stmt_type 1212 +#define invalid_elif_stmt_type 1213 +#define invalid_else_stmt_type 1214 +#define invalid_while_stmt_type 1215 +#define invalid_for_stmt_type 1216 +#define invalid_def_raw_type 1217 +#define invalid_class_def_raw_type 1218 +#define invalid_double_starred_kvpairs_type 1219 +#define invalid_kvpair_type 1220 +#define _loop0_1_type 1221 +#define _loop0_2_type 1222 +#define _loop0_4_type 1223 +#define _gather_3_type 1224 +#define _loop0_6_type 1225 +#define _gather_5_type 1226 +#define _loop0_8_type 1227 +#define _gather_7_type 1228 +#define _loop0_10_type 1229 +#define _gather_9_type 1230 +#define _loop1_11_type 1231 +#define _loop0_13_type 1232 +#define _gather_12_type 1233 +#define _tmp_14_type 1234 +#define _tmp_15_type 1235 +#define _tmp_16_type 1236 +#define _tmp_17_type 1237 +#define _tmp_18_type 1238 +#define _tmp_19_type 1239 +#define _tmp_20_type 1240 +#define _tmp_21_type 1241 +#define _loop1_22_type 1242 +#define _tmp_23_type 1243 +#define _tmp_24_type 1244 +#define _loop0_26_type 1245 +#define _gather_25_type 1246 +#define _loop0_28_type 1247 +#define _gather_27_type 1248 +#define _tmp_29_type 1249 +#define _tmp_30_type 1250 +#define _loop0_31_type 1251 +#define _loop1_32_type 1252 +#define _loop0_34_type 1253 +#define _gather_33_type 1254 +#define _tmp_35_type 1255 +#define _loop0_37_type 1256 +#define _gather_36_type 1257 +#define _tmp_38_type 1258 +#define _loop0_40_type 1259 +#define _gather_39_type 1260 +#define _loop0_42_type 1261 +#define _gather_41_type 1262 +#define _loop0_44_type 1263 +#define _gather_43_type 1264 +#define _loop0_46_type 1265 +#define _gather_45_type 1266 +#define _tmp_47_type 1267 +#define _loop1_48_type 1268 +#define _tmp_49_type 1269 +#define _loop1_50_type 1270 +#define _loop0_52_type 1271 +#define _gather_51_type 1272 +#define _tmp_53_type 1273 +#define _tmp_54_type 1274 +#define _tmp_55_type 1275 +#define _tmp_56_type 1276 +#define _loop0_58_type 1277 +#define _gather_57_type 1278 +#define _loop0_60_type 1279 +#define _gather_59_type 1280 +#define _tmp_61_type 1281 +#define _loop0_63_type 1282 +#define _gather_62_type 1283 +#define _loop0_65_type 1284 +#define _gather_64_type 1285 +#define _tmp_66_type 1286 +#define _tmp_67_type 1287 +#define _tmp_68_type 1288 +#define _tmp_69_type 1289 +#define _loop0_70_type 1290 +#define _loop0_71_type 1291 +#define _loop0_72_type 1292 +#define _loop1_73_type 1293 +#define _loop0_74_type 1294 +#define _loop1_75_type 1295 +#define _loop1_76_type 1296 +#define _loop1_77_type 1297 +#define _loop0_78_type 1298 +#define _loop1_79_type 1299 +#define _loop0_80_type 1300 +#define _loop1_81_type 1301 +#define _loop0_82_type 1302 +#define _loop1_83_type 1303 +#define _loop1_84_type 1304 +#define _tmp_85_type 1305 +#define _loop1_86_type 1306 +#define _loop0_88_type 1307 +#define _gather_87_type 1308 +#define _loop1_89_type 1309 +#define _loop0_90_type 1310 +#define _loop0_91_type 1311 +#define _loop0_92_type 1312 +#define _loop1_93_type 1313 +#define _loop0_94_type 1314 +#define _loop1_95_type 1315 +#define _loop1_96_type 1316 +#define _loop1_97_type 1317 +#define _loop0_98_type 1318 +#define _loop1_99_type 1319 +#define _loop0_100_type 1320 +#define _loop1_101_type 1321 +#define _loop0_102_type 1322 +#define _loop1_103_type 1323 +#define _loop1_104_type 1324 +#define _loop1_105_type 1325 +#define _loop1_106_type 1326 +#define _tmp_107_type 1327 +#define _loop0_109_type 1328 +#define _gather_108_type 1329 +#define _tmp_110_type 1330 +#define _tmp_111_type 1331 +#define _tmp_112_type 1332 +#define _tmp_113_type 1333 +#define _loop1_114_type 1334 +#define _tmp_115_type 1335 +#define _tmp_116_type 1336 +#define _tmp_117_type 1337 +#define _loop0_119_type 1338 +#define _gather_118_type 1339 +#define _loop1_120_type 1340 +#define _loop0_121_type 1341 +#define _loop0_122_type 1342 +#define _loop0_124_type 1343 +#define _gather_123_type 1344 +#define _tmp_125_type 1345 +#define _loop0_127_type 1346 +#define _gather_126_type 1347 +#define _loop0_129_type 1348 +#define _gather_128_type 1349 +#define _loop0_131_type 1350 +#define _gather_130_type 1351 #define _loop0_133_type 1352 -#define _loop0_135_type 1353 -#define _gather_134_type 1354 -#define _loop1_136_type 1355 -#define _tmp_137_type 1356 -#define _loop0_139_type 1357 -#define _gather_138_type 1358 -#define _loop0_141_type 1359 -#define _gather_140_type 1360 -#define _tmp_142_type 1361 -#define _tmp_143_type 1362 -#define _tmp_144_type 1363 -#define _tmp_145_type 1364 -#define _tmp_146_type 1365 -#define _loop0_147_type 1366 -#define _loop0_148_type 1367 -#define _loop0_149_type 1368 -#define _tmp_150_type 1369 -#define _tmp_151_type 1370 -#define _tmp_152_type 1371 -#define _tmp_153_type 1372 -#define _loop0_154_type 1373 -#define _loop1_155_type 1374 -#define _loop0_156_type 1375 -#define _loop1_157_type 1376 -#define _tmp_158_type 1377 -#define _tmp_159_type 1378 -#define _tmp_160_type 1379 -#define _loop0_162_type 1380 -#define _gather_161_type 1381 -#define _loop0_164_type 1382 -#define _gather_163_type 1383 -#define _loop0_166_type 1384 -#define _gather_165_type 1385 -#define _loop0_168_type 1386 -#define _gather_167_type 1387 -#define _tmp_169_type 1388 -#define _tmp_170_type 1389 -#define _tmp_171_type 1390 -#define _tmp_172_type 1391 -#define _tmp_173_type 1392 -#define _loop0_175_type 1393 -#define _gather_174_type 1394 -#define _tmp_176_type 1395 -#define _tmp_177_type 1396 -#define _tmp_178_type 1397 -#define _tmp_179_type 1398 -#define _tmp_180_type 1399 -#define _tmp_181_type 1400 -#define _tmp_182_type 1401 -#define _tmp_183_type 1402 -#define _tmp_184_type 1403 -#define _tmp_185_type 1404 -#define _tmp_186_type 1405 -#define _tmp_187_type 1406 -#define _tmp_188_type 1407 -#define _tmp_189_type 1408 -#define _tmp_190_type 1409 -#define _tmp_191_type 1410 -#define _tmp_192_type 1411 -#define _tmp_193_type 1412 -#define _tmp_194_type 1413 -#define _tmp_195_type 1414 -#define _tmp_196_type 1415 -#define _tmp_197_type 1416 -#define _tmp_198_type 1417 -#define _tmp_199_type 1418 -#define _tmp_200_type 1419 -#define _tmp_201_type 1420 +#define _gather_132_type 1353 +#define _loop0_134_type 1354 +#define _loop0_136_type 1355 +#define _gather_135_type 1356 +#define _loop1_137_type 1357 +#define _tmp_138_type 1358 +#define _loop0_140_type 1359 +#define _gather_139_type 1360 +#define _tmp_141_type 1361 +#define _tmp_142_type 1362 +#define _tmp_143_type 1363 +#define _tmp_144_type 1364 +#define _tmp_145_type 1365 +#define _tmp_146_type 1366 +#define _tmp_147_type 1367 +#define _tmp_148_type 1368 +#define _loop0_149_type 1369 +#define _loop0_150_type 1370 +#define _loop0_151_type 1371 +#define _tmp_152_type 1372 +#define _tmp_153_type 1373 +#define _tmp_154_type 1374 +#define _tmp_155_type 1375 +#define _loop0_156_type 1376 +#define _loop1_157_type 1377 +#define _loop0_158_type 1378 +#define _loop1_159_type 1379 +#define _tmp_160_type 1380 +#define _tmp_161_type 1381 +#define _tmp_162_type 1382 +#define _loop0_164_type 1383 +#define _gather_163_type 1384 +#define _loop0_166_type 1385 +#define _gather_165_type 1386 +#define _loop0_168_type 1387 +#define _gather_167_type 1388 +#define _loop0_170_type 1389 +#define _gather_169_type 1390 +#define _tmp_171_type 1391 +#define _tmp_172_type 1392 +#define _tmp_173_type 1393 +#define _tmp_174_type 1394 +#define _tmp_175_type 1395 +#define _tmp_176_type 1396 +#define _tmp_177_type 1397 +#define _loop0_179_type 1398 +#define _gather_178_type 1399 +#define _tmp_180_type 1400 +#define _tmp_181_type 1401 +#define _tmp_182_type 1402 +#define _tmp_183_type 1403 +#define _tmp_184_type 1404 +#define _tmp_185_type 1405 +#define _tmp_186_type 1406 +#define _tmp_187_type 1407 +#define _tmp_188_type 1408 +#define _tmp_189_type 1409 +#define _tmp_190_type 1410 +#define _tmp_191_type 1411 +#define _tmp_192_type 1412 +#define _tmp_193_type 1413 +#define _tmp_194_type 1414 +#define _tmp_195_type 1415 +#define _tmp_196_type 1416 +#define _tmp_197_type 1417 +#define _tmp_198_type 1418 +#define _tmp_199_type 1419 +#define _tmp_200_type 1420 +#define _tmp_201_type 1421 +#define _tmp_202_type 1422 +#define _tmp_203_type 1423 +#define _tmp_204_type 1424 +#define _tmp_205_type 1425 +#define _tmp_206_type 1426 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -592,8 +600,8 @@ static expr_ty star_expressions_rule(Parser *p); static expr_ty star_expression_rule(Parser *p); static asdl_expr_seq* star_named_expressions_rule(Parser *p); static expr_ty star_named_expression_rule(Parser *p); +static expr_ty assignment_expression_rule(Parser *p); static expr_ty named_expression_rule(Parser *p); -static expr_ty direct_named_expression_rule(Parser *p); static expr_ty annotated_rhs_rule(Parser *p); static expr_ty expressions_rule(Parser *p); static expr_ty expression_rule(Parser *p); @@ -669,20 +677,18 @@ static expr_ty single_subscript_attribute_target_rule(Parser *p); static asdl_expr_seq* del_targets_rule(Parser *p); static expr_ty del_target_rule(Parser *p); static expr_ty del_t_atom_rule(Parser *p); -static asdl_expr_seq* targets_rule(Parser *p); -static expr_ty target_rule(Parser *p); static expr_ty t_primary_rule(Parser *p); static void *t_lookahead_rule(Parser *p); -static expr_ty t_atom_rule(Parser *p); static void *invalid_arguments_rule(Parser *p); static void *invalid_kwarg_rule(Parser *p); +static expr_ty expression_without_invalid_rule(Parser *p); +static void *invalid_legacy_expression_rule(Parser *p); static void *invalid_expression_rule(Parser *p); static void *invalid_named_expression_rule(Parser *p); static void *invalid_assignment_rule(Parser *p); static expr_ty invalid_ann_assign_target_rule(Parser *p); static void *invalid_del_stmt_rule(Parser *p); static void *invalid_block_rule(Parser *p); -static void *invalid_primary_rule(Parser *p); static void *invalid_comprehension_rule(Parser *p); static void *invalid_dict_comprehension_rule(Parser *p); static void *invalid_parameters_rule(Parser *p); @@ -704,6 +710,9 @@ static void *invalid_finally_stmt_rule(Parser *p); static void *invalid_except_stmt_indent_rule(Parser *p); static void *invalid_match_stmt_rule(Parser *p); static void *invalid_case_block_rule(Parser *p); +static void *invalid_as_pattern_rule(Parser *p); +static void *invalid_class_pattern_rule(Parser *p); +static asdl_pattern_seq* invalid_class_argument_pattern_rule(Parser *p); static void *invalid_if_stmt_rule(Parser *p); static void *invalid_elif_stmt_rule(Parser *p); static void *invalid_else_stmt_rule(Parser *p); @@ -829,69 +838,69 @@ static void *_tmp_113_rule(Parser *p); static asdl_seq *_loop1_114_rule(Parser *p); static void *_tmp_115_rule(Parser *p); static void *_tmp_116_rule(Parser *p); -static asdl_seq *_loop0_118_rule(Parser *p); -static asdl_seq *_gather_117_rule(Parser *p); -static asdl_seq *_loop1_119_rule(Parser *p); -static asdl_seq *_loop0_120_rule(Parser *p); +static void *_tmp_117_rule(Parser *p); +static asdl_seq *_loop0_119_rule(Parser *p); +static asdl_seq *_gather_118_rule(Parser *p); +static asdl_seq *_loop1_120_rule(Parser *p); static asdl_seq *_loop0_121_rule(Parser *p); -static asdl_seq *_loop0_123_rule(Parser *p); -static asdl_seq *_gather_122_rule(Parser *p); -static void *_tmp_124_rule(Parser *p); -static asdl_seq *_loop0_126_rule(Parser *p); -static asdl_seq *_gather_125_rule(Parser *p); -static asdl_seq *_loop0_128_rule(Parser *p); -static asdl_seq *_gather_127_rule(Parser *p); -static asdl_seq *_loop0_130_rule(Parser *p); -static asdl_seq *_gather_129_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); -static asdl_seq *_gather_131_rule(Parser *p); +static asdl_seq *_loop0_122_rule(Parser *p); +static asdl_seq *_loop0_124_rule(Parser *p); +static asdl_seq *_gather_123_rule(Parser *p); +static void *_tmp_125_rule(Parser *p); +static asdl_seq *_loop0_127_rule(Parser *p); +static asdl_seq *_gather_126_rule(Parser *p); +static asdl_seq *_loop0_129_rule(Parser *p); +static asdl_seq *_gather_128_rule(Parser *p); +static asdl_seq *_loop0_131_rule(Parser *p); +static asdl_seq *_gather_130_rule(Parser *p); static asdl_seq *_loop0_133_rule(Parser *p); -static asdl_seq *_loop0_135_rule(Parser *p); -static asdl_seq *_gather_134_rule(Parser *p); -static asdl_seq *_loop1_136_rule(Parser *p); -static void *_tmp_137_rule(Parser *p); -static asdl_seq *_loop0_139_rule(Parser *p); -static asdl_seq *_gather_138_rule(Parser *p); -static asdl_seq *_loop0_141_rule(Parser *p); -static asdl_seq *_gather_140_rule(Parser *p); +static asdl_seq *_gather_132_rule(Parser *p); +static asdl_seq *_loop0_134_rule(Parser *p); +static asdl_seq *_loop0_136_rule(Parser *p); +static asdl_seq *_gather_135_rule(Parser *p); +static asdl_seq *_loop1_137_rule(Parser *p); +static void *_tmp_138_rule(Parser *p); +static asdl_seq *_loop0_140_rule(Parser *p); +static asdl_seq *_gather_139_rule(Parser *p); +static void *_tmp_141_rule(Parser *p); static void *_tmp_142_rule(Parser *p); static void *_tmp_143_rule(Parser *p); static void *_tmp_144_rule(Parser *p); static void *_tmp_145_rule(Parser *p); static void *_tmp_146_rule(Parser *p); -static asdl_seq *_loop0_147_rule(Parser *p); -static asdl_seq *_loop0_148_rule(Parser *p); +static void *_tmp_147_rule(Parser *p); +static void *_tmp_148_rule(Parser *p); static asdl_seq *_loop0_149_rule(Parser *p); -static void *_tmp_150_rule(Parser *p); -static void *_tmp_151_rule(Parser *p); +static asdl_seq *_loop0_150_rule(Parser *p); +static asdl_seq *_loop0_151_rule(Parser *p); static void *_tmp_152_rule(Parser *p); static void *_tmp_153_rule(Parser *p); -static asdl_seq *_loop0_154_rule(Parser *p); -static asdl_seq *_loop1_155_rule(Parser *p); +static void *_tmp_154_rule(Parser *p); +static void *_tmp_155_rule(Parser *p); static asdl_seq *_loop0_156_rule(Parser *p); static asdl_seq *_loop1_157_rule(Parser *p); -static void *_tmp_158_rule(Parser *p); -static void *_tmp_159_rule(Parser *p); +static asdl_seq *_loop0_158_rule(Parser *p); +static asdl_seq *_loop1_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); -static asdl_seq *_loop0_162_rule(Parser *p); -static asdl_seq *_gather_161_rule(Parser *p); +static void *_tmp_161_rule(Parser *p); +static void *_tmp_162_rule(Parser *p); static asdl_seq *_loop0_164_rule(Parser *p); static asdl_seq *_gather_163_rule(Parser *p); static asdl_seq *_loop0_166_rule(Parser *p); static asdl_seq *_gather_165_rule(Parser *p); static asdl_seq *_loop0_168_rule(Parser *p); static asdl_seq *_gather_167_rule(Parser *p); -static void *_tmp_169_rule(Parser *p); -static void *_tmp_170_rule(Parser *p); +static asdl_seq *_loop0_170_rule(Parser *p); +static asdl_seq *_gather_169_rule(Parser *p); static void *_tmp_171_rule(Parser *p); static void *_tmp_172_rule(Parser *p); static void *_tmp_173_rule(Parser *p); -static asdl_seq *_loop0_175_rule(Parser *p); -static asdl_seq *_gather_174_rule(Parser *p); +static void *_tmp_174_rule(Parser *p); +static void *_tmp_175_rule(Parser *p); static void *_tmp_176_rule(Parser *p); static void *_tmp_177_rule(Parser *p); -static void *_tmp_178_rule(Parser *p); -static void *_tmp_179_rule(Parser *p); +static asdl_seq *_loop0_179_rule(Parser *p); +static asdl_seq *_gather_178_rule(Parser *p); static void *_tmp_180_rule(Parser *p); static void *_tmp_181_rule(Parser *p); static void *_tmp_182_rule(Parser *p); @@ -914,29 +923,37 @@ static void *_tmp_198_rule(Parser *p); static void *_tmp_199_rule(Parser *p); static void *_tmp_200_rule(Parser *p); static void *_tmp_201_rule(Parser *p); +static void *_tmp_202_rule(Parser *p); +static void *_tmp_203_rule(Parser *p); +static void *_tmp_204_rule(Parser *p); +static void *_tmp_205_rule(Parser *p); +static void *_tmp_206_rule(Parser *p); // file: statements? $ static mod_ty file_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statements? $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> file[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statements? $")); void *a; Token * endmarker_var; if ( - (a = statements_rule(p), 1) // statements? + (a = statements_rule(p), !p->error_indicator) // statements? && (endmarker_var = _PyPegen_expect_token(p, ENDMARKER)) // token='ENDMARKER' ) @@ -945,7 +962,7 @@ file_rule(Parser *p) _res = _PyPegen_make_module ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -956,7 +973,7 @@ file_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -964,16 +981,19 @@ file_rule(Parser *p) static mod_ty interactive_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // statement_newline if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> interactive[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement_newline")); @@ -986,7 +1006,7 @@ interactive_rule(Parser *p) _res = _PyAST_Interactive ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -997,7 +1017,7 @@ interactive_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1005,16 +1025,19 @@ interactive_rule(Parser *p) static mod_ty eval_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // expressions NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eval[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions NEWLINE* $")); @@ -1033,7 +1056,7 @@ eval_rule(Parser *p) _res = _PyAST_Expression ( a , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1044,7 +1067,7 @@ eval_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1052,16 +1075,19 @@ eval_rule(Parser *p) static mod_ty func_type_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } mod_ty _res = NULL; int _mark = p->mark; { // '(' type_expressions? ')' '->' expression NEWLINE* $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' type_expressions? ')' '->' expression NEWLINE* $")); @@ -1075,7 +1101,7 @@ func_type_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = type_expressions_rule(p), 1) // type_expressions? + (a = type_expressions_rule(p), !p->error_indicator) // type_expressions? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -1092,7 +1118,7 @@ func_type_rule(Parser *p) _res = _PyAST_FunctionType ( a , b , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1103,7 +1129,7 @@ func_type_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1111,16 +1137,19 @@ func_type_rule(Parser *p) static expr_ty fstring_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> fstring[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1139,7 +1168,7 @@ fstring_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1154,16 +1183,19 @@ fstring_rule(Parser *p) static asdl_expr_seq* type_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.expression+ ',' '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression ',' '**' expression")); @@ -1194,7 +1226,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq * , _PyPegen_seq_append_to_end ( p , a , b ) ) , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1205,7 +1237,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '*' expression")); @@ -1227,7 +1259,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1238,7 +1270,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+ ',' '**' expression")); @@ -1260,7 +1292,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1271,7 +1303,7 @@ type_expressions_rule(Parser *p) } { // '*' expression ',' '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression ',' '**' expression")); @@ -1296,7 +1328,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_seq_append_to_end ( p , CHECK ( asdl_seq * , _PyPegen_singleton_seq ( p , a ) ) , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1307,7 +1339,7 @@ type_expressions_rule(Parser *p) } { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -1323,7 +1355,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1334,7 +1366,7 @@ type_expressions_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -1350,7 +1382,7 @@ type_expressions_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1361,7 +1393,7 @@ type_expressions_rule(Parser *p) } { // ','.expression+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -1374,7 +1406,7 @@ type_expressions_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1385,7 +1417,7 @@ type_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1393,16 +1425,19 @@ type_expressions_rule(Parser *p) static asdl_stmt_seq* statements_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // statement+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1415,7 +1450,7 @@ statements_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_seq_flatten ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1426,7 +1461,7 @@ statements_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1434,16 +1469,19 @@ statements_rule(Parser *p) static asdl_stmt_seq* statement_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // compound_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt")); @@ -1456,7 +1494,7 @@ statement_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1467,7 +1505,7 @@ statement_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1480,7 +1518,7 @@ statement_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1491,7 +1529,7 @@ statement_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1499,16 +1537,19 @@ statement_rule(Parser *p) static asdl_stmt_seq* statement_newline_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1517,7 +1558,7 @@ statement_newline_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // compound_stmt NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compound_stmt NEWLINE")); @@ -1533,7 +1574,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1544,7 +1585,7 @@ statement_newline_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -1563,7 +1604,7 @@ statement_newline_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -1575,7 +1616,7 @@ statement_newline_rule(Parser *p) D(fprintf(stderr, "%*c+ statement_newline[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1585,7 +1626,7 @@ statement_newline_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , CHECK ( stmt_ty , _PyAST_Pass ( EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1596,7 +1637,7 @@ statement_newline_rule(Parser *p) } { // $ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> statement_newline[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "$")); @@ -1609,7 +1650,7 @@ statement_newline_rule(Parser *p) _res = _PyPegen_interactive_exit ( p ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1620,7 +1661,7 @@ statement_newline_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1628,16 +1669,19 @@ statement_newline_rule(Parser *p) static asdl_stmt_seq* simple_stmts_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; { // simple_stmt !';' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt !';' NEWLINE")); @@ -1655,7 +1699,7 @@ simple_stmts_rule(Parser *p) _res = ( asdl_stmt_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1666,7 +1710,7 @@ simple_stmts_rule(Parser *p) } { // ';'.simple_stmt+ ';'? NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmts[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'.simple_stmt+ ';'? NEWLINE")); @@ -1677,7 +1721,7 @@ simple_stmts_rule(Parser *p) if ( (a = (asdl_stmt_seq*)_gather_12_rule(p)) // ';'.simple_stmt+ && - (_opt_var = _PyPegen_expect_token(p, 13), 1) // ';'? + (_opt_var = _PyPegen_expect_token(p, 13), !p->error_indicator) // ';'? && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -1686,7 +1730,7 @@ simple_stmts_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1697,7 +1741,7 @@ simple_stmts_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -1718,20 +1762,23 @@ simple_stmts_rule(Parser *p) static stmt_ty simple_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; if (_PyPegen_is_memoized(p, simple_stmt_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -1740,7 +1787,7 @@ simple_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment")); @@ -1759,7 +1806,7 @@ simple_stmt_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -1771,7 +1818,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1781,7 +1828,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Expr ( e , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1792,7 +1839,7 @@ simple_stmt_rule(Parser *p) } { // &'return' return_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'return' return_stmt")); @@ -1813,7 +1860,7 @@ simple_stmt_rule(Parser *p) } { // &('import' | 'from') import_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); @@ -1834,7 +1881,7 @@ simple_stmt_rule(Parser *p) } { // &'raise' raise_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'raise' raise_stmt")); @@ -1855,7 +1902,7 @@ simple_stmt_rule(Parser *p) } { // 'pass' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'pass'")); @@ -1867,7 +1914,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'pass'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1877,7 +1924,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Pass ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1888,7 +1935,7 @@ simple_stmt_rule(Parser *p) } { // &'del' del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'del' del_stmt")); @@ -1909,7 +1956,7 @@ simple_stmt_rule(Parser *p) } { // &'yield' yield_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'yield' yield_stmt")); @@ -1930,7 +1977,7 @@ simple_stmt_rule(Parser *p) } { // &'assert' assert_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'assert' assert_stmt")); @@ -1951,7 +1998,7 @@ simple_stmt_rule(Parser *p) } { // 'break' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'break'")); @@ -1963,7 +2010,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'break'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -1973,7 +2020,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Break ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -1984,7 +2031,7 @@ simple_stmt_rule(Parser *p) } { // 'continue' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'continue'")); @@ -1996,7 +2043,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'continue'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2006,7 +2053,7 @@ simple_stmt_rule(Parser *p) _res = _PyAST_Continue ( EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2017,7 +2064,7 @@ simple_stmt_rule(Parser *p) } { // &'global' global_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'global' global_stmt")); @@ -2038,7 +2085,7 @@ simple_stmt_rule(Parser *p) } { // &'nonlocal' nonlocal_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'nonlocal' nonlocal_stmt")); @@ -2060,7 +2107,7 @@ simple_stmt_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, simple_stmt_type, _res); - D(p->level--); + p->level--; return _res; } @@ -2076,16 +2123,19 @@ simple_stmt_rule(Parser *p) static stmt_ty compound_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // &('def' | '@' | ASYNC) function_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | ASYNC) function_def")); @@ -2106,7 +2156,7 @@ compound_stmt_rule(Parser *p) } { // &'if' if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); @@ -2127,7 +2177,7 @@ compound_stmt_rule(Parser *p) } { // &('class' | '@') class_def if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); @@ -2148,7 +2198,7 @@ compound_stmt_rule(Parser *p) } { // &('with' | ASYNC) with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | ASYNC) with_stmt")); @@ -2169,7 +2219,7 @@ compound_stmt_rule(Parser *p) } { // &('for' | ASYNC) for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | ASYNC) for_stmt")); @@ -2190,7 +2240,7 @@ compound_stmt_rule(Parser *p) } { // &'try' try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); @@ -2211,7 +2261,7 @@ compound_stmt_rule(Parser *p) } { // &'while' while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); @@ -2232,7 +2282,7 @@ compound_stmt_rule(Parser *p) } { // match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "match_stmt")); @@ -2251,7 +2301,7 @@ compound_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2264,16 +2314,19 @@ compound_stmt_rule(Parser *p) static stmt_ty assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2282,7 +2335,7 @@ assignment_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2297,13 +2350,13 @@ assignment_rule(Parser *p) && (b = expression_rule(p)) // expression && - (c = _tmp_19_rule(p), 1) // ['=' annotated_rhs] + (c = _tmp_19_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2313,7 +2366,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotation syntax is" , _PyAST_AnnAssign ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , c , 1 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2324,7 +2377,7 @@ assignment_rule(Parser *p) } { // ('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2339,13 +2392,13 @@ assignment_rule(Parser *p) && (b = expression_rule(p)) // expression && - (c = _tmp_21_rule(p), 1) // ['=' annotated_rhs] + (c = _tmp_21_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2355,7 +2408,7 @@ assignment_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 6 , "Variable annotations syntax is" , _PyAST_AnnAssign ( a , b , c , 0 , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2366,7 +2419,7 @@ assignment_rule(Parser *p) } { // ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); @@ -2380,13 +2433,13 @@ assignment_rule(Parser *p) && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2396,7 +2449,7 @@ assignment_rule(Parser *p) _res = _PyAST_Assign ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2407,7 +2460,7 @@ assignment_rule(Parser *p) } { // single_target augassign ~ (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); @@ -2428,7 +2481,7 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2438,7 +2491,7 @@ assignment_rule(Parser *p) _res = _PyAST_AugAssign ( a , b -> kind , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2447,13 +2500,13 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_assignment if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_assignment")); @@ -2472,7 +2525,7 @@ assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2493,16 +2546,19 @@ assignment_rule(Parser *p) static AugOperator* augassign_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } AugOperator* _res = NULL; int _mark = p->mark; { // '+=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+='")); @@ -2515,7 +2571,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Add ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2526,7 +2582,7 @@ augassign_rule(Parser *p) } { // '-=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-='")); @@ -2539,7 +2595,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Sub ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2550,7 +2606,7 @@ augassign_rule(Parser *p) } { // '*=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*='")); @@ -2563,7 +2619,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mult ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2574,7 +2630,7 @@ augassign_rule(Parser *p) } { // '@=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@='")); @@ -2587,7 +2643,7 @@ augassign_rule(Parser *p) _res = CHECK_VERSION ( AugOperator * , 5 , "The '@' operator is" , _PyPegen_augoperator ( p , MatMult ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2598,7 +2654,7 @@ augassign_rule(Parser *p) } { // '/=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/='")); @@ -2611,7 +2667,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Div ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2622,7 +2678,7 @@ augassign_rule(Parser *p) } { // '%=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%='")); @@ -2635,7 +2691,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Mod ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2646,7 +2702,7 @@ augassign_rule(Parser *p) } { // '&=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'&='")); @@ -2659,7 +2715,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitAnd ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2670,7 +2726,7 @@ augassign_rule(Parser *p) } { // '|=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|='")); @@ -2683,7 +2739,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitOr ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2694,7 +2750,7 @@ augassign_rule(Parser *p) } { // '^=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'^='")); @@ -2707,7 +2763,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , BitXor ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2718,7 +2774,7 @@ augassign_rule(Parser *p) } { // '<<=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<<='")); @@ -2731,7 +2787,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , LShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2742,7 +2798,7 @@ augassign_rule(Parser *p) } { // '>>=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>>='")); @@ -2755,7 +2811,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , RShift ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2766,7 +2822,7 @@ augassign_rule(Parser *p) } { // '**=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**='")); @@ -2779,7 +2835,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , Pow ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2790,7 +2846,7 @@ augassign_rule(Parser *p) } { // '//=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> augassign[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//='")); @@ -2803,7 +2859,7 @@ augassign_rule(Parser *p) _res = _PyPegen_augoperator ( p , FloorDiv ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2814,7 +2870,7 @@ augassign_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2822,16 +2878,19 @@ augassign_rule(Parser *p) static stmt_ty global_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2840,7 +2899,7 @@ global_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'global' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> global_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -2855,7 +2914,7 @@ global_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2865,7 +2924,7 @@ global_stmt_rule(Parser *p) _res = _PyAST_Global ( CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2876,7 +2935,7 @@ global_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2884,16 +2943,19 @@ global_stmt_rule(Parser *p) static stmt_ty nonlocal_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2902,7 +2964,7 @@ nonlocal_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'nonlocal' ','.NAME+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> nonlocal_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -2917,7 +2979,7 @@ nonlocal_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2927,7 +2989,7 @@ nonlocal_stmt_rule(Parser *p) _res = _PyAST_Nonlocal ( CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2938,7 +3000,7 @@ nonlocal_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -2946,16 +3008,19 @@ nonlocal_stmt_rule(Parser *p) static stmt_ty yield_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -2964,7 +3029,7 @@ yield_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -2976,7 +3041,7 @@ yield_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -2986,7 +3051,7 @@ yield_stmt_rule(Parser *p) _res = _PyAST_Expr ( y , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -2997,7 +3062,7 @@ yield_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3005,16 +3070,19 @@ yield_stmt_rule(Parser *p) static stmt_ty assert_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3023,7 +3091,7 @@ assert_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'assert' expression [',' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -3035,13 +3103,13 @@ assert_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_29_rule(p), 1) // [',' expression] + (b = _tmp_29_rule(p), !p->error_indicator) // [',' expression] ) { D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3051,7 +3119,7 @@ assert_stmt_rule(Parser *p) _res = _PyAST_Assert ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3062,7 +3130,7 @@ assert_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3070,16 +3138,19 @@ assert_stmt_rule(Parser *p) static stmt_ty del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3088,7 +3159,7 @@ del_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'del' del_targets &(';' | NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -3105,7 +3176,7 @@ del_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3115,7 +3186,7 @@ del_stmt_rule(Parser *p) _res = _PyAST_Delete ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3126,7 +3197,7 @@ del_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_del_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_del_stmt")); @@ -3145,7 +3216,7 @@ del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3153,16 +3224,19 @@ del_stmt_rule(Parser *p) static stmt_ty import_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // import_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_name")); @@ -3181,7 +3255,7 @@ import_stmt_rule(Parser *p) } { // import_from if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from")); @@ -3200,7 +3274,7 @@ import_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3208,16 +3282,19 @@ import_stmt_rule(Parser *p) static stmt_ty import_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3226,7 +3303,7 @@ import_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'import' dotted_as_names if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); @@ -3241,7 +3318,7 @@ import_name_rule(Parser *p) D(fprintf(stderr, "%*c+ import_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import' dotted_as_names")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3251,7 +3328,7 @@ import_name_rule(Parser *p) _res = _PyAST_Import ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3262,7 +3339,7 @@ import_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3272,16 +3349,19 @@ import_name_rule(Parser *p) static stmt_ty import_from_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3290,7 +3370,7 @@ import_from_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'from' (('.' | '...'))* dotted_name 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); @@ -3314,7 +3394,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))* dotted_name 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3324,7 +3404,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3335,7 +3415,7 @@ import_from_rule(Parser *p) } { // 'from' (('.' | '...'))+ 'import' import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); @@ -3356,7 +3436,7 @@ import_from_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' (('.' | '...'))+ 'import' import_from_targets")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3366,7 +3446,7 @@ import_from_rule(Parser *p) _res = _PyAST_ImportFrom ( NULL , b , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3377,7 +3457,7 @@ import_from_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3389,16 +3469,19 @@ import_from_rule(Parser *p) static asdl_alias_seq* import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3407,7 +3490,7 @@ import_from_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' import_from_as_names ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' import_from_as_names ','? ')'")); @@ -3421,7 +3504,7 @@ import_from_targets_rule(Parser *p) && (a = import_from_as_names_rule(p)) // import_from_as_names && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -3430,7 +3513,7 @@ import_from_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3441,7 +3524,7 @@ import_from_targets_rule(Parser *p) } { // import_from_as_names !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names !','")); @@ -3462,7 +3545,7 @@ import_from_targets_rule(Parser *p) } { // '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); @@ -3474,7 +3557,7 @@ import_from_targets_rule(Parser *p) D(fprintf(stderr, "%*c+ import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3484,7 +3567,7 @@ import_from_targets_rule(Parser *p) _res = ( asdl_alias_seq * ) _PyPegen_singleton_seq ( p , CHECK ( alias_ty , _PyPegen_alias_for_star ( p , EXTRA ) ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3495,7 +3578,7 @@ import_from_targets_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_import_from_targets if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_import_from_targets")); @@ -3514,7 +3597,7 @@ import_from_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3522,16 +3605,19 @@ import_from_targets_rule(Parser *p) static asdl_alias_seq* import_from_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.import_from_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3544,7 +3630,7 @@ import_from_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3555,7 +3641,7 @@ import_from_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3563,16 +3649,19 @@ import_from_as_names_rule(Parser *p) static alias_ty import_from_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3581,7 +3670,7 @@ import_from_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> import_from_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3590,13 +3679,13 @@ import_from_as_name_rule(Parser *p) if ( (a = _PyPegen_name_token(p)) // NAME && - (b = _tmp_35_rule(p), 1) // ['as' NAME] + (b = _tmp_35_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3606,7 +3695,7 @@ import_from_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3617,7 +3706,7 @@ import_from_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3625,16 +3714,19 @@ import_from_as_name_rule(Parser *p) static asdl_alias_seq* dotted_as_names_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_alias_seq* _res = NULL; int _mark = p->mark; { // ','.dotted_as_name+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3647,7 +3739,7 @@ dotted_as_names_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3658,7 +3750,7 @@ dotted_as_names_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3666,16 +3758,19 @@ dotted_as_names_rule(Parser *p) static alias_ty dotted_as_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } alias_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3684,7 +3779,7 @@ dotted_as_name_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // dotted_name ['as' NAME] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_as_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -3693,13 +3788,13 @@ dotted_as_name_rule(Parser *p) if ( (a = dotted_name_rule(p)) // dotted_name && - (b = _tmp_38_rule(p), 1) // ['as' NAME] + (b = _tmp_38_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3709,7 +3804,7 @@ dotted_as_name_rule(Parser *p) _res = _PyAST_alias ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Name . id : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3720,7 +3815,7 @@ dotted_as_name_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3730,10 +3825,13 @@ static expr_ty dotted_name_raw(Parser *); static expr_ty dotted_name_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, dotted_name_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -3741,35 +3839,42 @@ dotted_name_rule(Parser *p) while (1) { int tmpvar_0 = _PyPegen_update_memo(p, _mark, dotted_name_type, _res); if (tmpvar_0) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = dotted_name_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty dotted_name_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // dotted_name '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name '.' NAME")); @@ -3788,7 +3893,7 @@ dotted_name_raw(Parser *p) _res = _PyPegen_join_names_with_dot ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3799,7 +3904,7 @@ dotted_name_raw(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dotted_name[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -3818,7 +3923,7 @@ dotted_name_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3829,16 +3934,19 @@ dotted_name_raw(Parser *p) static stmt_ty if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3847,7 +3955,7 @@ if_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_if_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_if_stmt")); @@ -3866,7 +3974,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); @@ -3890,7 +3998,7 @@ if_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3900,7 +4008,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq * , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3911,7 +4019,7 @@ if_stmt_rule(Parser *p) } { // 'if' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); @@ -3929,13 +4037,13 @@ if_stmt_rule(Parser *p) && (b = block_rule(p)) // block && - (c = else_block_rule(p), 1) // else_block? + (c = else_block_rule(p), !p->error_indicator) // else_block? ) { D(fprintf(stderr, "%*c+ if_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -3945,7 +4053,7 @@ if_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -3956,7 +4064,7 @@ if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -3967,16 +4075,19 @@ if_stmt_rule(Parser *p) static stmt_ty elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -3985,7 +4096,7 @@ elif_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_elif_stmt")); @@ -4004,7 +4115,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block elif_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); @@ -4028,7 +4139,7 @@ elif_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block elif_stmt")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4038,7 +4149,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , CHECK ( asdl_stmt_seq * , _PyPegen_singleton_seq ( p , c ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4049,7 +4160,7 @@ elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); @@ -4067,13 +4178,13 @@ elif_stmt_rule(Parser *p) && (b = block_rule(p)) // block && - (c = else_block_rule(p), 1) // else_block? + (c = else_block_rule(p), !p->error_indicator) // else_block? ) { D(fprintf(stderr, "%*c+ elif_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4083,7 +4194,7 @@ elif_stmt_rule(Parser *p) _res = _PyAST_If ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4094,7 +4205,7 @@ elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4102,16 +4213,19 @@ elif_stmt_rule(Parser *p) static asdl_stmt_seq* else_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_else_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_else_stmt")); @@ -4130,7 +4244,7 @@ else_block_rule(Parser *p) } { // 'else' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> else_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' &&':' block")); @@ -4149,7 +4263,7 @@ else_block_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4160,7 +4274,7 @@ else_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4168,16 +4282,19 @@ else_block_rule(Parser *p) static stmt_ty while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4186,7 +4303,7 @@ while_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_while_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_while_stmt")); @@ -4205,7 +4322,7 @@ while_stmt_rule(Parser *p) } { // 'while' named_expression ':' block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); @@ -4223,13 +4340,13 @@ while_stmt_rule(Parser *p) && (b = block_rule(p)) // block && - (c = else_block_rule(p), 1) // else_block? + (c = else_block_rule(p), !p->error_indicator) // else_block? ) { D(fprintf(stderr, "%*c+ while_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4239,7 +4356,7 @@ while_stmt_rule(Parser *p) _res = _PyAST_While ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4250,7 +4367,7 @@ while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4262,16 +4379,19 @@ while_stmt_rule(Parser *p) static stmt_ty for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4280,7 +4400,7 @@ for_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_for_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_stmt")); @@ -4299,7 +4419,7 @@ for_stmt_rule(Parser *p) } { // 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -4325,17 +4445,17 @@ for_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && (b = block_rule(p)) // block && - (el = else_block_rule(p), 1) // else_block? + (el = else_block_rule(p), !p->error_indicator) // else_block? ) { D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4345,7 +4465,7 @@ for_stmt_rule(Parser *p) _res = _PyAST_For ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4354,13 +4474,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); @@ -4389,17 +4509,17 @@ for_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && (b = block_rule(p)) // block && - (el = else_block_rule(p), 1) // else_block? + (el = else_block_rule(p), !p->error_indicator) // else_block? ) { D(fprintf(stderr, "%*c+ for_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4409,7 +4529,7 @@ for_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async for loops are" , _PyAST_AsyncFor ( t , ex , b , el , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4418,13 +4538,13 @@ for_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s for_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ star_expressions &&':' TYPE_COMMENT? block else_block?")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -4443,7 +4563,7 @@ for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4457,16 +4577,19 @@ for_stmt_rule(Parser *p) static stmt_ty with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4475,7 +4598,7 @@ with_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_with_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt_indent")); @@ -4494,7 +4617,7 @@ with_stmt_rule(Parser *p) } { // 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4513,7 +4636,7 @@ with_stmt_rule(Parser *p) && (a = (asdl_withitem_seq*)_gather_39_rule(p)) // ','.with_item+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -4525,7 +4648,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4535,7 +4658,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4546,7 +4669,7 @@ with_stmt_rule(Parser *p) } { // 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4562,7 +4685,7 @@ with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && (b = block_rule(p)) // block ) @@ -4570,7 +4693,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4580,7 +4703,7 @@ with_stmt_rule(Parser *p) _res = _PyAST_With ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4591,7 +4714,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); @@ -4613,7 +4736,7 @@ with_stmt_rule(Parser *p) && (a = (asdl_withitem_seq*)_gather_43_rule(p)) // ','.with_item+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -4625,7 +4748,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4635,7 +4758,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NULL , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4646,7 +4769,7 @@ with_stmt_rule(Parser *p) } { // ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); @@ -4665,7 +4788,7 @@ with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && (b = block_rule(p)) // block ) @@ -4673,7 +4796,7 @@ with_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'with' ','.with_item+ ':' TYPE_COMMENT? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4683,7 +4806,7 @@ with_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async with statements are" , _PyAST_AsyncWith ( a , b , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4694,7 +4817,7 @@ with_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_stmt")); @@ -4713,7 +4836,7 @@ with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4724,16 +4847,19 @@ with_stmt_rule(Parser *p) static withitem_ty with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } withitem_ty _res = NULL; int _mark = p->mark; { // expression 'as' star_target &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -4754,7 +4880,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , t , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4765,7 +4891,7 @@ with_item_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_with_item")); @@ -4784,7 +4910,7 @@ with_item_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -4797,7 +4923,7 @@ with_item_rule(Parser *p) _res = _PyAST_withitem ( e , NULL , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4808,7 +4934,7 @@ with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4819,16 +4945,19 @@ with_item_rule(Parser *p) static stmt_ty try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4837,7 +4966,7 @@ try_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_try_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_try_stmt")); @@ -4856,7 +4985,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block finally_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); @@ -4877,7 +5006,7 @@ try_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block finally_block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4887,7 +5016,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , NULL , NULL , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4898,7 +5027,7 @@ try_stmt_rule(Parser *p) } { // 'try' &&':' block except_block+ else_block? finally_block? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); @@ -4917,15 +5046,15 @@ try_stmt_rule(Parser *p) && (ex = (asdl_excepthandler_seq*)_loop1_48_rule(p)) // except_block+ && - (el = else_block_rule(p), 1) // else_block? + (el = else_block_rule(p), !p->error_indicator) // else_block? && - (f = finally_block_rule(p), 1) // finally_block? + (f = finally_block_rule(p), !p->error_indicator) // finally_block? ) { D(fprintf(stderr, "%*c+ try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' &&':' block except_block+ else_block? finally_block?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -4935,7 +5064,7 @@ try_stmt_rule(Parser *p) _res = _PyAST_Try ( b , ex , el , f , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -4946,7 +5075,7 @@ try_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -4958,16 +5087,19 @@ try_stmt_rule(Parser *p) static excepthandler_ty except_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } excepthandler_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -4976,7 +5108,7 @@ except_block_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_except_stmt_indent if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt_indent")); @@ -4995,7 +5127,7 @@ except_block_rule(Parser *p) } { // 'except' expression ['as' NAME] ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); @@ -5009,7 +5141,7 @@ except_block_rule(Parser *p) && (e = expression_rule(p)) // expression && - (t = _tmp_49_rule(p), 1) // ['as' NAME] + (t = _tmp_49_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -5019,7 +5151,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5029,7 +5161,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( e , ( t ) ? ( ( expr_ty ) t ) -> v . Name . id : NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5040,7 +5172,7 @@ except_block_rule(Parser *p) } { // 'except' ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); @@ -5058,7 +5190,7 @@ except_block_rule(Parser *p) D(fprintf(stderr, "%*c+ except_block[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5068,7 +5200,7 @@ except_block_rule(Parser *p) _res = _PyAST_ExceptHandler ( NULL , NULL , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5079,7 +5211,7 @@ except_block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_except_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> except_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_except_stmt")); @@ -5098,7 +5230,7 @@ except_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5106,16 +5238,19 @@ except_block_rule(Parser *p) static asdl_stmt_seq* finally_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_finally_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_finally_stmt")); @@ -5134,7 +5269,7 @@ finally_block_rule(Parser *p) } { // 'finally' &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> finally_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' &&':' block")); @@ -5153,7 +5288,7 @@ finally_block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5164,7 +5299,7 @@ finally_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5174,16 +5309,19 @@ finally_block_rule(Parser *p) static stmt_ty match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5192,7 +5330,7 @@ match_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); @@ -5222,7 +5360,7 @@ match_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE INDENT case_block+ DEDENT")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5232,7 +5370,7 @@ match_stmt_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5243,7 +5381,7 @@ match_stmt_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_match_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_match_stmt")); @@ -5262,7 +5400,7 @@ match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5270,16 +5408,19 @@ match_stmt_rule(Parser *p) static expr_ty subject_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5288,7 +5429,7 @@ subject_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -5300,13 +5441,13 @@ subject_expr_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (values = star_named_expressions_rule(p), 1) // star_named_expressions? + (values = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { D(fprintf(stderr, "%*c+ subject_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5316,7 +5457,7 @@ subject_expr_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , value , values ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5327,7 +5468,7 @@ subject_expr_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> subject_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -5346,7 +5487,7 @@ subject_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5354,16 +5495,19 @@ subject_expr_rule(Parser *p) static match_case_ty case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } match_case_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_case_block")); @@ -5382,7 +5526,7 @@ case_block_rule(Parser *p) } { // "case" patterns guard? ':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block")); @@ -5396,7 +5540,7 @@ case_block_rule(Parser *p) && (pattern = patterns_rule(p)) // patterns && - (guard = guard_rule(p), 1) // guard? + (guard = guard_rule(p), !p->error_indicator) // guard? && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -5407,7 +5551,7 @@ case_block_rule(Parser *p) _res = _PyAST_match_case ( pattern , guard , body , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5418,7 +5562,7 @@ case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5426,16 +5570,19 @@ case_block_rule(Parser *p) static expr_ty guard_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // 'if' named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> guard[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression")); @@ -5451,7 +5598,7 @@ guard_rule(Parser *p) _res = guard; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5462,7 +5609,7 @@ guard_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5470,16 +5617,19 @@ guard_rule(Parser *p) static pattern_ty patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5488,7 +5638,7 @@ patterns_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // open_sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); @@ -5500,7 +5650,7 @@ patterns_rule(Parser *p) D(fprintf(stderr, "%*c+ patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "open_sequence_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5510,7 +5660,7 @@ patterns_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5521,7 +5671,7 @@ patterns_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -5540,7 +5690,7 @@ patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5548,16 +5698,19 @@ patterns_rule(Parser *p) static pattern_ty pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // as_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "as_pattern")); @@ -5576,7 +5729,7 @@ pattern_rule(Parser *p) } { // or_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern")); @@ -5595,24 +5748,27 @@ pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// as_pattern: or_pattern 'as' pattern_capture_target +// as_pattern: or_pattern 'as' pattern_capture_target | invalid_as_pattern static pattern_ty as_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5621,7 +5777,7 @@ as_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // or_pattern 'as' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); @@ -5639,7 +5795,7 @@ as_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5649,7 +5805,7 @@ as_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5658,9 +5814,28 @@ as_pattern_rule(Parser *p) D(fprintf(stderr, "%*c%s as_pattern[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "or_pattern 'as' pattern_capture_target")); } + if (p->call_invalid_rules) { // invalid_as_pattern + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_as_pattern")); + void *invalid_as_pattern_var; + if ( + (invalid_as_pattern_var = invalid_as_pattern_rule(p)) // invalid_as_pattern + ) + { + D(fprintf(stderr, "%*c+ as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_as_pattern")); + _res = invalid_as_pattern_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s as_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_as_pattern")); + } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5668,16 +5843,19 @@ as_pattern_rule(Parser *p) static pattern_ty or_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5686,7 +5864,7 @@ or_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '|'.closed_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -5698,7 +5876,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5708,7 +5886,7 @@ or_pattern_rule(Parser *p) _res = asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5719,7 +5897,7 @@ or_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5735,16 +5913,19 @@ or_pattern_rule(Parser *p) static pattern_ty closed_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // literal_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_pattern")); @@ -5763,7 +5944,7 @@ closed_pattern_rule(Parser *p) } { // capture_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "capture_pattern")); @@ -5782,7 +5963,7 @@ closed_pattern_rule(Parser *p) } { // wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "wildcard_pattern")); @@ -5801,7 +5982,7 @@ closed_pattern_rule(Parser *p) } { // value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "value_pattern")); @@ -5820,7 +6001,7 @@ closed_pattern_rule(Parser *p) } { // group_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group_pattern")); @@ -5839,7 +6020,7 @@ closed_pattern_rule(Parser *p) } { // sequence_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sequence_pattern")); @@ -5858,7 +6039,7 @@ closed_pattern_rule(Parser *p) } { // mapping_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "mapping_pattern")); @@ -5877,7 +6058,7 @@ closed_pattern_rule(Parser *p) } { // class_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> closed_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_pattern")); @@ -5896,7 +6077,7 @@ closed_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -5910,16 +6091,19 @@ closed_pattern_rule(Parser *p) static pattern_ty literal_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -5928,7 +6112,7 @@ literal_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -5942,7 +6126,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5952,7 +6136,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5963,7 +6147,7 @@ literal_pattern_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -5975,7 +6159,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "complex_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -5985,7 +6169,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -5996,7 +6180,7 @@ literal_pattern_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -6008,7 +6192,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "strings")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6018,7 +6202,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( value , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6029,7 +6213,7 @@ literal_pattern_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -6041,7 +6225,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6051,7 +6235,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_None , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6062,7 +6246,7 @@ literal_pattern_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -6074,7 +6258,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6084,7 +6268,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_True , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6095,7 +6279,7 @@ literal_pattern_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -6107,7 +6291,7 @@ literal_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6117,7 +6301,7 @@ literal_pattern_rule(Parser *p) _res = _PyAST_MatchSingleton ( Py_False , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6128,7 +6312,7 @@ literal_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6142,16 +6326,19 @@ literal_pattern_rule(Parser *p) static expr_ty literal_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6160,7 +6347,7 @@ literal_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_number !('+' | '-') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -6181,7 +6368,7 @@ literal_expr_rule(Parser *p) } { // complex_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "complex_number")); @@ -6200,7 +6387,7 @@ literal_expr_rule(Parser *p) } { // strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "strings")); @@ -6219,7 +6406,7 @@ literal_expr_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -6231,7 +6418,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6241,7 +6428,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6252,7 +6439,7 @@ literal_expr_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -6264,7 +6451,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6274,7 +6461,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6285,7 +6472,7 @@ literal_expr_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> literal_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -6297,7 +6484,7 @@ literal_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6307,7 +6494,7 @@ literal_expr_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6318,7 +6505,7 @@ literal_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6328,16 +6515,19 @@ literal_expr_rule(Parser *p) static expr_ty complex_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6346,7 +6536,7 @@ complex_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // signed_real_number '+' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); @@ -6364,7 +6554,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '+' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6374,7 +6564,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Add , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6385,7 +6575,7 @@ complex_number_rule(Parser *p) } { // signed_real_number '-' imaginary_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> complex_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); @@ -6403,7 +6593,7 @@ complex_number_rule(Parser *p) D(fprintf(stderr, "%*c+ complex_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_real_number '-' imaginary_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6413,7 +6603,7 @@ complex_number_rule(Parser *p) _res = _PyAST_BinOp ( real , Sub , imag , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6424,7 +6614,7 @@ complex_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6432,16 +6622,19 @@ complex_number_rule(Parser *p) static expr_ty signed_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6450,7 +6643,7 @@ signed_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6469,7 +6662,7 @@ signed_number_rule(Parser *p) } { // '-' NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); @@ -6484,7 +6677,7 @@ signed_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' NUMBER")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6494,7 +6687,7 @@ signed_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , number , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6505,7 +6698,7 @@ signed_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6513,16 +6706,19 @@ signed_number_rule(Parser *p) static expr_ty signed_real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6531,7 +6727,7 @@ signed_real_number_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "real_number")); @@ -6550,7 +6746,7 @@ signed_real_number_rule(Parser *p) } { // '-' real_number if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> signed_real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' real_number")); @@ -6565,7 +6761,7 @@ signed_real_number_rule(Parser *p) D(fprintf(stderr, "%*c+ signed_real_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' real_number")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6575,7 +6771,7 @@ signed_real_number_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , real , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6586,7 +6782,7 @@ signed_real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6594,16 +6790,19 @@ signed_real_number_rule(Parser *p) static expr_ty real_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> real_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6616,7 +6815,7 @@ real_number_rule(Parser *p) _res = _PyPegen_ensure_real ( p , real ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6627,7 +6826,7 @@ real_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6635,16 +6834,19 @@ real_number_rule(Parser *p) static expr_ty imaginary_number_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -6657,7 +6859,7 @@ imaginary_number_rule(Parser *p) _res = _PyPegen_ensure_imaginary ( p , imag ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6668,7 +6870,7 @@ imaginary_number_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6676,16 +6878,19 @@ imaginary_number_rule(Parser *p) static pattern_ty capture_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6694,7 +6899,7 @@ capture_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> capture_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); @@ -6706,7 +6911,7 @@ capture_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ capture_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6716,7 +6921,7 @@ capture_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6727,7 +6932,7 @@ capture_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6735,16 +6940,19 @@ capture_pattern_rule(Parser *p) static expr_ty pattern_capture_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // !"_" NAME !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> pattern_capture_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -6761,7 +6969,7 @@ pattern_capture_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , name , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6772,7 +6980,7 @@ pattern_capture_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6780,16 +6988,19 @@ pattern_capture_target_rule(Parser *p) static pattern_ty wildcard_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6798,7 +7009,7 @@ wildcard_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // "_" if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> wildcard_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"_\"")); @@ -6810,7 +7021,7 @@ wildcard_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ wildcard_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"_\"")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6820,7 +7031,7 @@ wildcard_pattern_rule(Parser *p) _res = _PyAST_MatchAs ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6831,7 +7042,7 @@ wildcard_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6839,16 +7050,19 @@ wildcard_pattern_rule(Parser *p) static pattern_ty value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6857,7 +7071,7 @@ value_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // attr !('.' | '(' | '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -6871,7 +7085,7 @@ value_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6881,7 +7095,7 @@ value_pattern_rule(Parser *p) _res = _PyAST_MatchValue ( attr , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6892,7 +7106,7 @@ value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6902,10 +7116,13 @@ static expr_ty attr_raw(Parser *); static expr_ty attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, attr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -6913,35 +7130,42 @@ attr_rule(Parser *p) while (1) { int tmpvar_1 = _PyPegen_update_memo(p, _mark, attr_type, _res); if (tmpvar_1) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = attr_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty attr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -6950,7 +7174,7 @@ attr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); @@ -6968,7 +7192,7 @@ attr_raw(Parser *p) D(fprintf(stderr, "%*c+ attr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -6978,7 +7202,7 @@ attr_raw(Parser *p) _res = _PyAST_Attribute ( value , attr -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -6989,7 +7213,7 @@ attr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -6998,16 +7222,19 @@ attr_raw(Parser *p) static expr_ty name_or_attr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -7026,7 +7253,7 @@ name_or_attr_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> name_or_attr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -7045,7 +7272,7 @@ name_or_attr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7053,16 +7280,19 @@ name_or_attr_rule(Parser *p) static pattern_ty group_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // '(' pattern ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' pattern ')'")); @@ -7081,7 +7311,7 @@ group_pattern_rule(Parser *p) _res = pattern; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7092,7 +7322,7 @@ group_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7100,16 +7330,19 @@ group_pattern_rule(Parser *p) static pattern_ty sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7118,7 +7351,7 @@ sequence_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' maybe_sequence_pattern? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); @@ -7128,7 +7361,7 @@ sequence_pattern_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' && - (patterns = maybe_sequence_pattern_rule(p), 1) // maybe_sequence_pattern? + (patterns = maybe_sequence_pattern_rule(p), !p->error_indicator) // maybe_sequence_pattern? && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' ) @@ -7136,7 +7369,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' maybe_sequence_pattern? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7146,7 +7379,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7157,7 +7390,7 @@ sequence_pattern_rule(Parser *p) } { // '(' open_sequence_pattern? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); @@ -7167,7 +7400,7 @@ sequence_pattern_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (patterns = open_sequence_pattern_rule(p), 1) // open_sequence_pattern? + (patterns = open_sequence_pattern_rule(p), !p->error_indicator) // open_sequence_pattern? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -7175,7 +7408,7 @@ sequence_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' open_sequence_pattern? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7185,7 +7418,7 @@ sequence_pattern_rule(Parser *p) _res = _PyAST_MatchSequence ( patterns , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7196,7 +7429,7 @@ sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7204,16 +7437,19 @@ sequence_pattern_rule(Parser *p) static asdl_seq* open_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // maybe_star_pattern ',' maybe_sequence_pattern? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> open_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); @@ -7225,14 +7461,14 @@ open_sequence_pattern_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (patterns = maybe_sequence_pattern_rule(p), 1) // maybe_sequence_pattern? + (patterns = maybe_sequence_pattern_rule(p), !p->error_indicator) // maybe_sequence_pattern? ) { D(fprintf(stderr, "%*c+ open_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern ',' maybe_sequence_pattern?")); _res = _PyPegen_seq_insert_in_front ( p , pattern , patterns ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7243,7 +7479,7 @@ open_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7251,16 +7487,19 @@ open_sequence_pattern_rule(Parser *p) static asdl_seq* maybe_sequence_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.maybe_star_pattern+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_sequence_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); @@ -7270,14 +7509,14 @@ maybe_sequence_pattern_rule(Parser *p) if ( (patterns = _gather_57_rule(p)) // ','.maybe_star_pattern+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ maybe_sequence_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.maybe_star_pattern+ ','?")); _res = patterns; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7288,7 +7527,7 @@ maybe_sequence_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7296,16 +7535,19 @@ maybe_sequence_pattern_rule(Parser *p) static pattern_ty maybe_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; { // star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_pattern")); @@ -7324,7 +7566,7 @@ maybe_star_pattern_rule(Parser *p) } { // pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> maybe_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern")); @@ -7343,7 +7585,7 @@ maybe_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7351,16 +7593,19 @@ maybe_star_pattern_rule(Parser *p) static pattern_ty star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7369,7 +7614,7 @@ star_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); @@ -7384,7 +7629,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' pattern_capture_target")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7394,7 +7639,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( target -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7405,7 +7650,7 @@ star_pattern_rule(Parser *p) } { // '*' wildcard_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); @@ -7420,7 +7665,7 @@ star_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ star_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' wildcard_pattern")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7430,7 +7675,7 @@ star_pattern_rule(Parser *p) _res = _PyAST_MatchStar ( NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7441,7 +7686,7 @@ star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7453,16 +7698,19 @@ star_pattern_rule(Parser *p) static pattern_ty mapping_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7471,7 +7719,7 @@ mapping_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '}'")); @@ -7486,7 +7734,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7496,7 +7744,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7507,7 +7755,7 @@ mapping_pattern_rule(Parser *p) } { // '{' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); @@ -7521,7 +7769,7 @@ mapping_pattern_rule(Parser *p) && (rest = double_star_pattern_rule(p)) // double_star_pattern && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 26)) // token='}' ) @@ -7529,7 +7777,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7539,7 +7787,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( NULL , NULL , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7550,7 +7798,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ',' double_star_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); @@ -7570,7 +7818,7 @@ mapping_pattern_rule(Parser *p) && (rest = double_star_pattern_rule(p)) // double_star_pattern && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_2 = _PyPegen_expect_token(p, 26)) // token='}' ) @@ -7578,7 +7826,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ',' double_star_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7588,7 +7836,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , items ) ) , rest -> v . Name . id , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7599,7 +7847,7 @@ mapping_pattern_rule(Parser *p) } { // '{' items_pattern ','? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> mapping_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); @@ -7613,7 +7861,7 @@ mapping_pattern_rule(Parser *p) && (items = items_pattern_rule(p)) // items_pattern && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 26)) // token='}' ) @@ -7621,7 +7869,7 @@ mapping_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ mapping_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' items_pattern ','? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7631,7 +7879,7 @@ mapping_pattern_rule(Parser *p) _res = _PyAST_MatchMapping ( CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , items ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , items ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7642,7 +7890,7 @@ mapping_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7650,16 +7898,19 @@ mapping_pattern_rule(Parser *p) static asdl_seq* items_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.key_value_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); @@ -7678,7 +7929,7 @@ items_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7686,16 +7937,19 @@ items_pattern_rule(Parser *p) static KeyPatternPair* key_value_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // (literal_expr | attr) ':' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> key_value_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(literal_expr | attr) ':' pattern")); @@ -7714,7 +7968,7 @@ key_value_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , key , pattern ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7725,7 +7979,7 @@ key_value_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7733,16 +7987,19 @@ key_value_pattern_rule(Parser *p) static expr_ty double_star_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '**' pattern_capture_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_star_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' pattern_capture_target")); @@ -7758,7 +8015,7 @@ double_star_pattern_rule(Parser *p) _res = target; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7769,7 +8026,7 @@ double_star_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7778,19 +8035,23 @@ double_star_pattern_rule(Parser *p) // | name_or_attr '(' positional_patterns ','? ')' // | name_or_attr '(' keyword_patterns ','? ')' // | name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' +// | invalid_class_pattern static pattern_ty class_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } pattern_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -7799,7 +8060,7 @@ class_pattern_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // name_or_attr '(' ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); @@ -7817,7 +8078,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7827,7 +8088,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7838,7 +8099,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); @@ -7855,7 +8116,7 @@ class_pattern_rule(Parser *p) && (patterns = positional_patterns_rule(p)) // positional_patterns && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -7863,7 +8124,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7873,7 +8134,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7884,7 +8145,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); @@ -7901,7 +8162,7 @@ class_pattern_rule(Parser *p) && (keywords = keyword_patterns_rule(p)) // keyword_patterns && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -7909,7 +8170,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7919,7 +8180,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7930,7 +8191,7 @@ class_pattern_rule(Parser *p) } { // name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); @@ -7953,7 +8214,7 @@ class_pattern_rule(Parser *p) && (keywords = keyword_patterns_rule(p)) // keyword_patterns && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_2 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -7961,7 +8222,7 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -7971,7 +8232,7 @@ class_pattern_rule(Parser *p) _res = _PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -7980,9 +8241,28 @@ class_pattern_rule(Parser *p) D(fprintf(stderr, "%*c%s class_pattern[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'")); } + if (p->call_invalid_rules) { // invalid_class_pattern + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_pattern")); + void *invalid_class_pattern_var; + if ( + (invalid_class_pattern_var = invalid_class_pattern_rule(p)) // invalid_class_pattern + ) + { + D(fprintf(stderr, "%*c+ class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_class_pattern")); + _res = invalid_class_pattern_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s class_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_class_pattern")); + } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -7990,16 +8270,19 @@ class_pattern_rule(Parser *p) static asdl_pattern_seq* positional_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_pattern_seq* _res = NULL; int _mark = p->mark; { // ','.pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -8012,7 +8295,7 @@ positional_patterns_rule(Parser *p) _res = args; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8023,7 +8306,7 @@ positional_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8031,16 +8314,19 @@ positional_patterns_rule(Parser *p) static asdl_seq* keyword_patterns_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.keyword_pattern+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); @@ -8059,7 +8345,7 @@ keyword_patterns_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8067,16 +8353,19 @@ keyword_patterns_rule(Parser *p) static KeyPatternPair* keyword_pattern_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyPatternPair* _res = NULL; int _mark = p->mark; { // NAME '=' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> keyword_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' pattern")); @@ -8095,7 +8384,7 @@ keyword_pattern_rule(Parser *p) _res = _PyPegen_key_pattern_pair ( p , arg , value ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8106,7 +8395,7 @@ keyword_pattern_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8114,16 +8403,19 @@ keyword_pattern_rule(Parser *p) static stmt_ty return_stmt_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8132,7 +8424,7 @@ return_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'return' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> return_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); @@ -8141,13 +8433,13 @@ return_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 500)) // token='return' && - (a = star_expressions_rule(p), 1) // star_expressions? + (a = star_expressions_rule(p), !p->error_indicator) // star_expressions? ) { D(fprintf(stderr, "%*c+ return_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'return' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8157,7 +8449,7 @@ return_stmt_rule(Parser *p) _res = _PyAST_Return ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8168,7 +8460,7 @@ return_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8176,16 +8468,19 @@ return_stmt_rule(Parser *p) static stmt_ty raise_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8194,7 +8489,7 @@ raise_stmt_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'raise' expression ['from' expression] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -8206,13 +8501,13 @@ raise_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_66_rule(p), 1) // ['from' expression] + (b = _tmp_66_rule(p), !p->error_indicator) // ['from' expression] ) { D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8222,7 +8517,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8233,7 +8528,7 @@ raise_stmt_rule(Parser *p) } { // 'raise' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> raise_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'raise'")); @@ -8245,7 +8540,7 @@ raise_stmt_rule(Parser *p) D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8255,7 +8550,7 @@ raise_stmt_rule(Parser *p) _res = _PyAST_Raise ( NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8266,7 +8561,7 @@ raise_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8274,16 +8569,19 @@ raise_stmt_rule(Parser *p) static stmt_ty function_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators function_def_raw")); @@ -8299,7 +8597,7 @@ function_def_rule(Parser *p) _res = _PyPegen_function_def_decorators ( p , d , f ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8310,7 +8608,7 @@ function_def_rule(Parser *p) } { // function_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "function_def_raw")); @@ -8329,7 +8627,7 @@ function_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8340,16 +8638,19 @@ function_def_rule(Parser *p) static stmt_ty function_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -8358,7 +8659,7 @@ function_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_def_raw")); @@ -8377,7 +8678,7 @@ function_def_raw_rule(Parser *p) } { // 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -8397,15 +8698,15 @@ function_def_raw_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (params = params_rule(p), 1) // params? + (params = params_rule(p), !p->error_indicator) // params? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_67_rule(p), 1) // ['->' expression] + (a = _tmp_67_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && - (tc = func_type_comment_rule(p), 1) // func_type_comment? + (tc = func_type_comment_rule(p), !p->error_indicator) // func_type_comment? && (b = block_rule(p)) // block ) @@ -8413,7 +8714,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8423,7 +8724,7 @@ function_def_raw_rule(Parser *p) _res = _PyAST_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8434,7 +8735,7 @@ function_def_raw_rule(Parser *p) } { // ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); @@ -8457,15 +8758,15 @@ function_def_raw_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (params = params_rule(p), 1) // params? + (params = params_rule(p), !p->error_indicator) // params? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_68_rule(p), 1) // ['->' expression] + (a = _tmp_68_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && - (tc = func_type_comment_rule(p), 1) // func_type_comment? + (tc = func_type_comment_rule(p), !p->error_indicator) // func_type_comment? && (b = block_rule(p)) // block ) @@ -8473,7 +8774,7 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME '(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -8483,7 +8784,7 @@ function_def_raw_rule(Parser *p) _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8494,7 +8795,7 @@ function_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8505,16 +8806,19 @@ function_def_raw_rule(Parser *p) static Token* func_type_comment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } Token* _res = NULL; int _mark = p->mark; { // NEWLINE TYPE_COMMENT &(NEWLINE INDENT) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -8532,7 +8836,7 @@ func_type_comment_rule(Parser *p) _res = t; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8543,7 +8847,7 @@ func_type_comment_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_double_type_comments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_double_type_comments")); @@ -8562,7 +8866,7 @@ func_type_comment_rule(Parser *p) } { // TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> func_type_comment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT")); @@ -8581,7 +8885,7 @@ func_type_comment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8589,16 +8893,19 @@ func_type_comment_rule(Parser *p) static arguments_ty params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_parameters")); @@ -8617,7 +8924,7 @@ params_rule(Parser *p) } { // parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "parameters")); @@ -8636,7 +8943,7 @@ params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8649,16 +8956,19 @@ params_rule(Parser *p) static arguments_ty parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // slash_no_default param_no_default* param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); @@ -8673,14 +8983,14 @@ parameters_rule(Parser *p) && (c = _loop0_71_rule(p)) // param_with_default* && - (d = star_etc_rule(p), 1) // star_etc? + (d = star_etc_rule(p), !p->error_indicator) // star_etc? ) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default param_no_default* param_with_default* star_etc?")); _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8691,7 +9001,7 @@ parameters_rule(Parser *p) } { // slash_with_default param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); @@ -8703,14 +9013,14 @@ parameters_rule(Parser *p) && (b = _loop0_72_rule(p)) // param_with_default* && - (c = star_etc_rule(p), 1) // star_etc? + (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default param_with_default* star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8721,7 +9031,7 @@ parameters_rule(Parser *p) } { // param_no_default+ param_with_default* star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); @@ -8733,14 +9043,14 @@ parameters_rule(Parser *p) && (b = _loop0_74_rule(p)) // param_with_default* && - (c = star_etc_rule(p), 1) // star_etc? + (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default+ param_with_default* star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8751,7 +9061,7 @@ parameters_rule(Parser *p) } { // param_with_default+ star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); @@ -8760,14 +9070,14 @@ parameters_rule(Parser *p) if ( (a = _loop1_75_rule(p)) // param_with_default+ && - (b = star_etc_rule(p), 1) // star_etc? + (b = star_etc_rule(p), !p->error_indicator) // star_etc? ) { D(fprintf(stderr, "%*c+ parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+ star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8778,7 +9088,7 @@ parameters_rule(Parser *p) } { // star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_etc")); @@ -8791,7 +9101,7 @@ parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8802,7 +9112,7 @@ parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8810,16 +9120,19 @@ parameters_rule(Parser *p) static asdl_arg_seq* slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' ','")); @@ -8838,7 +9151,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8849,7 +9162,7 @@ slash_no_default_rule(Parser *p) } { // param_no_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default+ '/' &')'")); @@ -8867,7 +9180,7 @@ slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8878,7 +9191,7 @@ slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8888,16 +9201,19 @@ slash_no_default_rule(Parser *p) static SlashWithDefault* slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // param_no_default* param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' ','")); @@ -8919,7 +9235,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8930,7 +9246,7 @@ slash_with_default_rule(Parser *p) } { // param_no_default* param_with_default+ '/' &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* param_with_default+ '/' &')'")); @@ -8951,7 +9267,7 @@ slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -8962,7 +9278,7 @@ slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -8974,16 +9290,19 @@ slash_with_default_rule(Parser *p) static StarEtc* star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' param_no_default param_maybe_default* kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); @@ -8998,14 +9317,14 @@ star_etc_rule(Parser *p) && (b = _loop0_82_rule(p)) // param_maybe_default* && - (c = kwds_rule(p), 1) // kwds? + (c = kwds_rule(p), !p->error_indicator) // kwds? ) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' param_no_default param_maybe_default* kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9016,7 +9335,7 @@ star_etc_rule(Parser *p) } { // '*' ',' param_maybe_default+ kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); @@ -9031,14 +9350,14 @@ star_etc_rule(Parser *p) && (b = _loop1_83_rule(p)) // param_maybe_default+ && - (c = kwds_rule(p), 1) // kwds? + (c = kwds_rule(p), !p->error_indicator) // kwds? ) { D(fprintf(stderr, "%*c+ star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' param_maybe_default+ kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9049,7 +9368,7 @@ star_etc_rule(Parser *p) } { // kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwds")); @@ -9062,7 +9381,7 @@ star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9073,7 +9392,7 @@ star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_star_etc")); @@ -9092,7 +9411,7 @@ star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9100,16 +9419,19 @@ star_etc_rule(Parser *p) static arg_ty kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' param_no_default")); @@ -9125,7 +9447,7 @@ kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9136,7 +9458,7 @@ kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9144,16 +9466,19 @@ kwds_rule(Parser *p) static arg_ty param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // param ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); @@ -9165,14 +9490,14 @@ param_no_default_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? ) { D(fprintf(stderr, "%*c+ param_no_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param ',' TYPE_COMMENT?")); _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9183,7 +9508,7 @@ param_no_default_rule(Parser *p) } { // param TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param TYPE_COMMENT? &')'")); @@ -9192,7 +9517,7 @@ param_no_default_rule(Parser *p) if ( (a = param_rule(p)) // param && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 8) // token=')' ) @@ -9201,7 +9526,7 @@ param_no_default_rule(Parser *p) _res = _PyPegen_add_type_comment_to_arg ( p , a , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9212,7 +9537,7 @@ param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9220,16 +9545,19 @@ param_no_default_rule(Parser *p) static NameDefaultPair* param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); @@ -9244,14 +9572,14 @@ param_with_default_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? ) { D(fprintf(stderr, "%*c+ param_with_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9262,7 +9590,7 @@ param_with_default_rule(Parser *p) } { // param default TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default TYPE_COMMENT? &')'")); @@ -9274,7 +9602,7 @@ param_with_default_rule(Parser *p) && (c = default_rule(p)) // default && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 8) // token=')' ) @@ -9283,7 +9611,7 @@ param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9294,7 +9622,7 @@ param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9304,16 +9632,19 @@ param_with_default_rule(Parser *p) static NameDefaultPair* param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // param default? ',' TYPE_COMMENT? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); @@ -9324,18 +9655,18 @@ param_maybe_default_rule(Parser *p) if ( (a = param_rule(p)) // param && - (c = default_rule(p), 1) // default? + (c = default_rule(p), !p->error_indicator) // default? && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? ) { D(fprintf(stderr, "%*c+ param_maybe_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param default? ',' TYPE_COMMENT?")); _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9346,7 +9677,7 @@ param_maybe_default_rule(Parser *p) } { // param default? TYPE_COMMENT? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param default? TYPE_COMMENT? &')'")); @@ -9356,9 +9687,9 @@ param_maybe_default_rule(Parser *p) if ( (a = param_rule(p)) // param && - (c = default_rule(p), 1) // default? + (c = default_rule(p), !p->error_indicator) // default? && - (tc = _PyPegen_expect_token(p, TYPE_COMMENT), 1) // TYPE_COMMENT? + (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? && _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 8) // token=')' ) @@ -9367,7 +9698,7 @@ param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , tc ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9378,7 +9709,7 @@ param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9386,16 +9717,19 @@ param_maybe_default_rule(Parser *p) static arg_ty param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9404,7 +9738,7 @@ param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME annotation? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); @@ -9413,13 +9747,13 @@ param_rule(Parser *p) if ( (a = _PyPegen_name_token(p)) // NAME && - (b = annotation_rule(p), 1) // annotation? + (b = annotation_rule(p), !p->error_indicator) // annotation? ) { D(fprintf(stderr, "%*c+ param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME annotation?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9429,7 +9763,7 @@ param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , b , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9440,7 +9774,7 @@ param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9448,16 +9782,19 @@ param_rule(Parser *p) static expr_ty annotation_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotation[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression")); @@ -9473,7 +9810,7 @@ annotation_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9484,7 +9821,7 @@ annotation_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9492,16 +9829,19 @@ annotation_rule(Parser *p) static expr_ty default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' expression")); @@ -9517,7 +9857,7 @@ default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9528,7 +9868,7 @@ default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9536,16 +9876,19 @@ default_rule(Parser *p) static asdl_expr_seq* decorators_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // (('@' named_expression NEWLINE))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -9558,7 +9901,7 @@ decorators_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9569,7 +9912,7 @@ decorators_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9577,16 +9920,19 @@ decorators_rule(Parser *p) static stmt_ty class_def_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; { // decorators class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "decorators class_def_raw")); @@ -9602,7 +9948,7 @@ class_def_rule(Parser *p) _res = _PyPegen_class_def_decorators ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9613,7 +9959,7 @@ class_def_rule(Parser *p) } { // class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "class_def_raw")); @@ -9632,7 +9978,7 @@ class_def_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9640,16 +9986,19 @@ class_def_rule(Parser *p) static stmt_ty class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } stmt_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9658,7 +10007,7 @@ class_def_raw_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_class_def_raw if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_class_def_raw")); @@ -9677,7 +10026,7 @@ class_def_raw_rule(Parser *p) } { // 'class' NAME ['(' arguments? ')'] &&':' block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); @@ -9691,7 +10040,7 @@ class_def_raw_rule(Parser *p) && (a = _PyPegen_name_token(p)) // NAME && - (b = _tmp_85_rule(p), 1) // ['(' arguments? ')'] + (b = _tmp_85_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -9701,7 +10050,7 @@ class_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] &&':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9711,7 +10060,7 @@ class_def_raw_rule(Parser *p) _res = _PyAST_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9722,7 +10071,7 @@ class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9730,20 +10079,23 @@ class_def_raw_rule(Parser *p) static asdl_stmt_seq* block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_stmt_seq* _res = NULL; if (_PyPegen_is_memoized(p, block_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // NEWLINE INDENT statements DEDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT statements DEDENT")); @@ -9765,7 +10117,7 @@ block_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9776,7 +10128,7 @@ block_rule(Parser *p) } { // simple_stmts if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmts")); @@ -9795,7 +10147,7 @@ block_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_block")); @@ -9815,7 +10167,7 @@ block_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, block_type, _res); - D(p->level--); + p->level--; return _res; } @@ -9826,16 +10178,19 @@ block_rule(Parser *p) static expr_ty star_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9844,7 +10199,7 @@ star_expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_expression ((',' star_expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); @@ -9857,13 +10212,13 @@ star_expressions_rule(Parser *p) && (b = _loop1_86_rule(p)) // ((',' star_expression))+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ((',' star_expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9873,7 +10228,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9884,7 +10239,7 @@ star_expressions_rule(Parser *p) } { // star_expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression ','")); @@ -9899,7 +10254,7 @@ star_expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9909,7 +10264,7 @@ star_expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -9920,7 +10275,7 @@ star_expressions_rule(Parser *p) } { // star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression")); @@ -9939,7 +10294,7 @@ star_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -9947,20 +10302,23 @@ star_expressions_rule(Parser *p) static expr_ty star_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -9969,7 +10327,7 @@ star_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -9984,7 +10342,7 @@ star_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -9994,7 +10352,7 @@ star_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10005,7 +10363,7 @@ star_expression_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10025,7 +10383,7 @@ star_expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10033,16 +10391,19 @@ star_expression_rule(Parser *p) static asdl_expr_seq* star_named_expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_named_expression+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); @@ -10052,14 +10413,14 @@ star_named_expressions_rule(Parser *p) if ( (a = (asdl_expr_seq*)_gather_87_rule(p)) // ','.star_named_expression+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ star_named_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_named_expression+ ','?")); _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10070,7 +10431,7 @@ star_named_expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10078,16 +10439,19 @@ star_named_expressions_rule(Parser *p) static expr_ty star_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10096,7 +10460,7 @@ star_named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); @@ -10111,7 +10475,7 @@ star_named_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ star_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' bitwise_or")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10121,7 +10485,7 @@ star_named_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10132,7 +10496,7 @@ star_named_expression_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -10151,24 +10515,27 @@ star_named_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// named_expression: NAME ':=' ~ expression | invalid_named_expression | expression !':=' +// assignment_expression: NAME ':=' ~ expression static expr_ty -named_expression_rule(Parser *p) +assignment_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10177,10 +10544,10 @@ named_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME ':=' ~ expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c> assignment_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); int _cut_var = 0; Token * _literal; expr_ty a; @@ -10195,10 +10562,10 @@ named_expression_rule(Parser *p) (b = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); + D(fprintf(stderr, "%*c+ assignment_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10208,137 +10575,83 @@ named_expression_rule(Parser *p) _res = _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s assignment_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); if (_cut_var) { - D(p->level--); - return NULL; - } - } - if (p->call_invalid_rules) { // invalid_named_expression - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); - void *invalid_named_expression_var; - if ( - (invalid_named_expression_var = invalid_named_expression_rule(p)) // invalid_named_expression - ) - { - D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); - _res = invalid_named_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_named_expression")); - } - { // expression !':=' - if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); - expr_ty expression_var; - if ( - (expression_var = expression_rule(p)) // expression - && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' - ) - { - D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); - _res = expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// direct_named_expression: NAME ':=' ~ expression | expression !':=' +// named_expression: assignment_expression | invalid_named_expression | expression !':=' static expr_ty -direct_named_expression_rule(Parser *p) +named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; - if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - int _start_lineno = p->tokens[_mark]->lineno; - UNUSED(_start_lineno); // Only used by EXTRA macro - int _start_col_offset = p->tokens[_mark]->col_offset; - UNUSED(_start_col_offset); // Only used by EXTRA macro - { // NAME ':=' ~ expression + { // assignment_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> direct_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); - int _cut_var = 0; - Token * _literal; - expr_ty a; - expr_ty b; + D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (a = _PyPegen_name_token(p)) // NAME - && - (_literal = _PyPegen_expect_token(p, 53)) // token=':=' - && - (_cut_var = 1) - && - (b = expression_rule(p)) // expression + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ direct_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':=' ~ expression")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_NamedExpr ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , b , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } + D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s direct_named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME ':=' ~ expression")); - if (_cut_var) { - D(p->level--); + D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); + } + if (p->call_invalid_rules) { // invalid_named_expression + if (p->error_indicator) { + p->level--; return NULL; } + D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); + void *invalid_named_expression_var; + if ( + (invalid_named_expression_var = invalid_named_expression_rule(p)) // invalid_named_expression + ) + { + D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_named_expression")); + _res = invalid_named_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_named_expression")); } { // expression !':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> direct_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -10346,17 +10659,17 @@ direct_named_expression_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ direct_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s direct_named_expression[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10364,16 +10677,19 @@ direct_named_expression_rule(Parser *p) static expr_ty annotated_rhs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -10392,7 +10708,7 @@ annotated_rhs_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> annotated_rhs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -10411,7 +10727,7 @@ annotated_rhs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10419,16 +10735,19 @@ annotated_rhs_rule(Parser *p) static expr_ty expressions_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10437,7 +10756,7 @@ expressions_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression ((',' expression))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); @@ -10450,13 +10769,13 @@ expressions_rule(Parser *p) && (b = _loop1_89_rule(p)) // ((',' expression))+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ((',' expression))+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10466,7 +10785,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10477,7 +10796,7 @@ expressions_rule(Parser *p) } { // expression ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ','")); @@ -10492,7 +10811,7 @@ expressions_rule(Parser *p) D(fprintf(stderr, "%*c+ expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ','")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10502,7 +10821,7 @@ expressions_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_singleton_seq ( p , a ) ) , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10513,7 +10832,7 @@ expressions_rule(Parser *p) } { // expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression")); @@ -10532,32 +10851,36 @@ expressions_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } // expression: // | invalid_expression +// | invalid_legacy_expression // | disjunction 'if' disjunction 'else' expression // | disjunction // | lambdef static expr_ty expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, expression_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10566,7 +10889,7 @@ expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro if (p->call_invalid_rules) { // invalid_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_expression")); @@ -10583,9 +10906,28 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_expression")); } + if (p->call_invalid_rules) { // invalid_legacy_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + void *invalid_legacy_expression_var; + if ( + (invalid_legacy_expression_var = invalid_legacy_expression_rule(p)) // invalid_legacy_expression + ) + { + D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_legacy_expression")); + _res = invalid_legacy_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_legacy_expression")); + } { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); @@ -10609,7 +10951,7 @@ expression_rule(Parser *p) D(fprintf(stderr, "%*c+ expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10619,7 +10961,7 @@ expression_rule(Parser *p) _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10630,7 +10972,7 @@ expression_rule(Parser *p) } { // disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); @@ -10649,7 +10991,7 @@ expression_rule(Parser *p) } { // lambdef if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); @@ -10669,7 +11011,7 @@ expression_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, expression_type, _res); - D(p->level--); + p->level--; return _res; } @@ -10677,16 +11019,19 @@ expression_rule(Parser *p) static expr_ty lambdef_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -10695,7 +11040,7 @@ lambdef_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'lambda' lambda_params? ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambdef[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); @@ -10706,7 +11051,7 @@ lambdef_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 528)) // token='lambda' && - (a = lambda_params_rule(p), 1) // lambda_params? + (a = lambda_params_rule(p), !p->error_indicator) // lambda_params? && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -10716,7 +11061,7 @@ lambdef_rule(Parser *p) D(fprintf(stderr, "%*c+ lambdef[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -10726,7 +11071,7 @@ lambdef_rule(Parser *p) _res = _PyAST_Lambda ( ( a ) ? a : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10737,7 +11082,7 @@ lambdef_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10745,16 +11090,19 @@ lambdef_rule(Parser *p) static arguments_ty lambda_params_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; if (p->call_invalid_rules) { // invalid_lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_parameters")); @@ -10773,7 +11121,7 @@ lambda_params_rule(Parser *p) } { // lambda_parameters if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_parameters")); @@ -10792,7 +11140,7 @@ lambda_params_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10805,16 +11153,19 @@ lambda_params_rule(Parser *p) static arguments_ty lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arguments_ty _res = NULL; int _mark = p->mark; { // lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); @@ -10829,14 +11180,14 @@ lambda_parameters_rule(Parser *p) && (c = _loop0_91_rule(p)) // lambda_param_with_default* && - (d = lambda_star_etc_rule(p), 1) // lambda_star_etc? + (d = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , a , NULL , b , c , d ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10847,7 +11198,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_slash_with_default lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); @@ -10859,14 +11210,14 @@ lambda_parameters_rule(Parser *p) && (b = _loop0_92_rule(p)) // lambda_param_with_default* && - (c = lambda_star_etc_rule(p), 1) // lambda_star_etc? + (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default lambda_param_with_default* lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , a , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10877,7 +11228,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_no_default+ lambda_param_with_default* lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); @@ -10889,14 +11240,14 @@ lambda_parameters_rule(Parser *p) && (b = _loop0_94_rule(p)) // lambda_param_with_default* && - (c = lambda_star_etc_rule(p), 1) // lambda_star_etc? + (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ lambda_param_with_default* lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10907,7 +11258,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_param_with_default+ lambda_star_etc? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); @@ -10916,14 +11267,14 @@ lambda_parameters_rule(Parser *p) if ( (a = _loop1_95_rule(p)) // lambda_param_with_default+ && - (b = lambda_star_etc_rule(p), 1) // lambda_star_etc? + (b = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) { D(fprintf(stderr, "%*c+ lambda_parameters[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+ lambda_star_etc?")); _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10934,7 +11285,7 @@ lambda_parameters_rule(Parser *p) } { // lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_star_etc")); @@ -10947,7 +11298,7 @@ lambda_parameters_rule(Parser *p) _res = _PyPegen_make_arguments ( p , NULL , NULL , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -10958,7 +11309,7 @@ lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -10968,16 +11319,19 @@ lambda_parameters_rule(Parser *p) static asdl_arg_seq* lambda_slash_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_arg_seq* _res = NULL; int _mark = p->mark; { // lambda_param_no_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' ','")); @@ -10996,7 +11350,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11007,7 +11361,7 @@ lambda_slash_no_default_rule(Parser *p) } { // lambda_param_no_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default+ '/' &':'")); @@ -11025,7 +11379,7 @@ lambda_slash_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11036,7 +11390,7 @@ lambda_slash_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11046,16 +11400,19 @@ lambda_slash_no_default_rule(Parser *p) static SlashWithDefault* lambda_slash_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } SlashWithDefault* _res = NULL; int _mark = p->mark; { // lambda_param_no_default* lambda_param_with_default+ '/' ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' ','")); @@ -11077,7 +11434,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11088,7 +11445,7 @@ lambda_slash_with_default_rule(Parser *p) } { // lambda_param_no_default* lambda_param_with_default+ '/' &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_slash_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* lambda_param_with_default+ '/' &':'")); @@ -11109,7 +11466,7 @@ lambda_slash_with_default_rule(Parser *p) _res = _PyPegen_slash_with_default ( p , ( asdl_arg_seq * ) a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11120,7 +11477,7 @@ lambda_slash_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11132,16 +11489,19 @@ lambda_slash_with_default_rule(Parser *p) static StarEtc* lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } StarEtc* _res = NULL; int _mark = p->mark; { // '*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); @@ -11156,14 +11516,14 @@ lambda_star_etc_rule(Parser *p) && (b = _loop0_102_rule(p)) // lambda_param_maybe_default* && - (c = lambda_kwds_rule(p), 1) // lambda_kwds? + (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' lambda_param_no_default lambda_param_maybe_default* lambda_kwds?")); _res = _PyPegen_star_etc ( p , a , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11174,7 +11534,7 @@ lambda_star_etc_rule(Parser *p) } { // '*' ',' lambda_param_maybe_default+ lambda_kwds? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); @@ -11189,14 +11549,14 @@ lambda_star_etc_rule(Parser *p) && (b = _loop1_103_rule(p)) // lambda_param_maybe_default+ && - (c = lambda_kwds_rule(p), 1) // lambda_kwds? + (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) { D(fprintf(stderr, "%*c+ lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' ',' lambda_param_maybe_default+ lambda_kwds?")); _res = _PyPegen_star_etc ( p , NULL , b , c ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11207,7 +11567,7 @@ lambda_star_etc_rule(Parser *p) } { // lambda_kwds if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_kwds")); @@ -11220,7 +11580,7 @@ lambda_star_etc_rule(Parser *p) _res = _PyPegen_star_etc ( p , NULL , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11231,7 +11591,7 @@ lambda_star_etc_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_lambda_star_etc if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_lambda_star_etc")); @@ -11250,7 +11610,7 @@ lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11258,16 +11618,19 @@ lambda_star_etc_rule(Parser *p) static arg_ty lambda_kwds_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // '**' lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_kwds[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' lambda_param_no_default")); @@ -11283,7 +11646,7 @@ lambda_kwds_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11294,7 +11657,7 @@ lambda_kwds_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11302,16 +11665,19 @@ lambda_kwds_rule(Parser *p) static arg_ty lambda_param_no_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; { // lambda_param ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param ','")); @@ -11327,7 +11693,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11338,7 +11704,7 @@ lambda_param_no_default_rule(Parser *p) } { // lambda_param &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_no_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param &':'")); @@ -11353,7 +11719,7 @@ lambda_param_no_default_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11364,7 +11730,7 @@ lambda_param_no_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11372,16 +11738,19 @@ lambda_param_no_default_rule(Parser *p) static NameDefaultPair* lambda_param_with_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default ','")); @@ -11400,7 +11769,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11411,7 +11780,7 @@ lambda_param_with_default_rule(Parser *p) } { // lambda_param default &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_with_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default &':'")); @@ -11429,7 +11798,7 @@ lambda_param_with_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11440,7 +11809,7 @@ lambda_param_with_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11448,16 +11817,19 @@ lambda_param_with_default_rule(Parser *p) static NameDefaultPair* lambda_param_maybe_default_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } NameDefaultPair* _res = NULL; int _mark = p->mark; { // lambda_param default? ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? ','")); @@ -11467,7 +11839,7 @@ lambda_param_maybe_default_rule(Parser *p) if ( (a = lambda_param_rule(p)) // lambda_param && - (c = default_rule(p), 1) // default? + (c = default_rule(p), !p->error_indicator) // default? && (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) @@ -11476,7 +11848,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11487,7 +11859,7 @@ lambda_param_maybe_default_rule(Parser *p) } { // lambda_param default? &':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param_maybe_default[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param default? &':'")); @@ -11496,7 +11868,7 @@ lambda_param_maybe_default_rule(Parser *p) if ( (a = lambda_param_rule(p)) // lambda_param && - (c = default_rule(p), 1) // default? + (c = default_rule(p), !p->error_indicator) // default? && _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 11) // token=':' ) @@ -11505,7 +11877,7 @@ lambda_param_maybe_default_rule(Parser *p) _res = _PyPegen_name_default_pair ( p , a , c , NULL ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11516,7 +11888,7 @@ lambda_param_maybe_default_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11524,16 +11896,19 @@ lambda_param_maybe_default_rule(Parser *p) static arg_ty lambda_param_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } arg_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11542,7 +11917,7 @@ lambda_param_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lambda_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -11554,7 +11929,7 @@ lambda_param_rule(Parser *p) D(fprintf(stderr, "%*c+ lambda_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11564,7 +11939,7 @@ lambda_param_rule(Parser *p) _res = _PyAST_arg ( a -> v . Name . id , NULL , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11575,7 +11950,7 @@ lambda_param_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11583,20 +11958,23 @@ lambda_param_rule(Parser *p) static expr_ty disjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, disjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11605,7 +11983,7 @@ disjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // conjunction (('or' conjunction))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -11620,7 +11998,7 @@ disjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11630,7 +12008,7 @@ disjunction_rule(Parser *p) _res = _PyAST_BoolOp ( Or , CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11641,7 +12019,7 @@ disjunction_rule(Parser *p) } { // conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> disjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "conjunction")); @@ -11661,7 +12039,7 @@ disjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, disjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11669,20 +12047,23 @@ disjunction_rule(Parser *p) static expr_ty conjunction_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, conjunction_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11691,7 +12072,7 @@ conjunction_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // inversion (('and' inversion))+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -11706,7 +12087,7 @@ conjunction_rule(Parser *p) D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11716,7 +12097,7 @@ conjunction_rule(Parser *p) _res = _PyAST_BoolOp ( And , CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11727,7 +12108,7 @@ conjunction_rule(Parser *p) } { // inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> conjunction[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "inversion")); @@ -11747,7 +12128,7 @@ conjunction_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, conjunction_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11755,20 +12136,23 @@ conjunction_rule(Parser *p) static expr_ty inversion_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, inversion_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11777,7 +12161,7 @@ inversion_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'not' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' inversion")); @@ -11792,7 +12176,7 @@ inversion_rule(Parser *p) D(fprintf(stderr, "%*c+ inversion[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'not' inversion")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11802,7 +12186,7 @@ inversion_rule(Parser *p) _res = _PyAST_UnaryOp ( Not , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11813,7 +12197,7 @@ inversion_rule(Parser *p) } { // comparison if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> inversion[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "comparison")); @@ -11833,7 +12217,7 @@ inversion_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, inversion_type, _res); - D(p->level--); + p->level--; return _res; } @@ -11841,16 +12225,19 @@ inversion_rule(Parser *p) static expr_ty comparison_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -11859,7 +12246,7 @@ comparison_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or compare_op_bitwise_or_pair+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -11874,7 +12261,7 @@ comparison_rule(Parser *p) D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -11884,7 +12271,7 @@ comparison_rule(Parser *p) _res = _PyAST_Compare ( a , CHECK ( asdl_int_seq * , _PyPegen_get_cmpops ( p , b ) ) , CHECK ( asdl_expr_seq * , _PyPegen_get_exprs ( p , b ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -11895,7 +12282,7 @@ comparison_rule(Parser *p) } { // bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> comparison[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or")); @@ -11914,7 +12301,7 @@ comparison_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -11932,16 +12319,19 @@ comparison_rule(Parser *p) static CmpopExprPair* compare_op_bitwise_or_pair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // eq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "eq_bitwise_or")); @@ -11960,7 +12350,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // noteq_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "noteq_bitwise_or")); @@ -11979,7 +12369,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lte_bitwise_or")); @@ -11998,7 +12388,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // lt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lt_bitwise_or")); @@ -12017,7 +12407,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gte_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gte_bitwise_or")); @@ -12036,7 +12426,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // gt_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "gt_bitwise_or")); @@ -12055,7 +12445,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // notin_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "notin_bitwise_or")); @@ -12074,7 +12464,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // in_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "in_bitwise_or")); @@ -12093,7 +12483,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // isnot_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "isnot_bitwise_or")); @@ -12112,7 +12502,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } { // is_bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> compare_op_bitwise_or_pair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "is_bitwise_or")); @@ -12131,7 +12521,7 @@ compare_op_bitwise_or_pair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12139,16 +12529,19 @@ compare_op_bitwise_or_pair_rule(Parser *p) static CmpopExprPair* eq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '==' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> eq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'==' bitwise_or")); @@ -12164,7 +12557,7 @@ eq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Eq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12175,7 +12568,7 @@ eq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12183,16 +12576,19 @@ eq_bitwise_or_rule(Parser *p) static CmpopExprPair* noteq_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // ('!=') bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); @@ -12208,7 +12604,7 @@ noteq_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotEq , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12219,7 +12615,7 @@ noteq_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12227,16 +12623,19 @@ noteq_bitwise_or_rule(Parser *p) static CmpopExprPair* lte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<=' bitwise_or")); @@ -12252,7 +12651,7 @@ lte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , LtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12263,7 +12662,7 @@ lte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12271,16 +12670,19 @@ lte_bitwise_or_rule(Parser *p) static CmpopExprPair* lt_bitwise_or_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '<' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> lt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'<' bitwise_or")); @@ -12296,7 +12698,7 @@ lt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Lt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12307,7 +12709,7 @@ lt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12315,16 +12717,19 @@ lt_bitwise_or_rule(Parser *p) static CmpopExprPair* gte_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>=' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gte_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>=' bitwise_or")); @@ -12340,7 +12745,7 @@ gte_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , GtE , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12351,7 +12756,7 @@ gte_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12359,16 +12764,19 @@ gte_bitwise_or_rule(Parser *p) static CmpopExprPair* gt_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // '>' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> gt_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'>' bitwise_or")); @@ -12384,7 +12792,7 @@ gt_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Gt , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12395,7 +12803,7 @@ gt_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12403,16 +12811,19 @@ gt_bitwise_or_rule(Parser *p) static CmpopExprPair* notin_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'not' 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> notin_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'not' 'in' bitwise_or")); @@ -12431,7 +12842,7 @@ notin_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , NotIn , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12442,7 +12853,7 @@ notin_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12450,16 +12861,19 @@ notin_bitwise_or_rule(Parser *p) static CmpopExprPair* in_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'in' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> in_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'in' bitwise_or")); @@ -12475,7 +12889,7 @@ in_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , In , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12486,7 +12900,7 @@ in_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12494,16 +12908,19 @@ in_bitwise_or_rule(Parser *p) static CmpopExprPair* isnot_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' 'not' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> isnot_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' 'not' bitwise_or")); @@ -12522,7 +12939,7 @@ isnot_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , IsNot , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12533,7 +12950,7 @@ isnot_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12541,16 +12958,19 @@ isnot_bitwise_or_rule(Parser *p) static CmpopExprPair* is_bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } CmpopExprPair* _res = NULL; int _mark = p->mark; { // 'is' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> is_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'is' bitwise_or")); @@ -12566,7 +12986,7 @@ is_bitwise_or_rule(Parser *p) _res = _PyPegen_cmpop_expr_pair ( p , Is , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12577,7 +12997,7 @@ is_bitwise_or_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12587,10 +13007,13 @@ static expr_ty bitwise_or_raw(Parser *); static expr_ty bitwise_or_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_or_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12598,35 +13021,42 @@ bitwise_or_rule(Parser *p) while (1) { int tmpvar_2 = _PyPegen_update_memo(p, _mark, bitwise_or_type, _res); if (tmpvar_2) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = bitwise_or_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_or_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12635,7 +13065,7 @@ bitwise_or_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_or '|' bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); @@ -12653,7 +13083,7 @@ bitwise_or_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_or[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or '|' bitwise_xor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12663,7 +13093,7 @@ bitwise_or_raw(Parser *p) _res = _PyAST_BinOp ( a , BitOr , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12674,7 +13104,7 @@ bitwise_or_raw(Parser *p) } { // bitwise_xor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor")); @@ -12693,7 +13123,7 @@ bitwise_or_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12703,10 +13133,13 @@ static expr_ty bitwise_xor_raw(Parser *); static expr_ty bitwise_xor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_xor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12714,35 +13147,42 @@ bitwise_xor_rule(Parser *p) while (1) { int tmpvar_3 = _PyPegen_update_memo(p, _mark, bitwise_xor_type, _res); if (tmpvar_3) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = bitwise_xor_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_xor_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12751,7 +13191,7 @@ bitwise_xor_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_xor '^' bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); @@ -12769,7 +13209,7 @@ bitwise_xor_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_xor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_xor '^' bitwise_and")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12779,7 +13219,7 @@ bitwise_xor_raw(Parser *p) _res = _PyAST_BinOp ( a , BitXor , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12790,7 +13230,7 @@ bitwise_xor_raw(Parser *p) } { // bitwise_and if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_xor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and")); @@ -12809,7 +13249,7 @@ bitwise_xor_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12819,10 +13259,13 @@ static expr_ty bitwise_and_raw(Parser *); static expr_ty bitwise_and_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, bitwise_and_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12830,35 +13273,42 @@ bitwise_and_rule(Parser *p) while (1) { int tmpvar_4 = _PyPegen_update_memo(p, _mark, bitwise_and_type, _res); if (tmpvar_4) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = bitwise_and_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty bitwise_and_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12867,7 +13317,7 @@ bitwise_and_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // bitwise_and '&' shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); @@ -12885,7 +13335,7 @@ bitwise_and_raw(Parser *p) D(fprintf(stderr, "%*c+ bitwise_and[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_and '&' shift_expr")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -12895,7 +13345,7 @@ bitwise_and_raw(Parser *p) _res = _PyAST_BinOp ( a , BitAnd , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -12906,7 +13356,7 @@ bitwise_and_raw(Parser *p) } { // shift_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> bitwise_and[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr")); @@ -12925,7 +13375,7 @@ bitwise_and_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -12935,10 +13385,13 @@ static expr_ty shift_expr_raw(Parser *); static expr_ty shift_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, shift_expr_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -12946,35 +13399,42 @@ shift_expr_rule(Parser *p) while (1) { int tmpvar_5 = _PyPegen_update_memo(p, _mark, shift_expr_type, _res); if (tmpvar_5) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = shift_expr_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty shift_expr_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -12983,7 +13443,7 @@ shift_expr_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // shift_expr '<<' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); @@ -13001,7 +13461,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '<<' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13011,7 +13471,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , LShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13022,7 +13482,7 @@ shift_expr_raw(Parser *p) } { // shift_expr '>>' sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); @@ -13040,7 +13500,7 @@ shift_expr_raw(Parser *p) D(fprintf(stderr, "%*c+ shift_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "shift_expr '>>' sum")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13050,7 +13510,7 @@ shift_expr_raw(Parser *p) _res = _PyAST_BinOp ( a , RShift , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13061,7 +13521,7 @@ shift_expr_raw(Parser *p) } { // sum if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> shift_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum")); @@ -13080,7 +13540,7 @@ shift_expr_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13090,10 +13550,13 @@ static expr_ty sum_raw(Parser *); static expr_ty sum_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, sum_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13101,35 +13564,42 @@ sum_rule(Parser *p) while (1) { int tmpvar_6 = _PyPegen_update_memo(p, _mark, sum_type, _res); if (tmpvar_6) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = sum_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty sum_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13138,7 +13608,7 @@ sum_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // sum '+' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '+' term")); @@ -13156,7 +13626,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '+' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13166,7 +13636,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Add , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13177,7 +13647,7 @@ sum_raw(Parser *p) } { // sum '-' term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum '-' term")); @@ -13195,7 +13665,7 @@ sum_raw(Parser *p) D(fprintf(stderr, "%*c+ sum[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "sum '-' term")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13205,7 +13675,7 @@ sum_raw(Parser *p) _res = _PyAST_BinOp ( a , Sub , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13216,7 +13686,7 @@ sum_raw(Parser *p) } { // term if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> sum[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term")); @@ -13235,7 +13705,7 @@ sum_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13251,10 +13721,13 @@ static expr_ty term_raw(Parser *); static expr_ty term_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, term_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13262,35 +13735,42 @@ term_rule(Parser *p) while (1) { int tmpvar_7 = _PyPegen_update_memo(p, _mark, term_type, _res); if (tmpvar_7) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = term_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty term_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13299,7 +13779,7 @@ term_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // term '*' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '*' factor")); @@ -13317,7 +13797,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '*' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13327,7 +13807,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mult , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13338,7 +13818,7 @@ term_raw(Parser *p) } { // term '/' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '/' factor")); @@ -13356,7 +13836,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '/' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13366,7 +13846,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Div , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13377,7 +13857,7 @@ term_raw(Parser *p) } { // term '//' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '//' factor")); @@ -13395,7 +13875,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '//' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13405,7 +13885,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , FloorDiv , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13416,7 +13896,7 @@ term_raw(Parser *p) } { // term '%' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '%' factor")); @@ -13434,7 +13914,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '%' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13444,7 +13924,7 @@ term_raw(Parser *p) _res = _PyAST_BinOp ( a , Mod , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13455,7 +13935,7 @@ term_raw(Parser *p) } { // term '@' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "term '@' factor")); @@ -13473,7 +13953,7 @@ term_raw(Parser *p) D(fprintf(stderr, "%*c+ term[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "term '@' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13483,7 +13963,7 @@ term_raw(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "The '@' operator is" , _PyAST_BinOp ( a , MatMult , b , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13494,7 +13974,7 @@ term_raw(Parser *p) } { // factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> term[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "factor")); @@ -13513,7 +13993,7 @@ term_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13521,20 +14001,23 @@ term_raw(Parser *p) static expr_ty factor_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, factor_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13543,7 +14026,7 @@ factor_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '+' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' factor")); @@ -13558,7 +14041,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13568,7 +14051,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( UAdd , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13579,7 +14062,7 @@ factor_rule(Parser *p) } { // '-' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-' factor")); @@ -13594,7 +14077,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13604,7 +14087,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( USub , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13615,7 +14098,7 @@ factor_rule(Parser *p) } { // '~' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~' factor")); @@ -13630,7 +14113,7 @@ factor_rule(Parser *p) D(fprintf(stderr, "%*c+ factor[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13640,7 +14123,7 @@ factor_rule(Parser *p) _res = _PyAST_UnaryOp ( Invert , a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13651,7 +14134,7 @@ factor_rule(Parser *p) } { // power if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "power")); @@ -13671,7 +14154,7 @@ factor_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, factor_type, _res); - D(p->level--); + p->level--; return _res; } @@ -13679,16 +14162,19 @@ factor_rule(Parser *p) static expr_ty power_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13697,7 +14183,7 @@ power_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // await_primary '**' factor if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); @@ -13715,7 +14201,7 @@ power_rule(Parser *p) D(fprintf(stderr, "%*c+ power[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "await_primary '**' factor")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13725,7 +14211,7 @@ power_rule(Parser *p) _res = _PyAST_BinOp ( a , Pow , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13736,7 +14222,7 @@ power_rule(Parser *p) } { // await_primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> power[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "await_primary")); @@ -13755,7 +14241,7 @@ power_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -13763,20 +14249,23 @@ power_rule(Parser *p) static expr_ty await_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, await_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -13785,7 +14274,7 @@ await_primary_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // AWAIT primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); @@ -13800,7 +14289,7 @@ await_primary_rule(Parser *p) D(fprintf(stderr, "%*c+ await_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "AWAIT primary")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13810,7 +14299,7 @@ await_primary_rule(Parser *p) _res = CHECK_VERSION ( expr_ty , 5 , "Await expressions are" , _PyAST_Await ( a , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13821,7 +14310,7 @@ await_primary_rule(Parser *p) } { // primary if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> await_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary")); @@ -13841,13 +14330,12 @@ await_primary_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, await_primary_type, _res); - D(p->level--); + p->level--; return _res; } // Left-recursive // primary: -// | invalid_primary // | primary '.' NAME // | primary genexp // | primary '(' arguments? ')' @@ -13857,10 +14345,13 @@ static expr_ty primary_raw(Parser *); static expr_ty primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -13868,63 +14359,51 @@ primary_rule(Parser *p) while (1) { int tmpvar_8 = _PyPegen_update_memo(p, _mark, primary_type, _res); if (tmpvar_8) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = primary_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - if (p->call_invalid_rules) { // invalid_primary - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_primary")); - void *invalid_primary_var; - if ( - (invalid_primary_var = invalid_primary_rule(p)) // invalid_primary - ) - { - D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_primary")); - _res = invalid_primary_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s primary[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_primary")); - } { // primary '.' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); @@ -13942,7 +14421,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '.' NAME")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13952,7 +14431,7 @@ primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13963,7 +14442,7 @@ primary_raw(Parser *p) } { // primary genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary genexp")); @@ -13978,7 +14457,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary genexp")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -13988,7 +14467,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq * , ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -13999,7 +14478,7 @@ primary_raw(Parser *p) } { // primary '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); @@ -14012,7 +14491,7 @@ primary_raw(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (b = arguments_rule(p), 1) // arguments? + (b = arguments_rule(p), !p->error_indicator) // arguments? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -14020,7 +14499,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '(' arguments? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14030,7 +14509,7 @@ primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14041,7 +14520,7 @@ primary_raw(Parser *p) } { // primary '[' slices ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); @@ -14062,7 +14541,7 @@ primary_raw(Parser *p) D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '[' slices ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14072,7 +14551,7 @@ primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14083,7 +14562,7 @@ primary_raw(Parser *p) } { // atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom")); @@ -14102,7 +14581,7 @@ primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14110,16 +14589,19 @@ primary_raw(Parser *p) static expr_ty slices_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14128,7 +14610,7 @@ slices_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // slice !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice !','")); @@ -14143,7 +14625,7 @@ slices_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14154,7 +14636,7 @@ slices_rule(Parser *p) } { // ','.slice+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slices[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); @@ -14164,13 +14646,13 @@ slices_rule(Parser *p) if ( (a = (asdl_expr_seq*)_gather_108_rule(p)) // ','.slice+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ slices[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.slice+ ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14180,7 +14662,7 @@ slices_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14191,7 +14673,7 @@ slices_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14199,16 +14681,19 @@ slices_rule(Parser *p) static expr_ty slice_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14217,7 +14702,7 @@ slice_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // expression? ':' expression? [':' expression?] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -14226,19 +14711,19 @@ slice_rule(Parser *p) void *b; void *c; if ( - (a = expression_rule(p), 1) // expression? + (a = expression_rule(p), !p->error_indicator) // expression? && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (b = expression_rule(p), 1) // expression? + (b = expression_rule(p), !p->error_indicator) // expression? && - (c = _tmp_110_rule(p), 1) // [':' expression?] + (c = _tmp_110_rule(p), !p->error_indicator) // [':' expression?] ) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14248,7 +14733,7 @@ slice_rule(Parser *p) _res = _PyAST_Slice ( a , b , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14259,7 +14744,7 @@ slice_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> slice[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -14272,7 +14757,7 @@ slice_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14283,7 +14768,7 @@ slice_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14301,16 +14786,19 @@ slice_rule(Parser *p) static expr_ty atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14319,7 +14807,7 @@ atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -14338,7 +14826,7 @@ atom_rule(Parser *p) } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); @@ -14350,7 +14838,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14360,7 +14848,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_True , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14371,7 +14859,7 @@ atom_rule(Parser *p) } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); @@ -14383,7 +14871,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14393,7 +14881,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_False , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14404,7 +14892,7 @@ atom_rule(Parser *p) } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); @@ -14416,7 +14904,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14426,7 +14914,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_None , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14437,7 +14925,7 @@ atom_rule(Parser *p) } { // &STRING strings if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&STRING strings")); @@ -14458,7 +14946,7 @@ atom_rule(Parser *p) } { // NUMBER if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NUMBER")); @@ -14477,7 +14965,7 @@ atom_rule(Parser *p) } { // &'(' (tuple | group | genexp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); @@ -14498,7 +14986,7 @@ atom_rule(Parser *p) } { // &'[' (list | listcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); @@ -14519,7 +15007,7 @@ atom_rule(Parser *p) } { // &'{' (dict | set | dictcomp | setcomp) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); @@ -14540,7 +15028,7 @@ atom_rule(Parser *p) } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); @@ -14552,7 +15040,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14562,7 +15050,7 @@ atom_rule(Parser *p) _res = _PyAST_Constant ( Py_Ellipsis , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14573,7 +15061,7 @@ atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14581,20 +15069,23 @@ atom_rule(Parser *p) static expr_ty strings_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, strings_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // STRING+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+")); @@ -14607,7 +15098,7 @@ strings_rule(Parser *p) _res = _PyPegen_concatenate_strings ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14619,7 +15110,7 @@ strings_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, strings_type, _res); - D(p->level--); + p->level--; return _res; } @@ -14627,16 +15118,19 @@ strings_rule(Parser *p) static expr_ty list_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14645,7 +15139,7 @@ list_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' star_named_expressions? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> list[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); @@ -14655,7 +15149,7 @@ list_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' && - (a = star_named_expressions_rule(p), 1) // star_named_expressions? + (a = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' ) @@ -14663,7 +15157,7 @@ list_rule(Parser *p) D(fprintf(stderr, "%*c+ list[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_named_expressions? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14673,7 +15167,7 @@ list_rule(Parser *p) _res = _PyAST_List ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14684,7 +15178,7 @@ list_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14692,16 +15186,19 @@ list_rule(Parser *p) static expr_ty listcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14710,7 +15207,7 @@ listcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '[' named_expression for_if_clauses ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); @@ -14731,7 +15228,7 @@ listcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14741,7 +15238,7 @@ listcomp_rule(Parser *p) _res = _PyAST_ListComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14752,7 +15249,7 @@ listcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -14771,7 +15268,7 @@ listcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14779,16 +15276,19 @@ listcomp_rule(Parser *p) static expr_ty tuple_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -14797,7 +15297,7 @@ tuple_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '(' [star_named_expression ',' star_named_expressions?] ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> tuple[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); @@ -14807,7 +15307,7 @@ tuple_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_115_rule(p), 1) // [star_named_expression ',' star_named_expressions?] + (a = _tmp_115_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -14815,7 +15315,7 @@ tuple_rule(Parser *p) D(fprintf(stderr, "%*c+ tuple[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' [star_named_expression ',' star_named_expressions?] ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14825,7 +15325,7 @@ tuple_rule(Parser *p) _res = _PyAST_Tuple ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14836,7 +15336,7 @@ tuple_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14844,16 +15344,19 @@ tuple_rule(Parser *p) static expr_ty group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // '(' (yield_expr | named_expression) ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (yield_expr | named_expression) ')'")); @@ -14872,7 +15375,7 @@ group_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -14883,7 +15386,7 @@ group_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_group")); @@ -14902,54 +15405,59 @@ group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// genexp: '(' direct_named_expression for_if_clauses ')' | invalid_comprehension +// genexp: +// | '(' (assignment_expression | expression !':=') for_if_clauses ')' +// | invalid_comprehension static expr_ty genexp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '(' direct_named_expression for_if_clauses ')' + { // '(' (assignment_expression | expression !':=') for_if_clauses ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); + D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token * _literal; Token * _literal_1; - expr_ty a; + void *a; asdl_comprehension_seq* b; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = direct_named_expression_rule(p)) // direct_named_expression + (a = _tmp_117_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); + D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -14959,18 +15467,18 @@ genexp_rule(Parser *p) _res = _PyAST_GeneratorExp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' direct_named_expression for_if_clauses ')'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (assignment_expression | expression !':=') for_if_clauses ')'")); } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -14989,7 +15497,7 @@ genexp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -14997,16 +15505,19 @@ genexp_rule(Parser *p) static expr_ty set_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15015,7 +15526,7 @@ set_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' star_named_expressions '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); @@ -15033,7 +15544,7 @@ set_rule(Parser *p) D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15043,7 +15554,7 @@ set_rule(Parser *p) _res = _PyAST_Set ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15054,7 +15565,7 @@ set_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15062,16 +15573,19 @@ set_rule(Parser *p) static expr_ty setcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15080,7 +15594,7 @@ setcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' named_expression for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); @@ -15101,7 +15615,7 @@ setcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15111,7 +15625,7 @@ setcomp_rule(Parser *p) _res = _PyAST_SetComp ( a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15122,7 +15636,7 @@ setcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_comprehension")); @@ -15141,7 +15655,7 @@ setcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15149,16 +15663,19 @@ setcomp_rule(Parser *p) static expr_ty dict_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15167,7 +15684,7 @@ dict_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' double_starred_kvpairs? '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); @@ -15177,7 +15694,7 @@ dict_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (a = double_starred_kvpairs_rule(p), 1) // double_starred_kvpairs? + (a = double_starred_kvpairs_rule(p), !p->error_indicator) // double_starred_kvpairs? && (_literal_1 = _PyPegen_expect_token(p, 26)) // token='}' ) @@ -15185,7 +15702,7 @@ dict_rule(Parser *p) D(fprintf(stderr, "%*c+ dict[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' double_starred_kvpairs? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15195,7 +15712,7 @@ dict_rule(Parser *p) _res = _PyAST_Dict ( CHECK ( asdl_expr_seq * , _PyPegen_get_keys ( p , a ) ) , CHECK ( asdl_expr_seq * , _PyPegen_get_values ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15206,7 +15723,7 @@ dict_rule(Parser *p) } { // '{' invalid_double_starred_kvpairs '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dict[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' invalid_double_starred_kvpairs '}'")); @@ -15231,7 +15748,7 @@ dict_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15239,16 +15756,19 @@ dict_rule(Parser *p) static expr_ty dictcomp_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15257,7 +15777,7 @@ dictcomp_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '{' kvpair for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); @@ -15278,7 +15798,7 @@ dictcomp_rule(Parser *p) D(fprintf(stderr, "%*c+ dictcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' kvpair for_if_clauses '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15288,7 +15808,7 @@ dictcomp_rule(Parser *p) _res = _PyAST_DictComp ( a -> key , a -> value , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15299,7 +15819,7 @@ dictcomp_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_dict_comprehension if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> dictcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_dict_comprehension")); @@ -15318,7 +15838,7 @@ dictcomp_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15326,16 +15846,19 @@ dictcomp_rule(Parser *p) static asdl_seq* double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); @@ -15343,16 +15866,16 @@ double_starred_kvpairs_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_117_rule(p)) // ','.double_starred_kvpair+ + (a = _gather_118_rule(p)) // ','.double_starred_kvpair+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ','?")); _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15363,7 +15886,7 @@ double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15371,16 +15894,19 @@ double_starred_kvpairs_rule(Parser *p) static KeyValuePair* double_starred_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // '**' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' bitwise_or")); @@ -15396,7 +15922,7 @@ double_starred_kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , NULL , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15407,7 +15933,7 @@ double_starred_kvpair_rule(Parser *p) } { // kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> double_starred_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kvpair")); @@ -15426,7 +15952,7 @@ double_starred_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15434,16 +15960,19 @@ double_starred_kvpair_rule(Parser *p) static KeyValuePair* kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeyValuePair* _res = NULL; int _mark = p->mark; { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -15462,7 +15991,7 @@ kvpair_rule(Parser *p) _res = _PyPegen_key_value_pair ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15473,7 +16002,7 @@ kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15481,29 +16010,32 @@ kvpair_rule(Parser *p) static asdl_comprehension_seq* for_if_clauses_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_comprehension_seq* _res = NULL; int _mark = p->mark; { // for_if_clause+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); asdl_comprehension_seq* a; if ( - (a = (asdl_comprehension_seq*)_loop1_119_rule(p)) // for_if_clause+ + (a = (asdl_comprehension_seq*)_loop1_120_rule(p)) // for_if_clause+ ) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15514,7 +16046,7 @@ for_if_clauses_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15525,16 +16057,19 @@ for_if_clauses_rule(Parser *p) static comprehension_ty for_if_clause_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } comprehension_ty _res = NULL; int _mark = p->mark; { // ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15558,14 +16093,14 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_120_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_121_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = CHECK_VERSION ( comprehension_ty , 6 , "Async comprehensions are" , _PyAST_comprehension ( a , b , c , 1 , p -> arena ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15574,13 +16109,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } { // 'for' star_targets 'in' ~ disjunction (('if' disjunction))* if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -15601,14 +16136,14 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_121_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_122_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); _res = _PyAST_comprehension ( a , b , c , 0 , p -> arena ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15617,13 +16152,13 @@ for_if_clause_rule(Parser *p) D(fprintf(stderr, "%*c%s for_if_clause[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); if (_cut_var) { - D(p->level--); + p->level--; return NULL; } } if (p->call_invalid_rules) { // invalid_for_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> for_if_clause[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_for_target")); @@ -15642,7 +16177,7 @@ for_if_clause_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15650,16 +16185,19 @@ for_if_clause_rule(Parser *p) static expr_ty yield_expr_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -15668,7 +16206,7 @@ yield_expr_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // 'yield' 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); @@ -15686,7 +16224,7 @@ yield_expr_rule(Parser *p) D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' 'from' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15696,7 +16234,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_YieldFrom ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15707,7 +16245,7 @@ yield_expr_rule(Parser *p) } { // 'yield' star_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> yield_expr[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); @@ -15716,13 +16254,13 @@ yield_expr_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 504)) // token='yield' && - (a = star_expressions_rule(p), 1) // star_expressions? + (a = star_expressions_rule(p), !p->error_indicator) // star_expressions? ) { D(fprintf(stderr, "%*c+ yield_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'yield' star_expressions?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15732,7 +16270,7 @@ yield_expr_rule(Parser *p) _res = _PyAST_Yield ( a , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15743,7 +16281,7 @@ yield_expr_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15751,20 +16289,23 @@ yield_expr_rule(Parser *p) static expr_ty arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, arguments_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; { // args ','? &')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','? &')'")); @@ -15774,7 +16315,7 @@ arguments_rule(Parser *p) if ( (a = args_rule(p)) // args && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 8) // token=')' ) @@ -15783,7 +16324,7 @@ arguments_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15794,7 +16335,7 @@ arguments_rule(Parser *p) } if (p->call_invalid_rules) { // invalid_arguments if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_arguments")); @@ -15814,48 +16355,53 @@ arguments_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, arguments_type, _res); - D(p->level--); + p->level--; return _res; } -// args: ','.(starred_expression | direct_named_expression !'=')+ [',' kwargs] | kwargs +// args: +// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] +// | kwargs static expr_ty args_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // ','.(starred_expression | direct_named_expression !'=')+ [',' kwargs] + { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | direct_named_expression !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_122_rule(p)) // ','.(starred_expression | direct_named_expression !'=')+ + (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_124_rule(p), 1) // [',' kwargs] + (b = _tmp_125_rule(p), !p->error_indicator) // [',' kwargs] ) { - D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | direct_named_expression !'=')+ [',' kwargs]")); + D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15865,18 +16411,18 @@ args_rule(Parser *p) _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | direct_named_expression !'=')+ [',' kwargs]")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); } { // kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); @@ -15888,7 +16434,7 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -15898,7 +16444,7 @@ args_rule(Parser *p) _res = _PyAST_Call ( _PyPegen_dummy_name ( p ) , CHECK_NULL_ALLOWED ( asdl_expr_seq * , _PyPegen_seq_extract_starred_exprs ( p , a ) ) , CHECK_NULL_ALLOWED ( asdl_keyword_seq * , _PyPegen_seq_delete_starred_exprs ( p , a ) ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15909,7 +16455,7 @@ args_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -15920,16 +16466,19 @@ args_rule(Parser *p) static asdl_seq* kwargs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq* _res = NULL; int _mark = p->mark; { // ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -15937,18 +16486,18 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_125_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_126_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_127_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_128_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); _res = _PyPegen_join_sequences ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -15959,17 +16508,17 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_129_var; + asdl_seq * _gather_130_var; if ( - (_gather_129_var = _gather_129_rule(p)) // ','.kwarg_or_starred+ + (_gather_130_var = _gather_130_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_129_var; + _res = _gather_130_var; goto done; } p->mark = _mark; @@ -15978,17 +16527,17 @@ kwargs_rule(Parser *p) } { // ','.kwarg_or_double_starred+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_131_var; + asdl_seq * _gather_132_var; if ( - (_gather_131_var = _gather_131_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_132_var = _gather_132_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_131_var; + _res = _gather_132_var; goto done; } p->mark = _mark; @@ -15997,7 +16546,7 @@ kwargs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16005,16 +16554,19 @@ kwargs_rule(Parser *p) static expr_ty starred_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16023,7 +16575,7 @@ starred_expression_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> starred_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' expression")); @@ -16038,7 +16590,7 @@ starred_expression_rule(Parser *p) D(fprintf(stderr, "%*c+ starred_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16048,7 +16600,7 @@ starred_expression_rule(Parser *p) _res = _PyAST_Starred ( a , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16059,33 +16611,55 @@ starred_expression_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// kwarg_or_starred: NAME '=' expression | starred_expression | invalid_kwarg +// kwarg_or_starred: invalid_kwarg | NAME '=' expression | starred_expression static KeywordOrStarred* kwarg_or_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro + if (p->call_invalid_rules) { // invalid_kwarg + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); + void *invalid_kwarg_var; + if ( + (invalid_kwarg_var = invalid_kwarg_rule(p)) // invalid_kwarg + ) + { + D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); + _res = invalid_kwarg_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s kwarg_or_starred[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_kwarg")); + } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16103,7 +16677,7 @@ kwarg_or_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16113,7 +16687,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16124,7 +16698,7 @@ kwarg_or_starred_rule(Parser *p) } { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); @@ -16137,7 +16711,7 @@ kwarg_or_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , a , 0 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16146,54 +16720,57 @@ kwarg_or_starred_rule(Parser *p) D(fprintf(stderr, "%*c%s kwarg_or_starred[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } - if (p->call_invalid_rules) { // invalid_kwarg - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> kwarg_or_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); - void *invalid_kwarg_var; - if ( - (invalid_kwarg_var = invalid_kwarg_rule(p)) // invalid_kwarg - ) - { - D(fprintf(stderr, "%*c+ kwarg_or_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); - _res = invalid_kwarg_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s kwarg_or_starred[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_kwarg")); - } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// kwarg_or_double_starred: NAME '=' expression | '**' expression | invalid_kwarg +// kwarg_or_double_starred: invalid_kwarg | NAME '=' expression | '**' expression static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } KeywordOrStarred* _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro + if (p->call_invalid_rules) { // invalid_kwarg + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); + void *invalid_kwarg_var; + if ( + (invalid_kwarg_var = invalid_kwarg_rule(p)) // invalid_kwarg + ) + { + D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); + _res = invalid_kwarg_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s kwarg_or_double_starred[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_kwarg")); + } { // NAME '=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); @@ -16211,7 +16788,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16221,7 +16798,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( a -> v . Name . id , b , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16232,7 +16809,7 @@ kwarg_or_double_starred_rule(Parser *p) } { // '**' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' expression")); @@ -16247,7 +16824,7 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' expression")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16257,7 +16834,7 @@ kwarg_or_double_starred_rule(Parser *p) _res = _PyPegen_keyword_or_starred ( p , CHECK ( keyword_ty , _PyAST_keyword ( NULL , a , EXTRA ) ) , 1 ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16266,28 +16843,9 @@ kwarg_or_double_starred_rule(Parser *p) D(fprintf(stderr, "%*c%s kwarg_or_double_starred[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' expression")); } - if (p->call_invalid_rules) { // invalid_kwarg - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> kwarg_or_double_starred[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); - void *invalid_kwarg_var; - if ( - (invalid_kwarg_var = invalid_kwarg_rule(p)) // invalid_kwarg - ) - { - D(fprintf(stderr, "%*c+ kwarg_or_double_starred[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_kwarg")); - _res = invalid_kwarg_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s kwarg_or_double_starred[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_kwarg")); - } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16295,16 +16853,19 @@ kwarg_or_double_starred_rule(Parser *p) static expr_ty star_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16313,7 +16874,7 @@ star_targets_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // star_target !',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target !','")); @@ -16328,7 +16889,7 @@ star_targets_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16339,7 +16900,7 @@ star_targets_rule(Parser *p) } { // star_target ((',' star_target))* ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); @@ -16350,15 +16911,15 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_133_rule(p)) // ((',' star_target))* + (b = _loop0_134_rule(p)) // ((',' star_target))* && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ star_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))* ','?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16368,7 +16929,7 @@ star_targets_rule(Parser *p) _res = _PyAST_Tuple ( CHECK ( asdl_expr_seq * , _PyPegen_seq_insert_in_front ( p , a , b ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16379,7 +16940,7 @@ star_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16387,16 +16948,19 @@ star_targets_rule(Parser *p) static asdl_expr_seq* star_targets_list_seq_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.star_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_list_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); @@ -16404,16 +16968,16 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_134_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_135_rule(p)) // ','.star_target+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ star_targets_list_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?")); _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16424,7 +16988,7 @@ star_targets_list_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16432,16 +16996,19 @@ star_targets_list_seq_rule(Parser *p) static asdl_expr_seq* star_targets_tuple_seq_rule(Parser *p) { - D(p->level++); - if (p->error_indicator) { - D(p->level--); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // star_target ((',' star_target))+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); @@ -16452,16 +17019,16 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_136_rule(p)) // ((',' star_target))+ + (b = _loop1_137_rule(p)) // ((',' star_target))+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?")); _res = ( asdl_expr_seq * ) _PyPegen_seq_insert_in_front ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16472,7 +17039,7 @@ star_targets_tuple_seq_rule(Parser *p) } { // star_target ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ','")); @@ -16488,7 +17055,7 @@ star_targets_tuple_seq_rule(Parser *p) _res = ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16499,7 +17066,7 @@ star_targets_tuple_seq_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16507,20 +17074,23 @@ star_targets_tuple_seq_rule(Parser *p) static expr_ty star_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, star_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16529,7 +17099,7 @@ star_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // '*' (!'*' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -16538,13 +17108,13 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_137_rule(p)) // !'*' star_target + (a = _tmp_138_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16554,7 +17124,7 @@ star_target_rule(Parser *p) _res = _PyAST_Starred ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , a , Store ) ) , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16565,7 +17135,7 @@ star_target_rule(Parser *p) } { // target_with_star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target_with_star_atom")); @@ -16585,7 +17155,7 @@ star_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, star_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16596,20 +17166,23 @@ star_target_rule(Parser *p) static expr_ty target_with_star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, target_with_star_atom_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16618,7 +17191,7 @@ target_with_star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -16638,7 +17211,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16648,7 +17221,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16659,7 +17232,7 @@ target_with_star_atom_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -16682,7 +17255,7 @@ target_with_star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16692,7 +17265,7 @@ target_with_star_atom_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16703,7 +17276,7 @@ target_with_star_atom_rule(Parser *p) } { // star_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom")); @@ -16723,7 +17296,7 @@ target_with_star_atom_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, target_with_star_atom_type, _res); - D(p->level--); + p->level--; return _res; } @@ -16735,16 +17308,19 @@ target_with_star_atom_rule(Parser *p) static expr_ty star_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -16753,7 +17329,7 @@ star_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16766,7 +17342,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16777,7 +17353,7 @@ star_atom_rule(Parser *p) } { // '(' target_with_star_atom ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'")); @@ -16796,7 +17372,7 @@ star_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16807,7 +17383,7 @@ star_atom_rule(Parser *p) } { // '(' star_targets_tuple_seq? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); @@ -16817,7 +17393,7 @@ star_atom_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = star_targets_tuple_seq_rule(p), 1) // star_targets_tuple_seq? + (a = star_targets_tuple_seq_rule(p), !p->error_indicator) // star_targets_tuple_seq? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -16825,7 +17401,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16835,7 +17411,7 @@ star_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16846,7 +17422,7 @@ star_atom_rule(Parser *p) } { // '[' star_targets_list_seq? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); @@ -16856,7 +17432,7 @@ star_atom_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' && - (a = star_targets_list_seq_rule(p), 1) // star_targets_list_seq? + (a = star_targets_list_seq_rule(p), !p->error_indicator) // star_targets_list_seq? && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' ) @@ -16864,7 +17440,7 @@ star_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -16874,7 +17450,7 @@ star_atom_rule(Parser *p) _res = _PyAST_List ( a , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16885,7 +17461,7 @@ star_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16893,16 +17469,19 @@ star_atom_rule(Parser *p) static expr_ty single_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -16921,7 +17500,7 @@ single_target_rule(Parser *p) } { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -16934,7 +17513,7 @@ single_target_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Store ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16945,7 +17524,7 @@ single_target_rule(Parser *p) } { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -16964,7 +17543,7 @@ single_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -16975,7 +17554,7 @@ single_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -16985,16 +17564,19 @@ single_target_rule(Parser *p) static expr_ty single_subscript_attribute_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17003,7 +17585,7 @@ single_subscript_attribute_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -17023,7 +17605,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17033,7 +17615,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17044,7 +17626,7 @@ single_subscript_attribute_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> single_subscript_attribute_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -17067,7 +17649,7 @@ single_subscript_attribute_target_rule(Parser *p) D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17077,7 +17659,7 @@ single_subscript_attribute_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Store , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17088,7 +17670,7 @@ single_subscript_attribute_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17096,16 +17678,19 @@ single_subscript_attribute_target_rule(Parser *p) static asdl_expr_seq* del_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_expr_seq* _res = NULL; int _mark = p->mark; { // ','.del_target+ ','? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); @@ -17113,16 +17698,16 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_138_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_139_rule(p)) // ','.del_target+ && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { D(fprintf(stderr, "%*c+ del_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.del_target+ ','?")); _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17133,7 +17718,7 @@ del_targets_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17144,20 +17729,23 @@ del_targets_rule(Parser *p) static expr_ty del_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, del_target_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17166,7 +17754,7 @@ del_target_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -17186,7 +17774,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17196,7 +17784,7 @@ del_target_rule(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17207,7 +17795,7 @@ del_target_rule(Parser *p) } { // t_primary '[' slices ']' !t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -17230,7 +17818,7 @@ del_target_rule(Parser *p) D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17240,7 +17828,7 @@ del_target_rule(Parser *p) _res = _PyAST_Subscript ( a , b , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17251,7 +17839,7 @@ del_target_rule(Parser *p) } { // del_t_atom if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_t_atom")); @@ -17271,7 +17859,7 @@ del_target_rule(Parser *p) _res = NULL; done: _PyPegen_insert_memo(p, _mark, del_target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -17279,16 +17867,19 @@ del_target_rule(Parser *p) static expr_ty del_t_atom_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17297,7 +17888,7 @@ del_t_atom_rule(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); @@ -17310,7 +17901,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17321,7 +17912,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_target ')'")); @@ -17340,7 +17931,7 @@ del_t_atom_rule(Parser *p) _res = _PyPegen_set_expr_context ( p , a , Del ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17351,7 +17942,7 @@ del_t_atom_rule(Parser *p) } { // '(' del_targets? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); @@ -17361,7 +17952,7 @@ del_t_atom_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = del_targets_rule(p), 1) // del_targets? + (a = del_targets_rule(p), !p->error_indicator) // del_targets? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -17369,7 +17960,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' del_targets? ')'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17379,7 +17970,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_Tuple ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17390,7 +17981,7 @@ del_t_atom_rule(Parser *p) } { // '[' del_targets? ']' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> del_t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); @@ -17400,7 +17991,7 @@ del_t_atom_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' && - (a = del_targets_rule(p), 1) // del_targets? + (a = del_targets_rule(p), !p->error_indicator) // del_targets? && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' ) @@ -17408,7 +17999,7 @@ del_t_atom_rule(Parser *p) D(fprintf(stderr, "%*c+ del_t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' del_targets? ']'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17418,7 +18009,7 @@ del_t_atom_rule(Parser *p) _res = _PyAST_List ( a , Del , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17429,190 +18020,7 @@ del_t_atom_rule(Parser *p) } _res = NULL; done: - D(p->level--); - return _res; -} - -// targets: ','.target+ ','? -static asdl_expr_seq* -targets_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - asdl_expr_seq* _res = NULL; - int _mark = p->mark; - { // ','.target+ ','? - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.target+ ','?")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - asdl_expr_seq* a; - if ( - (a = (asdl_expr_seq*)_gather_140_rule(p)) // ','.target+ - && - (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? - ) - { - D(fprintf(stderr, "%*c+ targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.target+ ','?")); - _res = a; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s targets[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.target+ ','?")); - } - _res = NULL; - done: - D(p->level--); - return _res; -} - -// target: -// | t_primary '.' NAME !t_lookahead -// | t_primary '[' slices ']' !t_lookahead -// | t_atom -static expr_ty -target_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - expr_ty _res = NULL; - if (_PyPegen_is_memoized(p, target_type, &_res)) { - D(p->level--); - return _res; - } - int _mark = p->mark; - if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - int _start_lineno = p->tokens[_mark]->lineno; - UNUSED(_start_lineno); // Only used by EXTRA macro - int _start_col_offset = p->tokens[_mark]->col_offset; - UNUSED(_start_col_offset); // Only used by EXTRA macro - { // t_primary '.' NAME !t_lookahead - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); - Token * _literal; - expr_ty a; - expr_ty b; - if ( - (a = t_primary_rule(p)) // t_primary - && - (_literal = _PyPegen_expect_token(p, 23)) // token='.' - && - (b = _PyPegen_name_token(p)) // NAME - && - _PyPegen_lookahead(0, t_lookahead_rule, p) - ) - { - D(fprintf(stderr, "%*c+ target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_Attribute ( a , b -> v . Name . id , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s target[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "t_primary '.' NAME !t_lookahead")); - } - { // t_primary '[' slices ']' !t_lookahead - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); - Token * _literal; - Token * _literal_1; - expr_ty a; - expr_ty b; - if ( - (a = t_primary_rule(p)) // t_primary - && - (_literal = _PyPegen_expect_token(p, 9)) // token='[' - && - (b = slices_rule(p)) // slices - && - (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' - && - _PyPegen_lookahead(0, t_lookahead_rule, p) - ) - { - D(fprintf(stderr, "%*c+ target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_Subscript ( a , b , Store , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s target[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); - } - { // t_atom - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_atom")); - expr_ty t_atom_var; - if ( - (t_atom_var = t_atom_rule(p)) // t_atom - ) - { - D(fprintf(stderr, "%*c+ target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_atom")); - _res = t_atom_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s target[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "t_atom")); - } - _res = NULL; - done: - _PyPegen_insert_memo(p, _mark, target_type, _res); - D(p->level--); + p->level--; return _res; } @@ -17627,10 +18035,13 @@ static expr_ty t_primary_raw(Parser *); static expr_ty t_primary_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } expr_ty _res = NULL; if (_PyPegen_is_memoized(p, t_primary_type, &_res)) { - D(p->level--); + p->level--; return _res; } int _mark = p->mark; @@ -17638,35 +18049,42 @@ t_primary_rule(Parser *p) while (1) { int tmpvar_9 = _PyPegen_update_memo(p, _mark, t_primary_type, _res); if (tmpvar_9) { - D(p->level--); + p->level--; return _res; } p->mark = _mark; + p->in_raw_rule++; void *_raw = t_primary_raw(p); - if (p->error_indicator) + p->in_raw_rule--; + if (p->error_indicator) { + p->level--; return NULL; + } if (_raw == NULL || p->mark <= _resmark) break; _resmark = p->mark; _res = _raw; } p->mark = _resmark; - D(p->level--); + p->level--; return _res; } static expr_ty t_primary_raw(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } int _start_lineno = p->tokens[_mark]->lineno; @@ -17675,7 +18093,7 @@ t_primary_raw(Parser *p) UNUSED(_start_col_offset); // Only used by EXTRA macro { // t_primary '.' NAME &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); @@ -17695,7 +18113,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17705,7 +18123,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Attribute ( a , b -> v . Name . id , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17716,7 +18134,7 @@ t_primary_raw(Parser *p) } { // t_primary '[' slices ']' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); @@ -17739,7 +18157,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17749,7 +18167,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Subscript ( a , b , Load , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17760,7 +18178,7 @@ t_primary_raw(Parser *p) } { // t_primary genexp &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); @@ -17777,7 +18195,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17787,7 +18205,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , CHECK ( asdl_expr_seq * , ( asdl_expr_seq * ) _PyPegen_singleton_seq ( p , b ) ) , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17798,7 +18216,7 @@ t_primary_raw(Parser *p) } { // t_primary '(' arguments? ')' &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); @@ -17811,7 +18229,7 @@ t_primary_raw(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (b = arguments_rule(p), 1) // arguments? + (b = arguments_rule(p), !p->error_indicator) // arguments? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -17821,7 +18239,7 @@ t_primary_raw(Parser *p) D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { - D(p->level--); + p->level--; return NULL; } int _end_lineno = _token->end_lineno; @@ -17831,7 +18249,7 @@ t_primary_raw(Parser *p) _res = _PyAST_Call ( a , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17842,7 +18260,7 @@ t_primary_raw(Parser *p) } { // atom &t_lookahead if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); @@ -17857,7 +18275,7 @@ t_primary_raw(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -17868,7 +18286,7 @@ t_primary_raw(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -17876,16 +18294,19 @@ t_primary_raw(Parser *p) static void * t_lookahead_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -17904,7 +18325,7 @@ t_lookahead_rule(Parser *p) } { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); @@ -17923,7 +18344,7 @@ t_lookahead_rule(Parser *p) } { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> t_lookahead[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -17942,451 +18363,602 @@ t_lookahead_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// t_atom: NAME | '(' target ')' | '(' targets? ')' | '[' targets? ']' -static expr_ty -t_atom_rule(Parser *p) +// invalid_arguments: +// | args ',' '*' +// | expression for_if_clauses ',' [args | expression for_if_clauses] +// | NAME '=' expression for_if_clauses +// | args for_if_clauses +// | args ',' expression for_if_clauses +// | args ',' args +static void * +invalid_arguments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - expr_ty _res = NULL; + void * _res = NULL; int _mark = p->mark; - if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - int _start_lineno = p->tokens[_mark]->lineno; - UNUSED(_start_lineno); // Only used by EXTRA macro - int _start_col_offset = p->tokens[_mark]->col_offset; - UNUSED(_start_col_offset); // Only used by EXTRA macro - { // NAME + { // args ',' '*' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME")); + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); + Token * _literal; + Token * _literal_1; expr_ty a; if ( - (a = _PyPegen_name_token(p)) // NAME + (a = args_rule(p)) // args + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (_literal_1 = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME")); - _res = _PyPegen_set_expr_context ( p , a , Store ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable argument unpacking follows keyword argument unpacking" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s t_atom[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME")); + D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' '*'")); } - { // '(' target ')' + { // expression for_if_clauses ',' [args | expression for_if_clauses] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target ')'")); + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); Token * _literal; - Token * _literal_1; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings expr_ty a; + asdl_comprehension_seq* b; if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (a = expression_rule(p)) // expression && - (a = target_rule(p)) // target + (b = for_if_clauses_rule(p)) // for_if_clauses && - (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (_opt_var = _tmp_141_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { - D(fprintf(stderr, "%*c+ t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' target ')'")); - _res = _PyPegen_set_expr_context ( p , a , Store ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , comprehension_ty ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s t_atom[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' target ')'")); + D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); } - { // '(' targets? ')' + { // NAME '=' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' targets? ')'")); - Token * _literal; - Token * _literal_1; - void *b; + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); + expr_ty a; + Token * b; + expr_ty expression_var; + asdl_comprehension_seq* for_if_clauses_var; if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (a = _PyPegen_name_token(p)) // NAME && - (b = targets_rule(p), 1) // targets? + (b = _PyPegen_expect_token(p, 22)) // token='=' && - (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' + (expression_var = expression_rule(p)) // expression + && + (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' targets? ')'")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_Tuple ( b , Store , EXTRA ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s t_atom[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' targets? ')'")); + D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '=' expression for_if_clauses")); } - { // '[' targets? ']' + { // args for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> t_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' targets? ']'")); - Token * _literal; - Token * _literal_1; - void *b; + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); + expr_ty a; + asdl_comprehension_seq* b; if ( - (_literal = _PyPegen_expect_token(p, 9)) // token='[' - && - (b = targets_rule(p), 1) // targets? + (a = args_rule(p)) // args && - (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' + (b = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ t_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' targets? ']'")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_List ( b , Store , EXTRA ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); + _res = _PyPegen_nonparen_genexp_in_call ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s t_atom[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' targets? ']'")); - } - _res = NULL; - done: - D(p->level--); - return _res; -} - -// invalid_arguments: -// | args ',' '*' -// | expression for_if_clauses ',' [args | expression for_if_clauses] -// | args for_if_clauses -// | args ',' expression for_if_clauses -// | args ',' args -static void * -invalid_arguments_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; + D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args for_if_clauses")); } - void * _res = NULL; - int _mark = p->mark; - { // args ',' '*' + { // args ',' expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); Token * _literal; - Token * _literal_1; expr_ty a; + expr_ty args_var; + asdl_comprehension_seq* b; if ( - (a = args_rule(p)) // args + (args_var = args_rule(p)) // args && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_literal_1 = _PyPegen_expect_token(p, 16)) // token='*' + (a = expression_rule(p)) // expression + && + (b = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' '*'")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable argument unpacking follows keyword argument unpacking" ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , asdl_seq_GET ( b , b -> size - 1 ) -> target , "Generator expression must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' '*'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' expression for_if_clauses")); } - { // expression for_if_clauses ',' [args | expression for_if_clauses] + { // args ',' args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); + D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args")); Token * _literal; - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings expr_ty a; - asdl_comprehension_seq* b; + expr_ty args_var; if ( - (a = expression_rule(p)) // expression - && - (b = for_if_clauses_rule(p)) // for_if_clauses + (a = args_rule(p)) // args && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_142_rule(p), 1) // [args | expression for_if_clauses] + (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , comprehension_ty ) -> target , "Generator expression must be parenthesized" ); + D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args")); + _res = _PyPegen_arguments_parsing_error ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' args")); } - { // args for_if_clauses + _res = NULL; + done: + p->level--; + return _res; +} + +// invalid_kwarg: +// | ('True' | 'False' | 'None') '=' +// | NAME '=' expression for_if_clauses +// | !(NAME '=') expression '=' +static void * +invalid_kwarg_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // ('True' | 'False' | 'None') '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); + D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + Token* a; + Token * b; + if ( + (a = (Token*)_tmp_142_rule(p)) // 'True' | 'False' | 'None' + && + (b = _PyPegen_expect_token(p, 22)) // token='=' + ) + { + D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('True' | 'False' | 'None') '='")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot assign to %s" , PyBytes_AS_STRING ( a -> bytes ) ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('True' | 'False' | 'None') '='")); + } + { // NAME '=' expression for_if_clauses + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); expr_ty a; + Token * b; + expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( - (a = args_rule(p)) // args + (a = _PyPegen_name_token(p)) // NAME + && + (b = _PyPegen_expect_token(p, 22)) // token='=' + && + (expression_var = expression_rule(p)) // expression && (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses")); - _res = _PyPegen_nonparen_genexp_in_call ( p , a ); + D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' expression for_if_clauses")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args for_if_clauses")); + D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '=' expression for_if_clauses")); } - { // args ',' expression for_if_clauses + { // !(NAME '=') expression '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); - Token * _literal; + D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); expr_ty a; - expr_ty args_var; - asdl_comprehension_seq* b; + Token * b; if ( - (args_var = args_rule(p)) // args - && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + _PyPegen_lookahead(0, _tmp_143_rule, p) && (a = expression_rule(p)) // expression && - (b = for_if_clauses_rule(p)) // for_if_clauses + (b = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , asdl_seq_GET ( b , b -> size - 1 ) -> target , "Generator expression must be parenthesized" ); + D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME '=') expression '='")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' expression for_if_clauses")); + D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(NAME '=') expression '='")); } - { // args ',' args + _res = NULL; + done: + p->level--; + return _res; +} + +// expression_without_invalid: +// | disjunction 'if' disjunction 'else' expression +// | disjunction +// | lambdef +static expr_ty +expression_without_invalid_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + expr_ty _res = NULL; + int _mark = p->mark; + if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { + p->error_indicator = 1; + p->level--; + return NULL; + } + int _start_lineno = p->tokens[_mark]->lineno; + UNUSED(_start_lineno); // Only used by EXTRA macro + int _start_col_offset = p->tokens[_mark]->col_offset; + UNUSED(_start_col_offset); // Only used by EXTRA macro + { // disjunction 'if' disjunction 'else' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args")); - Token * _literal; + D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); + Token * _keyword; + Token * _keyword_1; expr_ty a; - expr_ty args_var; + expr_ty b; + expr_ty c; if ( - (a = args_rule(p)) // args + (a = disjunction_rule(p)) // disjunction && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (_keyword = _PyPegen_expect_token(p, 510)) // token='if' && - (args_var = args_rule(p)) // args + (b = disjunction_rule(p)) // disjunction + && + (_keyword_1 = _PyPegen_expect_token(p, 516)) // token='else' + && + (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args")); - _res = _PyPegen_arguments_parsing_error ( p , a ); + D(fprintf(stderr, "%*c+ expression_without_invalid[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + p->level--; + return NULL; + } + int _end_lineno = _token->end_lineno; + UNUSED(_end_lineno); // Only used by EXTRA macro + int _end_col_offset = _token->end_col_offset; + UNUSED(_end_col_offset); // Only used by EXTRA macro + _res = _PyAST_IfExp ( b , a , c , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' args")); + D(fprintf(stderr, "%*c%s expression_without_invalid[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction 'if' disjunction 'else' expression")); + } + { // disjunction + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction")); + expr_ty disjunction_var; + if ( + (disjunction_var = disjunction_rule(p)) // disjunction + ) + { + D(fprintf(stderr, "%*c+ expression_without_invalid[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction")); + _res = disjunction_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s expression_without_invalid[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction")); + } + { // lambdef + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> expression_without_invalid[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambdef")); + expr_ty lambdef_var; + if ( + (lambdef_var = lambdef_rule(p)) // lambdef + ) + { + D(fprintf(stderr, "%*c+ expression_without_invalid[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambdef")); + _res = lambdef_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s expression_without_invalid[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambdef")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// invalid_kwarg: expression '=' +// invalid_legacy_expression: NAME !'(' star_expressions static void * -invalid_kwarg_rule(Parser *p) +invalid_legacy_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; - { // expression '=' + { // NAME !'(' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_kwarg[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression '='")); + D(fprintf(stderr, "%*c> invalid_legacy_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); expr_ty a; - Token * b; + expr_ty b; if ( - (a = expression_rule(p)) // expression + (a = _PyPegen_name_token(p)) // NAME && - (b = _PyPegen_expect_token(p, 22)) // token='=' + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 7) // token='(' + && + (b = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ invalid_kwarg[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression '='")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expression cannot contain assignment, perhaps you meant \"==\"?" ); + D(fprintf(stderr, "%*c+ invalid_legacy_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME !'(' star_expressions")); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "Missing parentheses in call to '%U'. Did you mean %U(...)?" , a -> v . Name . id , a -> v . Name . id ) : NULL; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_kwarg[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression '='")); + D(fprintf(stderr, "%*c%s invalid_legacy_expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME !'(' star_expressions")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// invalid_expression: !(NAME STRING | SOFT_KEYWORD) disjunction expression +// invalid_expression: +// | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid +// | disjunction 'if' disjunction !('else' | ':') static void * invalid_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; - { // !(NAME STRING | SOFT_KEYWORD) disjunction expression + { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression")); + D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_143_rule, p) + _PyPegen_lookahead(0, _tmp_144_rule, p) && (a = disjunction_rule(p)) // disjunction && - (b = expression_rule(p)) // expression + (b = expression_without_invalid_rule(p)) // expression_without_invalid + ) + { + D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); + _res = _PyPegen_check_legacy_stmt ( p , a ) ? NULL : p -> tokens [ p -> mark - 1 ] -> level == 0 ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid")); + } + { // disjunction 'if' disjunction !('else' | ':') + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); + Token * _keyword; + expr_ty a; + expr_ty b; + if ( + (a = disjunction_rule(p)) // disjunction + && + (_keyword = _PyPegen_expect_token(p, 510)) // token='if' + && + (b = disjunction_rule(p)) // disjunction + && + _PyPegen_lookahead(0, _tmp_145_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Perhaps you forgot a comma?" ); + D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } // invalid_named_expression: // | expression ':=' expression -// | NAME '=' bitwise_or !('=' | ':=' | ',') -// | !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=' | ',') +// | NAME '=' bitwise_or !('=' | ':=') +// | !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=') static void * invalid_named_expression_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ':=' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':=' expression")); @@ -18405,7 +18977,7 @@ invalid_named_expression_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18414,12 +18986,12 @@ invalid_named_expression_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_named_expression[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ':=' expression")); } - { // NAME '=' bitwise_or !('=' | ':=' | ',') + { // NAME '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=' | ',')")); + D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); Token * _literal; expr_ty a; expr_ty b; @@ -18430,33 +19002,33 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_144_rule, p) + _PyPegen_lookahead(0, _tmp_146_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=' | ',')")); - _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); + D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); + _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "invalid syntax. Maybe you meant '==' or ':=' instead of '='?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=' | ',')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); } - { // !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=' | ',') + { // !(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=' | ',')")); + D(fprintf(stderr, "%*c> invalid_named_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); expr_ty a; Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_145_rule, p) + _PyPegen_lookahead(0, _tmp_147_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -18464,25 +19036,25 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_146_rule, p) + _PyPegen_lookahead(0, _tmp_148_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=' | ',')")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); + D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); + _res = p -> in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s here. Maybe you meant '==' instead of '='?" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_named_expression[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=' | ',')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18496,16 +19068,19 @@ invalid_named_expression_rule(Parser *p) static void * invalid_assignment_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // invalid_ann_assign_target ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_ann_assign_target ':' expression")); @@ -18524,7 +19099,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not %s) can be annotated" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18535,13 +19110,13 @@ invalid_assignment_rule(Parser *p) } { // star_named_expression ',' star_named_expressions* ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_147_var; + asdl_seq * _loop0_149_var; expr_ty a; expr_ty expression_var; if ( @@ -18549,7 +19124,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_147_var = _loop0_147_rule(p)) // star_named_expressions* + (_loop0_149_var = _loop0_149_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -18560,7 +19135,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "only single target (not tuple) can be annotated" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18571,7 +19146,7 @@ invalid_assignment_rule(Parser *p) } { // expression ':' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' expression")); @@ -18590,7 +19165,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal target for annotation" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18601,15 +19176,15 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* star_expressions '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_148_var; + asdl_seq * _loop0_150_var; expr_ty a; if ( - (_loop0_148_var = _loop0_148_rule(p)) // ((star_targets '='))* + (_loop0_150_var = _loop0_150_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -18620,7 +19195,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18631,15 +19206,15 @@ invalid_assignment_rule(Parser *p) } { // ((star_targets '='))* yield_expr '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_149_var; + asdl_seq * _loop0_151_var; expr_ty a; if ( - (_loop0_149_var = _loop0_149_rule(p)) // ((star_targets '='))* + (_loop0_151_var = _loop0_151_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -18650,7 +19225,7 @@ invalid_assignment_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "assignment to yield expression not possible" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18661,11 +19236,11 @@ invalid_assignment_rule(Parser *p) } { // star_expressions augassign (yield_expr | star_expressions) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_150_var; + void *_tmp_152_var; expr_ty a; AugOperator* augassign_var; if ( @@ -18673,14 +19248,14 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_150_var = _tmp_150_rule(p)) // yield_expr | star_expressions + (_tmp_152_var = _tmp_152_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18691,7 +19266,7 @@ invalid_assignment_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18699,16 +19274,19 @@ invalid_assignment_rule(Parser *p) static expr_ty invalid_ann_assign_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } expr_ty _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -18727,7 +19305,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -18746,7 +19324,7 @@ invalid_ann_assign_target_rule(Parser *p) } { // '(' invalid_ann_assign_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_ann_assign_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' invalid_ann_assign_target ')'")); @@ -18765,7 +19343,7 @@ invalid_ann_assign_target_rule(Parser *p) _res = a; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18776,7 +19354,7 @@ invalid_ann_assign_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18784,16 +19362,19 @@ invalid_ann_assign_target_rule(Parser *p) static void * invalid_del_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'del' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_del_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'del' star_expressions")); @@ -18809,7 +19390,7 @@ invalid_del_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18820,7 +19401,7 @@ invalid_del_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -18828,16 +19409,19 @@ invalid_del_stmt_rule(Parser *p) static void * invalid_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE !INDENT")); @@ -18852,7 +19436,7 @@ invalid_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18863,52 +19447,7 @@ invalid_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); - return _res; -} - -// Left-recursive -// invalid_primary: primary '{' -static void * -invalid_primary_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // primary '{' - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> invalid_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '{'")); - Token * a; - expr_ty primary_var; - if ( - (primary_var = primary_rule(p)) // primary - && - (a = _PyPegen_expect_token(p, 25)) // token='{' - ) - { - D(fprintf(stderr, "%*c+ invalid_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '{'")); - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid syntax" ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s invalid_primary[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "primary '{'")); - } - _res = NULL; - done: - D(p->level--); + p->level--; return _res; } @@ -18919,24 +19458,27 @@ invalid_primary_rule(Parser *p) static void * invalid_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_151_var; + void *_tmp_153_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_151_var = _tmp_151_rule(p)) // '[' | '(' | '{' + (_tmp_153_var = _tmp_153_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -18947,7 +19489,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "iterable unpacking cannot be used in comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18958,17 +19500,17 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_152_var; + void *_tmp_154_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_152_var = _tmp_152_rule(p)) // '[' | '{' + (_tmp_154_var = _tmp_154_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -18983,7 +19525,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , PyPegen_last_item ( b , expr_ty ) , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -18994,16 +19536,16 @@ invalid_comprehension_rule(Parser *p) } { // ('[' | '{') star_named_expression ',' for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_153_var; + void *_tmp_155_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_153_var = _tmp_153_rule(p)) // '[' | '{' + (_tmp_155_var = _tmp_155_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -19016,7 +19558,7 @@ invalid_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "did you forget parentheses around the comprehension target?" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19027,7 +19569,7 @@ invalid_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19035,16 +19577,19 @@ invalid_comprehension_rule(Parser *p) static void * invalid_dict_comprehension_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '{' '**' bitwise_or for_if_clauses '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_dict_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' '**' bitwise_or for_if_clauses '}'")); @@ -19069,7 +19614,7 @@ invalid_dict_comprehension_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "dict unpacking cannot be used in dict comprehension" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19080,7 +19625,7 @@ invalid_dict_comprehension_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19088,24 +19633,27 @@ invalid_dict_comprehension_rule(Parser *p) static void * invalid_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // param_no_default* invalid_parameters_helper param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_154_var; + asdl_seq * _loop0_156_var; arg_ty a; void *invalid_parameters_helper_var; if ( - (_loop0_154_var = _loop0_154_rule(p)) // param_no_default* + (_loop0_156_var = _loop0_156_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -19116,7 +19664,7 @@ invalid_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19127,7 +19675,7 @@ invalid_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19135,16 +19683,19 @@ invalid_parameters_rule(Parser *p) static void * invalid_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); @@ -19157,7 +19708,7 @@ invalid_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19168,17 +19719,17 @@ invalid_parameters_helper_rule(Parser *p) } { // param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_155_var; + asdl_seq * _loop1_157_var; if ( - (_loop1_155_var = _loop1_155_rule(p)) // param_with_default+ + (_loop1_157_var = _loop1_157_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_155_var; + _res = _loop1_157_var; goto done; } p->mark = _mark; @@ -19187,7 +19738,7 @@ invalid_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19196,24 +19747,27 @@ invalid_parameters_helper_rule(Parser *p) static void * invalid_lambda_parameters_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_156_var; + asdl_seq * _loop0_158_var; arg_ty a; void *invalid_lambda_parameters_helper_var; if ( - (_loop0_156_var = _loop0_156_rule(p)) // lambda_param_no_default* + (_loop0_158_var = _loop0_158_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -19224,7 +19778,7 @@ invalid_lambda_parameters_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "non-default argument follows default argument" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19235,7 +19789,7 @@ invalid_lambda_parameters_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19245,16 +19799,19 @@ invalid_lambda_parameters_rule(Parser *p) static void * invalid_lambda_parameters_helper_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // lambda_slash_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); @@ -19267,7 +19824,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) _res = _PyPegen_singleton_seq ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19278,17 +19835,17 @@ invalid_lambda_parameters_helper_rule(Parser *p) } { // lambda_param_with_default+ if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_157_var; + asdl_seq * _loop1_159_var; if ( - (_loop1_157_var = _loop1_157_rule(p)) // lambda_param_with_default+ + (_loop1_159_var = _loop1_159_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_157_var; + _res = _loop1_159_var; goto done; } p->mark = _mark; @@ -19297,7 +19854,7 @@ invalid_lambda_parameters_helper_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19305,32 +19862,35 @@ invalid_lambda_parameters_helper_rule(Parser *p) static void * invalid_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_158_var; + void *_tmp_160_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_158_var = _tmp_158_rule(p)) // ')' | ',' (')' | '**') + (_tmp_160_var = _tmp_160_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19341,7 +19901,7 @@ invalid_star_etc_rule(Parser *p) } { // '*' ',' TYPE_COMMENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' ',' TYPE_COMMENT")); @@ -19360,7 +19920,7 @@ invalid_star_etc_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19371,7 +19931,7 @@ invalid_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19379,32 +19939,35 @@ invalid_star_etc_rule(Parser *p) static void * invalid_lambda_star_etc_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_159_var; + void *_tmp_161_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_159_var = _tmp_159_rule(p)) // ':' | ',' (':' | '**') + (_tmp_161_var = _tmp_161_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19415,7 +19978,7 @@ invalid_lambda_star_etc_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19423,16 +19986,19 @@ invalid_lambda_star_etc_rule(Parser *p) static void * invalid_double_type_comments_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_type_comments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT")); @@ -19457,7 +20023,7 @@ invalid_double_type_comments_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "Cannot have two type comments on def" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19468,7 +20034,7 @@ invalid_double_type_comments_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19476,16 +20042,19 @@ invalid_double_type_comments_rule(Parser *p) static void * invalid_with_item_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression 'as' expression &(',' | ')' | ':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -19499,14 +20068,14 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_160_rule, p) + _PyPegen_lookahead(1, _tmp_162_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( STAR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19517,7 +20086,7 @@ invalid_with_item_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19525,16 +20094,19 @@ invalid_with_item_rule(Parser *p) static void * invalid_for_target_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_expressions")); @@ -19543,7 +20115,7 @@ invalid_for_target_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings expr_ty a; if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (_keyword = _PyPegen_expect_token(p, 517)) // token='for' && @@ -19554,7 +20126,7 @@ invalid_for_target_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( FOR_TARGETS , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19565,7 +20137,7 @@ invalid_for_target_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19573,16 +20145,19 @@ invalid_for_target_rule(Parser *p) static void * invalid_group_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' starred_expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' starred_expression ')'")); @@ -19601,7 +20176,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19612,7 +20187,7 @@ invalid_group_rule(Parser *p) } { // '(' '**' expression ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' '**' expression ')'")); @@ -19634,7 +20209,7 @@ invalid_group_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use double starred expression here" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19645,51 +20220,57 @@ invalid_group_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// invalid_import_from_targets: import_from_as_names ',' +// invalid_import_from_targets: import_from_as_names ',' NEWLINE static void * invalid_import_from_targets_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; - { // import_from_as_names ',' + { // import_from_as_names ',' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names ','")); + D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); Token * _literal; asdl_alias_seq* import_from_as_names_var; + Token * newline_var; if ( (import_from_as_names_var = import_from_as_names_rule(p)) // import_from_as_names && (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_names ','")); + D(fprintf(stderr, "%*c+ invalid_import_from_targets[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_names ',' NEWLINE")); _res = RAISE_SYNTAX_ERROR ( "trailing comma not allowed without surrounding parentheses" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_import_from_targets[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_names ','")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_names ',' NEWLINE")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19699,36 +20280,39 @@ invalid_import_from_targets_rule(Parser *p) static void * invalid_with_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - asdl_seq * _gather_161_var; + asdl_seq * _gather_163_var; Token * _keyword; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (_keyword = _PyPegen_expect_token(p, 519)) // token='with' && - (_gather_161_var = _gather_161_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_163_var = _gather_163_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_161_var, _literal); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _gather_163_var, _literal); goto done; } p->mark = _mark; @@ -19737,11 +20321,11 @@ invalid_with_stmt_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - asdl_seq * _gather_163_var; + asdl_seq * _gather_165_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -19751,15 +20335,15 @@ invalid_with_stmt_rule(Parser *p) void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (_keyword = _PyPegen_expect_token(p, 519)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_163_var = _gather_163_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_165_var = _gather_165_rule(p)) // ','.(expressions ['as' star_target])+ && - (_opt_var_1 = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -19767,7 +20351,7 @@ invalid_with_stmt_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_with_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'")); - _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_163_var, _opt_var_1, _literal_1, _literal_2); + _res = _PyPegen_dummy_name(p, _opt_var, _keyword, _literal, _gather_165_var, _opt_var_1, _literal_1, _literal_2); goto done; } p->mark = _mark; @@ -19776,7 +20360,7 @@ invalid_with_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19786,31 +20370,34 @@ invalid_with_stmt_rule(Parser *p) static void * invalid_with_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_165_var; + asdl_seq * _gather_167_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (a = _PyPegen_expect_token(p, 519)) // token='with' && - (_gather_165_var = _gather_165_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_167_var = _gather_167_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -19823,7 +20410,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19834,11 +20421,11 @@ invalid_with_stmt_indent_rule(Parser *p) } { // ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_167_var; + asdl_seq * _gather_169_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -19849,15 +20436,15 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (a = _PyPegen_expect_token(p, 519)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_167_var = _gather_167_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_169_var = _gather_169_rule(p)) // ','.(expressions ['as' star_target])+ && - (_opt_var_1 = _PyPegen_expect_token(p, 12), 1) // ','? + (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && @@ -19872,7 +20459,7 @@ invalid_with_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'with' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19883,56 +20470,91 @@ invalid_with_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// invalid_try_stmt: 'try' ':' NEWLINE !INDENT +// invalid_try_stmt: 'try' ':' NEWLINE !INDENT | 'try' ':' block !('except' | 'finally') static void * invalid_try_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - void * _res = NULL; - int _mark = p->mark; - { // 'try' ':' NEWLINE !INDENT + void * _res = NULL; + int _mark = p->mark; + { // 'try' ':' NEWLINE !INDENT + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); + Token * _literal; + Token * a; + Token * newline_var; + if ( + (a = _PyPegen_expect_token(p, 511)) // token='try' + && + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT + ) + { + D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); + _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_try_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' ':' NEWLINE !INDENT")); + } + { // 'try' ':' block !('except' | 'finally') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); + D(fprintf(stderr, "%*c> invalid_try_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); + Token * _keyword; Token * _literal; - Token * a; - Token * newline_var; + asdl_stmt_seq* block_var; if ( - (a = _PyPegen_expect_token(p, 511)) // token='try' + (_keyword = _PyPegen_expect_token(p, 511)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + (block_var = block_rule(p)) // block && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, INDENT) // token=INDENT + _PyPegen_lookahead(0, _tmp_171_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' NEWLINE !INDENT")); - _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'try' statement on line %d" , a -> lineno ); + D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); + _res = RAISE_SYNTAX_ERROR ( "expected 'except' or 'finally' block" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_try_stmt[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' ':' NEWLINE !INDENT")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'try' ':' block !('except' | 'finally')")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -19943,16 +20565,19 @@ invalid_try_stmt_rule(Parser *p) static void * invalid_except_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' expression ',' expressions ['as' NAME] ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); @@ -19972,16 +20597,16 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_169_rule(p), 1) // ['as' NAME] + (_opt_var = _tmp_172_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' expression ',' expressions ['as' NAME] ':'")); - _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "exception group must be parenthesized" ); + _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "multiple exception types must be parenthesized" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -19992,7 +20617,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' expression ['as' NAME] NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] NEWLINE")); @@ -20006,7 +20631,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_170_rule(p), 1) // ['as' NAME] + (_opt_var = _tmp_173_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -20015,7 +20640,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20026,7 +20651,7 @@ invalid_except_stmt_rule(Parser *p) } { // 'except' NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' NEWLINE")); @@ -20042,7 +20667,7 @@ invalid_except_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20053,7 +20678,7 @@ invalid_except_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20061,16 +20686,19 @@ invalid_except_stmt_rule(Parser *p) static void * invalid_finally_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'finally' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_finally_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally' ':' NEWLINE !INDENT")); @@ -20091,7 +20719,7 @@ invalid_finally_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'finally' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20102,7 +20730,7 @@ invalid_finally_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20112,16 +20740,19 @@ invalid_finally_stmt_rule(Parser *p) static void * invalid_except_stmt_indent_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'except' expression ['as' NAME] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' expression ['as' NAME] ':' NEWLINE !INDENT")); @@ -20136,7 +20767,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_171_rule(p), 1) // ['as' NAME] + (_opt_var = _tmp_174_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20149,7 +20780,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'except' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20160,7 +20791,7 @@ invalid_except_stmt_indent_rule(Parser *p) } { // 'except' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_except_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' ':' NEWLINE !INDENT")); @@ -20181,7 +20812,7 @@ invalid_except_stmt_indent_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected an indented block after except statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20192,7 +20823,7 @@ invalid_except_stmt_indent_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20202,16 +20833,19 @@ invalid_except_stmt_indent_rule(Parser *p) static void * invalid_match_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "match" subject_expr !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr !':'")); @@ -20229,7 +20863,7 @@ invalid_match_stmt_rule(Parser *p) _res = CHECK_VERSION ( void * , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20240,7 +20874,7 @@ invalid_match_stmt_rule(Parser *p) } { // "match" subject_expr ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT")); @@ -20264,7 +20898,7 @@ invalid_match_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'match' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20275,7 +20909,7 @@ invalid_match_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20285,16 +20919,19 @@ invalid_match_stmt_rule(Parser *p) static void * invalid_case_block_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // "case" patterns guard? !':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? !':'")); @@ -20307,7 +20944,7 @@ invalid_case_block_rule(Parser *p) && (patterns_var = patterns_rule(p)) // patterns && - (_opt_var = guard_rule(p), 1) // guard? + (_opt_var = guard_rule(p), !p->error_indicator) // guard? && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 11) // token=':' ) @@ -20316,7 +20953,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20327,7 +20964,7 @@ invalid_case_block_rule(Parser *p) } { // "case" patterns guard? ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_case_block[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' NEWLINE !INDENT")); @@ -20342,7 +20979,7 @@ invalid_case_block_rule(Parser *p) && (patterns_var = patterns_rule(p)) // patterns && - (_opt_var = guard_rule(p), 1) // guard? + (_opt_var = guard_rule(p), !p->error_indicator) // guard? && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20355,7 +20992,7 @@ invalid_case_block_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'case' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20366,7 +21003,194 @@ invalid_case_block_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; + return _res; +} + +// invalid_as_pattern: or_pattern 'as' "_" | or_pattern 'as' !NAME expression +static void * +invalid_as_pattern_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // or_pattern 'as' "_" + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); + Token * _keyword; + expr_ty a; + pattern_ty or_pattern_var; + if ( + (or_pattern_var = or_pattern_rule(p)) // or_pattern + && + (_keyword = _PyPegen_expect_token(p, 520)) // token='as' + && + (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' + ) + { + D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' \"_\"")); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot use '_' as a target" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_as_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "or_pattern 'as' \"_\"")); + } + { // or_pattern 'as' !NAME expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_as_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' !NAME expression")); + Token * _keyword; + expr_ty a; + pattern_ty or_pattern_var; + if ( + (or_pattern_var = or_pattern_rule(p)) // or_pattern + && + (_keyword = _PyPegen_expect_token(p, 520)) // token='as' + && + _PyPegen_lookahead_with_name(0, _PyPegen_name_token, p) + && + (a = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ invalid_as_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "or_pattern 'as' !NAME expression")); + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid pattern target" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_as_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "or_pattern 'as' !NAME expression")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// invalid_class_pattern: name_or_attr '(' invalid_class_argument_pattern +static void * +invalid_class_pattern_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // name_or_attr '(' invalid_class_argument_pattern + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_class_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); + Token * _literal; + asdl_pattern_seq* a; + expr_ty name_or_attr_var; + if ( + (name_or_attr_var = name_or_attr_rule(p)) // name_or_attr + && + (_literal = _PyPegen_expect_token(p, 7)) // token='(' + && + (a = invalid_class_argument_pattern_rule(p)) // invalid_class_argument_pattern + ) + { + D(fprintf(stderr, "%*c+ invalid_class_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_class_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "name_or_attr '(' invalid_class_argument_pattern")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// invalid_class_argument_pattern: +// | [positional_patterns ','] keyword_patterns ',' positional_patterns +static asdl_pattern_seq* +invalid_class_argument_pattern_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_pattern_seq* _res = NULL; + int _mark = p->mark; + { // [positional_patterns ','] keyword_patterns ',' positional_patterns + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_class_argument_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); + Token * _literal; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + asdl_pattern_seq* a; + asdl_seq* keyword_patterns_var; + if ( + (_opt_var = _tmp_175_rule(p), !p->error_indicator) // [positional_patterns ','] + && + (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (a = positional_patterns_rule(p)) // positional_patterns + ) + { + D(fprintf(stderr, "%*c+ invalid_class_argument_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); + _res = a; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_class_argument_pattern[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "[positional_patterns ','] keyword_patterns ',' positional_patterns")); + } + _res = NULL; + done: + p->level--; return _res; } @@ -20376,16 +21200,19 @@ invalid_case_block_rule(Parser *p) static void * invalid_if_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression NEWLINE")); @@ -20404,7 +21231,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20415,7 +21242,7 @@ invalid_if_stmt_rule(Parser *p) } { // 'if' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_if_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' named_expression ':' NEWLINE !INDENT")); @@ -20439,7 +21266,7 @@ invalid_if_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'if' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20450,7 +21277,7 @@ invalid_if_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20460,16 +21287,19 @@ invalid_if_stmt_rule(Parser *p) static void * invalid_elif_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'elif' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression NEWLINE")); @@ -20488,7 +21318,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20499,7 +21329,7 @@ invalid_elif_stmt_rule(Parser *p) } { // 'elif' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_elif_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'elif' named_expression ':' NEWLINE !INDENT")); @@ -20523,7 +21353,7 @@ invalid_elif_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'elif' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20534,7 +21364,7 @@ invalid_elif_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20542,16 +21372,19 @@ invalid_elif_stmt_rule(Parser *p) static void * invalid_else_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'else' ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_else_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else' ':' NEWLINE !INDENT")); @@ -20572,7 +21405,7 @@ invalid_else_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'else' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20583,7 +21416,7 @@ invalid_else_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20593,16 +21426,19 @@ invalid_else_stmt_rule(Parser *p) static void * invalid_while_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'while' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression NEWLINE")); @@ -20621,7 +21457,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_SYNTAX_ERROR ( "expected ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20632,7 +21468,7 @@ invalid_while_stmt_rule(Parser *p) } { // 'while' named_expression ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_while_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'while' named_expression ':' NEWLINE !INDENT")); @@ -20656,7 +21492,7 @@ invalid_while_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'while' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20667,7 +21503,7 @@ invalid_while_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20675,16 +21511,19 @@ invalid_while_stmt_rule(Parser *p) static void * invalid_for_stmt_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_for_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT")); @@ -20697,7 +21536,7 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (a = _PyPegen_expect_token(p, 517)) // token='for' && @@ -20718,7 +21557,7 @@ invalid_for_stmt_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after 'for' statement on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20729,7 +21568,7 @@ invalid_for_stmt_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20738,16 +21577,19 @@ invalid_for_stmt_rule(Parser *p) static void * invalid_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'def' NAME '(' params? ')' ['->' expression] ':' NEWLINE !INDENT")); @@ -20764,7 +21606,7 @@ invalid_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, ASYNC), 1) // ASYNC? + (_opt_var = _PyPegen_expect_token(p, ASYNC), !p->error_indicator) // ASYNC? && (a = _PyPegen_expect_token(p, 526)) // token='def' && @@ -20772,11 +21614,11 @@ invalid_def_raw_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_opt_var_1 = params_rule(p), 1) // params? + (_opt_var_1 = params_rule(p), !p->error_indicator) // params? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_172_rule(p), 1) // ['->' expression] + (_opt_var_2 = _tmp_176_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20789,7 +21631,7 @@ invalid_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after function definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20800,7 +21642,7 @@ invalid_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20808,16 +21650,19 @@ invalid_def_raw_rule(Parser *p) static void * invalid_class_def_raw_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' NEWLINE !INDENT")); @@ -20832,7 +21677,7 @@ invalid_class_def_raw_rule(Parser *p) && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_173_rule(p), 1) // ['(' arguments? ')'] + (_opt_var = _tmp_177_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20845,7 +21690,7 @@ invalid_class_def_raw_rule(Parser *p) _res = RAISE_INDENTATION_ERROR ( "expected an indented block after class definition on line %d" , a -> lineno ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20856,7 +21701,7 @@ invalid_class_def_raw_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20867,24 +21712,27 @@ invalid_class_def_raw_rule(Parser *p) static void * invalid_double_starred_kvpairs_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ','.double_starred_kvpair+ ',' invalid_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_174_var; + asdl_seq * _gather_178_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_174_var = _gather_174_rule(p)) // ','.double_starred_kvpair+ + (_gather_178_var = _gather_178_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -20892,7 +21740,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_174_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_178_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -20901,7 +21749,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -20923,7 +21771,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20934,7 +21782,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } { // expression ':' &('}' | ',') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -20945,14 +21793,14 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_176_rule, p) + _PyPegen_lookahead(1, _tmp_180_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -20963,7 +21811,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -20971,16 +21819,19 @@ invalid_double_starred_kvpairs_rule(Parser *p) static void * invalid_kvpair_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression !(':') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !(':')")); @@ -20995,7 +21846,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_ERROR_KNOWN_LOCATION ( p , PyExc_SyntaxError , a -> lineno , a -> end_col_offset - 1 , a -> end_lineno , - 1 , "':' expected after dictionary key" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21006,7 +21857,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' '*' bitwise_or if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':' '*' bitwise_or")); @@ -21028,7 +21879,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( a , "cannot use a starred expression in a dictionary value" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21039,7 +21890,7 @@ invalid_kvpair_rule(Parser *p) } { // expression ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> invalid_kvpair[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ':'")); @@ -21055,7 +21906,7 @@ invalid_kvpair_rule(Parser *p) _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "expression expected after dictionary key and ':'" ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -21066,7 +21917,7 @@ invalid_kvpair_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21074,9 +21925,12 @@ invalid_kvpair_rule(Parser *p) static asdl_seq * _loop0_1_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21086,14 +21940,14 @@ _loop0_1_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_1[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21109,7 +21963,7 @@ _loop0_1_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21126,13 +21980,13 @@ _loop0_1_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_1_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21140,9 +21994,12 @@ _loop0_1_rule(Parser *p) static asdl_seq * _loop0_2_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21152,14 +22009,14 @@ _loop0_2_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -21175,7 +22032,7 @@ _loop0_2_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21192,13 +22049,13 @@ _loop0_2_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_2_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21206,9 +22063,12 @@ _loop0_2_rule(Parser *p) static asdl_seq * _loop0_4_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21218,14 +22078,14 @@ _loop0_4_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21241,7 +22101,7 @@ _loop0_4_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21250,7 +22110,7 @@ _loop0_4_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21267,13 +22127,13 @@ _loop0_4_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_4_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21281,16 +22141,19 @@ _loop0_4_rule(Parser *p) static asdl_seq * _gather_3_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_4 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_4")); @@ -21312,7 +22175,7 @@ _gather_3_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21320,9 +22183,12 @@ _gather_3_rule(Parser *p) static asdl_seq * _loop0_6_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21332,14 +22198,14 @@ _loop0_6_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21355,7 +22221,7 @@ _loop0_6_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21364,7 +22230,7 @@ _loop0_6_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21381,13 +22247,13 @@ _loop0_6_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_6_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21395,16 +22261,19 @@ _loop0_6_rule(Parser *p) static asdl_seq * _gather_5_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_6 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_6")); @@ -21426,7 +22295,7 @@ _gather_5_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21434,9 +22303,12 @@ _gather_5_rule(Parser *p) static asdl_seq * _loop0_8_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21446,14 +22318,14 @@ _loop0_8_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21469,7 +22341,7 @@ _loop0_8_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21478,7 +22350,7 @@ _loop0_8_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21495,13 +22367,13 @@ _loop0_8_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_8_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21509,16 +22381,19 @@ _loop0_8_rule(Parser *p) static asdl_seq * _gather_7_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_8 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_8")); @@ -21540,7 +22415,7 @@ _gather_7_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21548,9 +22423,12 @@ _gather_7_rule(Parser *p) static asdl_seq * _loop0_10_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21560,14 +22438,14 @@ _loop0_10_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -21583,7 +22461,7 @@ _loop0_10_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21592,7 +22470,7 @@ _loop0_10_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21609,13 +22487,13 @@ _loop0_10_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_10_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21623,16 +22501,19 @@ _loop0_10_rule(Parser *p) static asdl_seq * _gather_9_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // expression _loop0_10 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_10")); @@ -21654,7 +22535,7 @@ _gather_9_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21662,9 +22543,12 @@ _gather_9_rule(Parser *p) static asdl_seq * _loop1_11_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21674,14 +22558,14 @@ _loop1_11_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // statement if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); @@ -21697,7 +22581,7 @@ _loop1_11_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21711,7 +22595,7 @@ _loop1_11_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -21719,13 +22603,13 @@ _loop1_11_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_11_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21733,9 +22617,12 @@ _loop1_11_rule(Parser *p) static asdl_seq * _loop0_13_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -21745,14 +22632,14 @@ _loop0_13_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ';' simple_stmt if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); @@ -21768,7 +22655,7 @@ _loop0_13_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -21777,7 +22664,7 @@ _loop0_13_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -21794,13 +22681,13 @@ _loop0_13_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_13_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -21808,16 +22695,19 @@ _loop0_13_rule(Parser *p) static asdl_seq * _gather_12_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // simple_stmt _loop0_13 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_13")); @@ -21839,7 +22729,7 @@ _gather_12_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21847,16 +22737,19 @@ _gather_12_rule(Parser *p) static void * _tmp_14_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'import' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); @@ -21875,7 +22768,7 @@ _tmp_14_rule(Parser *p) } { // 'from' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); @@ -21894,7 +22787,7 @@ _tmp_14_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21902,16 +22795,19 @@ _tmp_14_rule(Parser *p) static void * _tmp_15_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'def' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -21930,7 +22826,7 @@ _tmp_15_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -21949,7 +22845,7 @@ _tmp_15_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -21968,7 +22864,7 @@ _tmp_15_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -21976,16 +22872,19 @@ _tmp_15_rule(Parser *p) static void * _tmp_16_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'class' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -22004,7 +22903,7 @@ _tmp_16_rule(Parser *p) } { // '@' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); @@ -22023,7 +22922,7 @@ _tmp_16_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22031,16 +22930,19 @@ _tmp_16_rule(Parser *p) static void * _tmp_17_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'with' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -22059,7 +22961,7 @@ _tmp_17_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22078,7 +22980,7 @@ _tmp_17_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22086,16 +22988,19 @@ _tmp_17_rule(Parser *p) static void * _tmp_18_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'for' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -22114,7 +23019,7 @@ _tmp_18_rule(Parser *p) } { // ASYNC if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC")); @@ -22133,7 +23038,7 @@ _tmp_18_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22141,16 +23046,19 @@ _tmp_18_rule(Parser *p) static void * _tmp_19_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22166,7 +23074,7 @@ _tmp_19_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22177,7 +23085,7 @@ _tmp_19_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22185,16 +23093,19 @@ _tmp_19_rule(Parser *p) static void * _tmp_20_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' single_target ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); @@ -22213,7 +23124,7 @@ _tmp_20_rule(Parser *p) _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22224,7 +23135,7 @@ _tmp_20_rule(Parser *p) } { // single_subscript_attribute_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); @@ -22243,7 +23154,7 @@ _tmp_20_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22251,16 +23162,19 @@ _tmp_20_rule(Parser *p) static void * _tmp_21_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' annotated_rhs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); @@ -22276,7 +23190,7 @@ _tmp_21_rule(Parser *p) _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22287,7 +23201,7 @@ _tmp_21_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22295,9 +23209,12 @@ _tmp_21_rule(Parser *p) static asdl_seq * _loop1_22_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22307,30 +23224,30 @@ _loop1_22_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_177_var; + void *_tmp_181_var; while ( - (_tmp_177_var = _tmp_177_rule(p)) // star_targets '=' + (_tmp_181_var = _tmp_181_rule(p)) // star_targets '=' ) { - _res = _tmp_177_var; + _res = _tmp_181_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22344,7 +23261,7 @@ _loop1_22_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -22352,13 +23269,13 @@ _loop1_22_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_22_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22366,16 +23283,19 @@ _loop1_22_rule(Parser *p) static void * _tmp_23_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22394,7 +23314,7 @@ _tmp_23_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22413,7 +23333,7 @@ _tmp_23_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22421,16 +23341,19 @@ _tmp_23_rule(Parser *p) static void * _tmp_24_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -22449,7 +23372,7 @@ _tmp_24_rule(Parser *p) } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); @@ -22468,7 +23391,7 @@ _tmp_24_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22476,9 +23399,12 @@ _tmp_24_rule(Parser *p) static asdl_seq * _loop0_26_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22488,14 +23414,14 @@ _loop0_26_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22511,7 +23437,7 @@ _loop0_26_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22520,7 +23446,7 @@ _loop0_26_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22537,13 +23463,13 @@ _loop0_26_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_26_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22551,16 +23477,19 @@ _loop0_26_rule(Parser *p) static asdl_seq * _gather_25_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_26 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_26")); @@ -22582,7 +23511,7 @@ _gather_25_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22590,9 +23519,12 @@ _gather_25_rule(Parser *p) static asdl_seq * _loop0_28_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22602,14 +23534,14 @@ _loop0_28_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); @@ -22625,7 +23557,7 @@ _loop0_28_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22634,7 +23566,7 @@ _loop0_28_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22651,13 +23583,13 @@ _loop0_28_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_28_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22665,16 +23597,19 @@ _loop0_28_rule(Parser *p) static asdl_seq * _gather_27_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // NAME _loop0_28 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_28")); @@ -22696,7 +23631,7 @@ _gather_27_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22704,16 +23639,19 @@ _gather_27_rule(Parser *p) static void * _tmp_29_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); @@ -22729,7 +23667,7 @@ _tmp_29_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -22740,7 +23678,7 @@ _tmp_29_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22748,16 +23686,19 @@ _tmp_29_rule(Parser *p) static void * _tmp_30_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ';' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); @@ -22776,7 +23717,7 @@ _tmp_30_rule(Parser *p) } { // NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); @@ -22795,7 +23736,7 @@ _tmp_30_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -22803,9 +23744,12 @@ _tmp_30_rule(Parser *p) static asdl_seq * _loop0_31_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22815,30 +23759,30 @@ _loop0_31_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_178_var; + void *_tmp_182_var; while ( - (_tmp_178_var = _tmp_178_rule(p)) // '.' | '...' + (_tmp_182_var = _tmp_182_rule(p)) // '.' | '...' ) { - _res = _tmp_178_var; + _res = _tmp_182_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22855,13 +23799,13 @@ _loop0_31_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_31_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22869,9 +23813,12 @@ _loop0_31_rule(Parser *p) static asdl_seq * _loop1_32_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22881,30 +23828,30 @@ _loop1_32_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('.' | '...') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_179_var; + void *_tmp_183_var; while ( - (_tmp_179_var = _tmp_179_rule(p)) // '.' | '...' + (_tmp_183_var = _tmp_183_rule(p)) // '.' | '...' ) { - _res = _tmp_179_var; + _res = _tmp_183_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -22918,7 +23865,7 @@ _loop1_32_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -22926,13 +23873,13 @@ _loop1_32_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_32_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -22940,9 +23887,12 @@ _loop1_32_rule(Parser *p) static asdl_seq * _loop0_34_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -22952,14 +23902,14 @@ _loop0_34_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' import_from_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); @@ -22975,7 +23925,7 @@ _loop0_34_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -22984,7 +23934,7 @@ _loop0_34_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23001,13 +23951,13 @@ _loop0_34_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_34_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23015,16 +23965,19 @@ _loop0_34_rule(Parser *p) static asdl_seq * _gather_33_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // import_from_as_name _loop0_34 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_34")); @@ -23046,7 +23999,7 @@ _gather_33_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23054,16 +24007,19 @@ _gather_33_rule(Parser *p) static void * _tmp_35_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23079,7 +24035,7 @@ _tmp_35_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23090,7 +24046,7 @@ _tmp_35_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23098,9 +24054,12 @@ _tmp_35_rule(Parser *p) static asdl_seq * _loop0_37_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23110,14 +24069,14 @@ _loop0_37_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' dotted_as_name if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); @@ -23133,7 +24092,7 @@ _loop0_37_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23142,7 +24101,7 @@ _loop0_37_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23159,13 +24118,13 @@ _loop0_37_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_37_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23173,16 +24132,19 @@ _loop0_37_rule(Parser *p) static asdl_seq * _gather_36_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // dotted_as_name _loop0_37 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_37")); @@ -23204,7 +24166,7 @@ _gather_36_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23212,16 +24174,19 @@ _gather_36_rule(Parser *p) static void * _tmp_38_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23237,7 +24202,7 @@ _tmp_38_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23248,7 +24213,7 @@ _tmp_38_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23256,9 +24221,12 @@ _tmp_38_rule(Parser *p) static asdl_seq * _loop0_40_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23268,14 +24236,14 @@ _loop0_40_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23291,7 +24259,7 @@ _loop0_40_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23300,7 +24268,7 @@ _loop0_40_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23317,13 +24285,13 @@ _loop0_40_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_40_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23331,16 +24299,19 @@ _loop0_40_rule(Parser *p) static asdl_seq * _gather_39_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_40 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_40")); @@ -23362,7 +24333,7 @@ _gather_39_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23370,9 +24341,12 @@ _gather_39_rule(Parser *p) static asdl_seq * _loop0_42_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23382,14 +24356,14 @@ _loop0_42_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23405,7 +24379,7 @@ _loop0_42_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23414,7 +24388,7 @@ _loop0_42_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23431,13 +24405,13 @@ _loop0_42_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_42_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23445,16 +24419,19 @@ _loop0_42_rule(Parser *p) static asdl_seq * _gather_41_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_42 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_42")); @@ -23476,7 +24453,7 @@ _gather_41_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23484,9 +24461,12 @@ _gather_41_rule(Parser *p) static asdl_seq * _loop0_44_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23496,14 +24476,14 @@ _loop0_44_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23519,7 +24499,7 @@ _loop0_44_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23528,7 +24508,7 @@ _loop0_44_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23545,13 +24525,13 @@ _loop0_44_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_44_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23559,16 +24539,19 @@ _loop0_44_rule(Parser *p) static asdl_seq * _gather_43_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_44 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_44")); @@ -23590,7 +24573,7 @@ _gather_43_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23598,9 +24581,12 @@ _gather_43_rule(Parser *p) static asdl_seq * _loop0_46_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23610,14 +24596,14 @@ _loop0_46_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' with_item if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); @@ -23633,7 +24619,7 @@ _loop0_46_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -23642,7 +24628,7 @@ _loop0_46_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23659,13 +24645,13 @@ _loop0_46_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_46_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23673,16 +24659,19 @@ _loop0_46_rule(Parser *p) static asdl_seq * _gather_45_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // with_item _loop0_46 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_46")); @@ -23704,7 +24693,7 @@ _gather_45_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23712,16 +24701,19 @@ _gather_45_rule(Parser *p) static void * _tmp_47_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); @@ -23740,7 +24732,7 @@ _tmp_47_rule(Parser *p) } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); @@ -23759,7 +24751,7 @@ _tmp_47_rule(Parser *p) } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); @@ -23778,7 +24770,7 @@ _tmp_47_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23786,9 +24778,12 @@ _tmp_47_rule(Parser *p) static asdl_seq * _loop1_48_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23798,14 +24793,14 @@ _loop1_48_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // except_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); @@ -23821,7 +24816,7 @@ _loop1_48_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23835,7 +24830,7 @@ _loop1_48_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23843,13 +24838,13 @@ _loop1_48_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_48_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23857,16 +24852,19 @@ _loop1_48_rule(Parser *p) static void * _tmp_49_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); @@ -23882,7 +24880,7 @@ _tmp_49_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -23893,7 +24891,7 @@ _tmp_49_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -23901,9 +24899,12 @@ _tmp_49_rule(Parser *p) static asdl_seq * _loop1_50_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23913,14 +24914,14 @@ _loop1_50_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // case_block if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); @@ -23936,7 +24937,7 @@ _loop1_50_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -23950,7 +24951,7 @@ _loop1_50_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -23958,13 +24959,13 @@ _loop1_50_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_50_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -23972,9 +24973,12 @@ _loop1_50_rule(Parser *p) static asdl_seq * _loop0_52_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -23984,14 +24988,14 @@ _loop0_52_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // '|' closed_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); @@ -24007,7 +25011,7 @@ _loop0_52_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24016,7 +25020,7 @@ _loop0_52_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24033,13 +25037,13 @@ _loop0_52_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_52_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24047,16 +25051,19 @@ _loop0_52_rule(Parser *p) static asdl_seq * _gather_51_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // closed_pattern _loop0_52 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_52")); @@ -24078,7 +25085,7 @@ _gather_51_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24086,16 +25093,19 @@ _gather_51_rule(Parser *p) static void * _tmp_53_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -24114,7 +25124,7 @@ _tmp_53_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -24133,7 +25143,7 @@ _tmp_53_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24141,16 +25151,19 @@ _tmp_53_rule(Parser *p) static void * _tmp_54_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '+' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); @@ -24169,7 +25182,7 @@ _tmp_54_rule(Parser *p) } { // '-' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); @@ -24188,7 +25201,7 @@ _tmp_54_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24196,16 +25209,19 @@ _tmp_54_rule(Parser *p) static void * _tmp_55_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -24224,7 +25240,7 @@ _tmp_55_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -24243,7 +25259,7 @@ _tmp_55_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -24262,7 +25278,7 @@ _tmp_55_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24270,16 +25286,19 @@ _tmp_55_rule(Parser *p) static void * _tmp_56_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); @@ -24298,7 +25317,7 @@ _tmp_56_rule(Parser *p) } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); @@ -24317,7 +25336,7 @@ _tmp_56_rule(Parser *p) } { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); @@ -24336,7 +25355,7 @@ _tmp_56_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24344,9 +25363,12 @@ _tmp_56_rule(Parser *p) static asdl_seq * _loop0_58_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24356,14 +25378,14 @@ _loop0_58_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' maybe_star_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); @@ -24379,7 +25401,7 @@ _loop0_58_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24388,7 +25410,7 @@ _loop0_58_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24405,13 +25427,13 @@ _loop0_58_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_58_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24419,16 +25441,19 @@ _loop0_58_rule(Parser *p) static asdl_seq * _gather_57_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // maybe_star_pattern _loop0_58 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_58")); @@ -24450,7 +25475,7 @@ _gather_57_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24458,9 +25483,12 @@ _gather_57_rule(Parser *p) static asdl_seq * _loop0_60_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24470,14 +25498,14 @@ _loop0_60_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' key_value_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); @@ -24493,7 +25521,7 @@ _loop0_60_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24502,7 +25530,7 @@ _loop0_60_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24519,13 +25547,13 @@ _loop0_60_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_60_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24533,16 +25561,19 @@ _loop0_60_rule(Parser *p) static asdl_seq * _gather_59_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // key_value_pattern _loop0_60 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_60")); @@ -24564,7 +25595,7 @@ _gather_59_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24572,16 +25603,19 @@ _gather_59_rule(Parser *p) static void * _tmp_61_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // literal_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); @@ -24600,7 +25634,7 @@ _tmp_61_rule(Parser *p) } { // attr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); @@ -24619,7 +25653,7 @@ _tmp_61_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24627,9 +25661,12 @@ _tmp_61_rule(Parser *p) static asdl_seq * _loop0_63_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24639,14 +25676,14 @@ _loop0_63_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); @@ -24662,7 +25699,7 @@ _loop0_63_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24671,7 +25708,7 @@ _loop0_63_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24688,13 +25725,13 @@ _loop0_63_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_63_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24702,16 +25739,19 @@ _loop0_63_rule(Parser *p) static asdl_seq * _gather_62_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // pattern _loop0_63 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_63")); @@ -24733,7 +25773,7 @@ _gather_62_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24741,9 +25781,12 @@ _gather_62_rule(Parser *p) static asdl_seq * _loop0_65_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -24753,14 +25796,14 @@ _loop0_65_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' keyword_pattern if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); @@ -24776,7 +25819,7 @@ _loop0_65_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -24785,7 +25828,7 @@ _loop0_65_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -24802,13 +25845,13 @@ _loop0_65_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_65_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -24816,16 +25859,19 @@ _loop0_65_rule(Parser *p) static asdl_seq * _gather_64_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // keyword_pattern _loop0_65 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_65")); @@ -24847,7 +25893,7 @@ _gather_64_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24855,16 +25901,19 @@ _gather_64_rule(Parser *p) static void * _tmp_66_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'from' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); @@ -24880,7 +25929,7 @@ _tmp_66_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24891,7 +25940,7 @@ _tmp_66_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24899,16 +25948,19 @@ _tmp_66_rule(Parser *p) static void * _tmp_67_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -24924,7 +25976,7 @@ _tmp_67_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24935,7 +25987,7 @@ _tmp_67_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24943,16 +25995,19 @@ _tmp_67_rule(Parser *p) static void * _tmp_68_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); @@ -24968,7 +26023,7 @@ _tmp_68_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -24979,7 +26034,7 @@ _tmp_68_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -24987,16 +26042,19 @@ _tmp_68_rule(Parser *p) static void * _tmp_69_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NEWLINE INDENT if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); @@ -25018,7 +26076,7 @@ _tmp_69_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -25026,9 +26084,12 @@ _tmp_69_rule(Parser *p) static asdl_seq * _loop0_70_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25038,14 +26099,14 @@ _loop0_70_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25061,7 +26122,7 @@ _loop0_70_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25078,13 +26139,13 @@ _loop0_70_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_70_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25092,9 +26153,12 @@ _loop0_70_rule(Parser *p) static asdl_seq * _loop0_71_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25104,14 +26168,14 @@ _loop0_71_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25127,7 +26191,7 @@ _loop0_71_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25144,13 +26208,13 @@ _loop0_71_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25158,9 +26222,12 @@ _loop0_71_rule(Parser *p) static asdl_seq * _loop0_72_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25170,14 +26237,14 @@ _loop0_72_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25193,7 +26260,7 @@ _loop0_72_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25210,13 +26277,13 @@ _loop0_72_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_72_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25224,9 +26291,12 @@ _loop0_72_rule(Parser *p) static asdl_seq * _loop1_73_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25236,14 +26306,14 @@ _loop1_73_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25259,7 +26329,7 @@ _loop1_73_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25273,7 +26343,7 @@ _loop1_73_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25281,13 +26351,13 @@ _loop1_73_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_73_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25295,9 +26365,12 @@ _loop1_73_rule(Parser *p) static asdl_seq * _loop0_74_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25307,14 +26380,14 @@ _loop0_74_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25330,7 +26403,7 @@ _loop0_74_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25347,13 +26420,13 @@ _loop0_74_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25361,9 +26434,12 @@ _loop0_74_rule(Parser *p) static asdl_seq * _loop1_75_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25373,14 +26449,14 @@ _loop1_75_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25396,7 +26472,7 @@ _loop1_75_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25410,7 +26486,7 @@ _loop1_75_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25418,13 +26494,13 @@ _loop1_75_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_75_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25432,9 +26508,12 @@ _loop1_75_rule(Parser *p) static asdl_seq * _loop1_76_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25444,14 +26523,14 @@ _loop1_76_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25467,7 +26546,7 @@ _loop1_76_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25481,7 +26560,7 @@ _loop1_76_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25489,13 +26568,13 @@ _loop1_76_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_76_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25503,9 +26582,12 @@ _loop1_76_rule(Parser *p) static asdl_seq * _loop1_77_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25515,14 +26597,14 @@ _loop1_77_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25538,7 +26620,7 @@ _loop1_77_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25552,7 +26634,7 @@ _loop1_77_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25560,13 +26642,13 @@ _loop1_77_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25574,9 +26656,12 @@ _loop1_77_rule(Parser *p) static asdl_seq * _loop0_78_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25586,14 +26671,14 @@ _loop0_78_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25609,7 +26694,7 @@ _loop0_78_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25626,13 +26711,13 @@ _loop0_78_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25640,9 +26725,12 @@ _loop0_78_rule(Parser *p) static asdl_seq * _loop1_79_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25652,14 +26740,14 @@ _loop1_79_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25675,7 +26763,7 @@ _loop1_79_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25689,7 +26777,7 @@ _loop1_79_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25697,13 +26785,13 @@ _loop1_79_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25711,9 +26799,12 @@ _loop1_79_rule(Parser *p) static asdl_seq * _loop0_80_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25723,14 +26814,14 @@ _loop0_80_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); @@ -25746,7 +26837,7 @@ _loop0_80_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25763,13 +26854,13 @@ _loop0_80_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_80_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25777,9 +26868,12 @@ _loop0_80_rule(Parser *p) static asdl_seq * _loop1_81_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25789,14 +26883,14 @@ _loop1_81_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); @@ -25812,7 +26906,7 @@ _loop1_81_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25826,7 +26920,7 @@ _loop1_81_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25834,13 +26928,13 @@ _loop1_81_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25848,9 +26942,12 @@ _loop1_81_rule(Parser *p) static asdl_seq * _loop0_82_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25860,14 +26957,14 @@ _loop0_82_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -25883,7 +26980,7 @@ _loop0_82_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25900,13 +26997,13 @@ _loop0_82_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25914,9 +27011,12 @@ _loop0_82_rule(Parser *p) static asdl_seq * _loop1_83_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25926,14 +27026,14 @@ _loop1_83_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); @@ -25949,7 +27049,7 @@ _loop1_83_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -25963,7 +27063,7 @@ _loop1_83_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -25971,13 +27071,13 @@ _loop1_83_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -25985,9 +27085,12 @@ _loop1_83_rule(Parser *p) static asdl_seq * _loop1_84_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -25997,30 +27100,30 @@ _loop1_84_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('@' named_expression NEWLINE) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_180_var; + void *_tmp_184_var; while ( - (_tmp_180_var = _tmp_180_rule(p)) // '@' named_expression NEWLINE + (_tmp_184_var = _tmp_184_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_180_var; + _res = _tmp_184_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26034,7 +27137,7 @@ _loop1_84_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26042,13 +27145,13 @@ _loop1_84_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_84_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26056,16 +27159,19 @@ _loop1_84_rule(Parser *p) static void * _tmp_85_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); @@ -26075,7 +27181,7 @@ _tmp_85_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (z = arguments_rule(p), 1) // arguments? + (z = arguments_rule(p), !p->error_indicator) // arguments? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -26084,7 +27190,7 @@ _tmp_85_rule(Parser *p) _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -26095,7 +27201,7 @@ _tmp_85_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26103,9 +27209,12 @@ _tmp_85_rule(Parser *p) static asdl_seq * _loop1_86_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26115,30 +27224,30 @@ _loop1_86_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_181_var; + void *_tmp_185_var; while ( - (_tmp_181_var = _tmp_181_rule(p)) // ',' star_expression + (_tmp_185_var = _tmp_185_rule(p)) // ',' star_expression ) { - _res = _tmp_181_var; + _res = _tmp_185_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26152,7 +27261,7 @@ _loop1_86_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26160,13 +27269,13 @@ _loop1_86_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_86_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26174,9 +27283,12 @@ _loop1_86_rule(Parser *p) static asdl_seq * _loop0_88_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26186,14 +27298,14 @@ _loop0_88_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); @@ -26209,7 +27321,7 @@ _loop0_88_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -26218,7 +27330,7 @@ _loop0_88_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26235,13 +27347,13 @@ _loop0_88_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26249,16 +27361,19 @@ _loop0_88_rule(Parser *p) static asdl_seq * _gather_87_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // star_named_expression _loop0_88 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_88")); @@ -26280,7 +27395,7 @@ _gather_87_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -26288,9 +27403,12 @@ _gather_87_rule(Parser *p) static asdl_seq * _loop1_89_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26300,30 +27418,30 @@ _loop1_89_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' expression) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_182_var; + void *_tmp_186_var; while ( - (_tmp_182_var = _tmp_182_rule(p)) // ',' expression + (_tmp_186_var = _tmp_186_rule(p)) // ',' expression ) { - _res = _tmp_182_var; + _res = _tmp_186_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26337,7 +27455,7 @@ _loop1_89_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26345,13 +27463,13 @@ _loop1_89_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26359,9 +27477,12 @@ _loop1_89_rule(Parser *p) static asdl_seq * _loop0_90_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26371,14 +27492,14 @@ _loop0_90_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26394,7 +27515,7 @@ _loop0_90_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26411,13 +27532,13 @@ _loop0_90_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_90_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26425,9 +27546,12 @@ _loop0_90_rule(Parser *p) static asdl_seq * _loop0_91_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26437,14 +27561,14 @@ _loop0_91_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26460,7 +27584,7 @@ _loop0_91_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26477,13 +27601,13 @@ _loop0_91_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_91_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26491,9 +27615,12 @@ _loop0_91_rule(Parser *p) static asdl_seq * _loop0_92_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26503,14 +27630,14 @@ _loop0_92_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26526,7 +27653,7 @@ _loop0_92_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26543,13 +27670,13 @@ _loop0_92_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_92_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26557,9 +27684,12 @@ _loop0_92_rule(Parser *p) static asdl_seq * _loop1_93_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26569,14 +27699,14 @@ _loop1_93_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26592,7 +27722,7 @@ _loop1_93_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26606,7 +27736,7 @@ _loop1_93_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26614,13 +27744,13 @@ _loop1_93_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_93_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26628,9 +27758,12 @@ _loop1_93_rule(Parser *p) static asdl_seq * _loop0_94_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26640,14 +27773,14 @@ _loop0_94_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26663,7 +27796,7 @@ _loop0_94_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26680,13 +27813,13 @@ _loop0_94_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26694,9 +27827,12 @@ _loop0_94_rule(Parser *p) static asdl_seq * _loop1_95_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26706,14 +27842,14 @@ _loop1_95_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -26729,7 +27865,7 @@ _loop1_95_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26743,7 +27879,7 @@ _loop1_95_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26751,13 +27887,13 @@ _loop1_95_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_95_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26765,9 +27901,12 @@ _loop1_95_rule(Parser *p) static asdl_seq * _loop1_96_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26777,14 +27916,14 @@ _loop1_96_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26800,7 +27939,7 @@ _loop1_96_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26814,7 +27953,7 @@ _loop1_96_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26822,13 +27961,13 @@ _loop1_96_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_96_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26836,9 +27975,12 @@ _loop1_96_rule(Parser *p) static asdl_seq * _loop1_97_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26848,14 +27990,14 @@ _loop1_97_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26871,7 +28013,7 @@ _loop1_97_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26885,7 +28027,7 @@ _loop1_97_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26893,13 +28035,13 @@ _loop1_97_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26907,9 +28049,12 @@ _loop1_97_rule(Parser *p) static asdl_seq * _loop0_98_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26919,14 +28064,14 @@ _loop0_98_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -26942,7 +28087,7 @@ _loop0_98_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -26959,13 +28104,13 @@ _loop0_98_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_98_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -26973,9 +28118,12 @@ _loop0_98_rule(Parser *p) static asdl_seq * _loop1_99_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -26985,14 +28133,14 @@ _loop1_99_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27008,7 +28156,7 @@ _loop1_99_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27022,7 +28170,7 @@ _loop1_99_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27030,13 +28178,13 @@ _loop1_99_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27044,9 +28192,12 @@ _loop1_99_rule(Parser *p) static asdl_seq * _loop0_100_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27056,14 +28207,14 @@ _loop0_100_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); @@ -27079,7 +28230,7 @@ _loop0_100_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27096,13 +28247,13 @@ _loop0_100_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_100_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27110,9 +28261,12 @@ _loop0_100_rule(Parser *p) static asdl_seq * _loop1_101_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27122,14 +28276,14 @@ _loop1_101_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); @@ -27145,7 +28299,7 @@ _loop1_101_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27159,7 +28313,7 @@ _loop1_101_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27167,13 +28321,13 @@ _loop1_101_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27181,9 +28335,12 @@ _loop1_101_rule(Parser *p) static asdl_seq * _loop0_102_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27193,14 +28350,14 @@ _loop0_102_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -27216,7 +28373,7 @@ _loop0_102_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27233,13 +28390,13 @@ _loop0_102_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27247,9 +28404,12 @@ _loop0_102_rule(Parser *p) static asdl_seq * _loop1_103_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27259,14 +28419,14 @@ _loop1_103_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_maybe_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); @@ -27282,7 +28442,7 @@ _loop1_103_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27296,7 +28456,7 @@ _loop1_103_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27304,13 +28464,13 @@ _loop1_103_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27318,9 +28478,12 @@ _loop1_103_rule(Parser *p) static asdl_seq * _loop1_104_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27330,30 +28493,30 @@ _loop1_104_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('or' conjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_183_var; + void *_tmp_187_var; while ( - (_tmp_183_var = _tmp_183_rule(p)) // 'or' conjunction + (_tmp_187_var = _tmp_187_rule(p)) // 'or' conjunction ) { - _res = _tmp_183_var; + _res = _tmp_187_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27367,7 +28530,7 @@ _loop1_104_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27375,13 +28538,13 @@ _loop1_104_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_104_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27389,9 +28552,12 @@ _loop1_104_rule(Parser *p) static asdl_seq * _loop1_105_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27401,30 +28567,30 @@ _loop1_105_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('and' inversion) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_184_var; + void *_tmp_188_var; while ( - (_tmp_184_var = _tmp_184_rule(p)) // 'and' inversion + (_tmp_188_var = _tmp_188_rule(p)) // 'and' inversion ) { - _res = _tmp_184_var; + _res = _tmp_188_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27438,7 +28604,7 @@ _loop1_105_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27446,13 +28612,13 @@ _loop1_105_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27460,9 +28626,12 @@ _loop1_105_rule(Parser *p) static asdl_seq * _loop1_106_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27472,14 +28641,14 @@ _loop1_106_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // compare_op_bitwise_or_pair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); @@ -27495,7 +28664,7 @@ _loop1_106_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27509,7 +28678,7 @@ _loop1_106_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27517,13 +28686,13 @@ _loop1_106_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_106_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27531,16 +28700,19 @@ _loop1_106_rule(Parser *p) static void * _tmp_107_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '!=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); @@ -27553,7 +28725,7 @@ _tmp_107_rule(Parser *p) _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -27564,7 +28736,7 @@ _tmp_107_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27572,9 +28744,12 @@ _tmp_107_rule(Parser *p) static asdl_seq * _loop0_109_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27584,14 +28759,14 @@ _loop0_109_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' slice if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice")); @@ -27607,7 +28782,7 @@ _loop0_109_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -27616,7 +28791,7 @@ _loop0_109_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -27633,13 +28808,13 @@ _loop0_109_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -27647,16 +28822,19 @@ _loop0_109_rule(Parser *p) static asdl_seq * _gather_108_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; { // slice _loop0_109 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _gather_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_109")); @@ -27678,7 +28856,7 @@ _gather_108_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27686,16 +28864,19 @@ _gather_108_rule(Parser *p) static void * _tmp_110_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' expression? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); @@ -27704,14 +28885,14 @@ _tmp_110_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (d = expression_rule(p), 1) // expression? + (d = expression_rule(p), !p->error_indicator) // expression? ) { D(fprintf(stderr, "%*c+ _tmp_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -27722,7 +28903,7 @@ _tmp_110_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27730,16 +28911,19 @@ _tmp_110_rule(Parser *p) static void * _tmp_111_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); @@ -27758,7 +28942,7 @@ _tmp_111_rule(Parser *p) } { // group if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); @@ -27777,7 +28961,7 @@ _tmp_111_rule(Parser *p) } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); @@ -27796,7 +28980,7 @@ _tmp_111_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27804,16 +28988,19 @@ _tmp_111_rule(Parser *p) static void * _tmp_112_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); @@ -27832,7 +29019,7 @@ _tmp_112_rule(Parser *p) } { // listcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); @@ -27851,7 +29038,7 @@ _tmp_112_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27859,16 +29046,19 @@ _tmp_112_rule(Parser *p) static void * _tmp_113_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // dict if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); @@ -27887,7 +29077,7 @@ _tmp_113_rule(Parser *p) } { // set if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); @@ -27906,7 +29096,7 @@ _tmp_113_rule(Parser *p) } { // dictcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); @@ -27925,7 +29115,7 @@ _tmp_113_rule(Parser *p) } { // setcomp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); @@ -27944,7 +29134,7 @@ _tmp_113_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -27952,9 +29142,12 @@ _tmp_113_rule(Parser *p) static asdl_seq * _loop1_114_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -27964,14 +29157,14 @@ _loop1_114_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _loop1_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); @@ -27987,7 +29180,7 @@ _loop1_114_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28001,7 +29194,7 @@ _loop1_114_rule(Parser *p) } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28009,13 +29202,13 @@ _loop1_114_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); _PyPegen_insert_memo(p, _start_mark, _loop1_114_type, _seq); - D(p->level--); + p->level--; return _seq; } @@ -28023,16 +29216,19 @@ _loop1_114_rule(Parser *p) static void * _tmp_115_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); @@ -28044,14 +29240,14 @@ _tmp_115_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (z = star_named_expressions_rule(p), 1) // star_named_expressions? + (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; @@ -28062,7 +29258,7 @@ _tmp_115_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; return _res; } @@ -28070,16 +29266,19 @@ _tmp_115_rule(Parser *p) static void * _tmp_116_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); @@ -28098,7 +29297,7 @@ _tmp_116_rule(Parser *p) } { // named_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); @@ -28117,17 +29316,80 @@ _tmp_116_rule(Parser *p) } _res = NULL; done: - D(p->level--); + p->level--; + return _res; +} + +// _tmp_117: assignment_expression | expression !':=' +static void * +_tmp_117_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // assignment_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; + if ( + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); + } + { // expression !':=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + expr_ty expression_var; + if ( + (expression_var = expression_rule(p)) // expression + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + _res = expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); + } + _res = NULL; + done: + p->level--; return _res; } -// _loop0_118: ',' double_starred_kvpair +// _loop0_119: ',' double_starred_kvpair static asdl_seq * -_loop0_118_rule(Parser *p) +_loop0_119_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28137,17 +29399,17 @@ _loop0_118_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -28160,7 +29422,7 @@ _loop0_118_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28169,7 +29431,7 @@ _loop0_118_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28178,7 +29440,7 @@ _loop0_118_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28186,62 +29448,68 @@ _loop0_118_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_118_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq); + p->level--; return _seq; } -// _gather_117: double_starred_kvpair _loop0_118 +// _gather_118: double_starred_kvpair _loop0_119 static asdl_seq * -_gather_117_rule(Parser *p) +_gather_118_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_118 + { // double_starred_kvpair _loop0_119 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c> _gather_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_119")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_118_rule(p)) // _loop0_118 + (seq = _loop0_119_rule(p)) // _loop0_119 ) { - D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c+ _gather_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_119")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c%s _gather_118[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_119")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop1_119: for_if_clause +// _loop1_120: for_if_clause static asdl_seq * -_loop1_119_rule(Parser *p) +_loop1_120_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28251,17 +29519,17 @@ _loop1_119_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // for_if_clause if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); + D(fprintf(stderr, "%*c> _loop1_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); comprehension_ty for_if_clause_var; while ( (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause @@ -28274,7 +29542,7 @@ _loop1_119_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28283,12 +29551,12 @@ _loop1_119_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_119[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28296,23 +29564,26 @@ _loop1_119_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_119_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop1_120_type, _seq); + p->level--; return _seq; } -// _loop0_120: ('if' disjunction) +// _loop0_121: ('if' disjunction) static asdl_seq * -_loop0_120_rule(Parser *p) +_loop0_121_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28322,30 +29593,30 @@ _loop0_120_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_185_var; + D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_189_var; while ( - (_tmp_185_var = _tmp_185_rule(p)) // 'if' disjunction + (_tmp_189_var = _tmp_189_rule(p)) // 'if' disjunction ) { - _res = _tmp_185_var; + _res = _tmp_189_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28354,7 +29625,7 @@ _loop0_120_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28362,23 +29633,26 @@ _loop0_120_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_120_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq); + p->level--; return _seq; } -// _loop0_121: ('if' disjunction) +// _loop0_122: ('if' disjunction) static asdl_seq * -_loop0_121_rule(Parser *p) +_loop0_122_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28388,30 +29662,30 @@ _loop0_121_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ('if' disjunction) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_186_var; + D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_190_var; while ( - (_tmp_186_var = _tmp_186_rule(p)) // 'if' disjunction + (_tmp_190_var = _tmp_190_rule(p)) // 'if' disjunction ) { - _res = _tmp_186_var; + _res = _tmp_190_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28420,7 +29694,7 @@ _loop0_121_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28428,23 +29702,26 @@ _loop0_121_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); + p->level--; return _seq; } -// _loop0_123: ',' (starred_expression | direct_named_expression !'=') +// _loop0_124: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_123_rule(Parser *p) +_loop0_124_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28454,30 +29731,30 @@ _loop0_123_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' (starred_expression | direct_named_expression !'=') + { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | direct_named_expression !'=')")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_187_rule(p)) // starred_expression | direct_named_expression !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28486,7 +29763,7 @@ _loop0_123_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28495,80 +29772,87 @@ _loop0_123_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_123[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | direct_named_expression !'=')")); + D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_123_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); + p->level--; return _seq; } -// _gather_122: (starred_expression | direct_named_expression !'=') _loop0_123 +// _gather_123: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 static asdl_seq * -_gather_122_rule(Parser *p) +_gather_123_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | direct_named_expression !'=') _loop0_123 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | direct_named_expression !'=') _loop0_123")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_187_rule(p)) // starred_expression | direct_named_expression !'=' + (elem = _tmp_191_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_123_rule(p)) // _loop0_123 + (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | direct_named_expression !'=') _loop0_123")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_122[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | direct_named_expression !'=') _loop0_123")); + D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_124: ',' kwargs +// _tmp_125: ',' kwargs static void * -_tmp_124_rule(Parser *p) +_tmp_125_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' kwargs if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; asdl_seq* k; if ( @@ -28577,32 +29861,35 @@ _tmp_124_rule(Parser *p) (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_126: ',' kwarg_or_starred +// _loop0_127: ',' kwarg_or_starred static asdl_seq * -_loop0_126_rule(Parser *p) +_loop0_127_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28612,17 +29899,17 @@ _loop0_126_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28635,7 +29922,7 @@ _loop0_126_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28644,7 +29931,7 @@ _loop0_126_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28653,7 +29940,7 @@ _loop0_126_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28661,62 +29948,68 @@ _loop0_126_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); + p->level--; return _seq; } -// _gather_125: kwarg_or_starred _loop0_126 +// _gather_126: kwarg_or_starred _loop0_127 static asdl_seq * -_gather_125_rule(Parser *p) +_gather_126_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_126 + { // kwarg_or_starred _loop0_127 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_126")); + D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_126_rule(p)) // _loop0_126 + (seq = _loop0_127_rule(p)) // _loop0_127 ) { - D(fprintf(stderr, "%*c+ _gather_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_126")); + D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_125[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_126")); + D(fprintf(stderr, "%*c%s _gather_126[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_127")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_128: ',' kwarg_or_double_starred +// _loop0_129: ',' kwarg_or_double_starred static asdl_seq * -_loop0_128_rule(Parser *p) +_loop0_129_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28726,17 +30019,17 @@ _loop0_128_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28749,7 +30042,7 @@ _loop0_128_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28758,7 +30051,7 @@ _loop0_128_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28767,7 +30060,7 @@ _loop0_128_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28775,62 +30068,68 @@ _loop0_128_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); + p->level--; return _seq; } -// _gather_127: kwarg_or_double_starred _loop0_128 +// _gather_128: kwarg_or_double_starred _loop0_129 static asdl_seq * -_gather_127_rule(Parser *p) +_gather_128_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_128 + { // kwarg_or_double_starred _loop0_129 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_128")); + D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_128_rule(p)) // _loop0_128 + (seq = _loop0_129_rule(p)) // _loop0_129 ) { - D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_128")); + D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_127[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_128")); + D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_129")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_130: ',' kwarg_or_starred +// _loop0_131: ',' kwarg_or_starred static asdl_seq * -_loop0_130_rule(Parser *p) +_loop0_131_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28840,17 +30139,17 @@ _loop0_130_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28863,7 +30162,7 @@ _loop0_130_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28872,7 +30171,7 @@ _loop0_130_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28881,7 +30180,7 @@ _loop0_130_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -28889,62 +30188,68 @@ _loop0_130_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_130_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); + p->level--; return _seq; } -// _gather_129: kwarg_or_starred _loop0_130 +// _gather_130: kwarg_or_starred _loop0_131 static asdl_seq * -_gather_129_rule(Parser *p) +_gather_130_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_130 + { // kwarg_or_starred _loop0_131 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_130")); + D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_130_rule(p)) // _loop0_130 + (seq = _loop0_131_rule(p)) // _loop0_131 ) { - D(fprintf(stderr, "%*c+ _gather_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_130")); + D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_129[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_130")); + D(fprintf(stderr, "%*c%s _gather_130[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_131")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_132: ',' kwarg_or_double_starred +// _loop0_133: ',' kwarg_or_double_starred static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_133_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -28954,17 +30259,17 @@ _loop0_132_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' kwarg_or_double_starred if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -28977,7 +30282,7 @@ _loop0_132_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -28986,7 +30291,7 @@ _loop0_132_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -28995,7 +30300,7 @@ _loop0_132_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29003,62 +30308,68 @@ _loop0_132_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); + p->level--; return _seq; } -// _gather_131: kwarg_or_double_starred _loop0_132 +// _gather_132: kwarg_or_double_starred _loop0_133 static asdl_seq * -_gather_131_rule(Parser *p) +_gather_132_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_132 + { // kwarg_or_double_starred _loop0_133 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_132")); + D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_132_rule(p)) // _loop0_132 + (seq = _loop0_133_rule(p)) // _loop0_133 ) { - D(fprintf(stderr, "%*c+ _gather_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_132")); + D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_131[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_132")); + D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_133")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_133: (',' star_target) +// _loop0_134: (',' star_target) static asdl_seq * -_loop0_133_rule(Parser *p) +_loop0_134_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29068,30 +30379,30 @@ _loop0_133_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_188_var; + D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_192_var; while ( - (_tmp_188_var = _tmp_188_rule(p)) // ',' star_target + (_tmp_192_var = _tmp_192_rule(p)) // ',' star_target ) { - _res = _tmp_188_var; + _res = _tmp_192_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29100,7 +30411,7 @@ _loop0_133_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29108,23 +30419,26 @@ _loop0_133_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq); + p->level--; return _seq; } -// _loop0_135: ',' star_target +// _loop0_136: ',' star_target static asdl_seq * -_loop0_135_rule(Parser *p) +_loop0_136_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29134,17 +30448,17 @@ _loop0_135_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -29157,7 +30471,7 @@ _loop0_135_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29166,7 +30480,7 @@ _loop0_135_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29175,7 +30489,7 @@ _loop0_135_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_136[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29183,171 +30497,68 @@ _loop0_135_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_136_type, _seq); + p->level--; return _seq; } -// _gather_134: star_target _loop0_135 +// _gather_135: star_target _loop0_136 static asdl_seq * -_gather_134_rule(Parser *p) +_gather_135_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_135 + { // star_target _loop0_136 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_135")); + D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_135_rule(p)) // _loop0_135 + (seq = _loop0_136_rule(p)) // _loop0_136 ) { - D(fprintf(stderr, "%*c+ _gather_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_135")); + D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_134[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_135")); - } - _res = NULL; - done: - D(p->level--); - return _res; -} - -// _loop1_136: (',' star_target) -static asdl_seq * -_loop1_136_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - int _start_mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - D(p->level--); - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (',' star_target) - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_189_var; - while ( - (_tmp_189_var = _tmp_189_rule(p)) // ',' star_target - ) - { - _res = _tmp_189_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - D(p->level--); - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_136[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - D(p->level--); - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - D(p->level--); - return NULL; - } - for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_136_type, _seq); - D(p->level--); - return _seq; -} - -// _tmp_137: !'*' star_target -static void * -_tmp_137_rule(Parser *p) -{ - D(p->level++); - if (p->error_indicator) { - D(p->level--); - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // !'*' star_target - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); - expr_ty star_target_var; - if ( - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' - && - (star_target_var = star_target_rule(p)) // star_target - ) - { - D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); - _res = star_target_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_136")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_139: ',' del_target +// _loop1_137: (',' star_target) static asdl_seq * -_loop0_139_rule(Parser *p) +_loop1_137_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29357,39 +30568,30 @@ _loop0_139_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' del_target + { // (',' star_target) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); - Token * _literal; - expr_ty elem; + D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_193_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = del_target_rule(p)) // del_target + (_tmp_193_var = _tmp_193_rule(p)) // ',' star_target ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - D(p->level--); - return NULL; - } + _res = _tmp_193_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29398,70 +30600,80 @@ _loop0_139_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_139[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c%s _loop1_137[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_139_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop1_137_type, _seq); + p->level--; return _seq; } -// _gather_138: del_target _loop0_139 -static asdl_seq * -_gather_138_rule(Parser *p) +// _tmp_138: !'*' star_target +static void * +_tmp_138_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - asdl_seq * _res = NULL; + void * _res = NULL; int _mark = p->mark; - { // del_target _loop0_139 + { // !'*' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_139")); - expr_ty elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + expr_ty star_target_var; if ( - (elem = del_target_rule(p)) // del_target + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' && - (seq = _loop0_139_rule(p)) // _loop0_139 + (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _gather_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_139")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_138[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_139")); + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_141: ',' target +// _loop0_140: ',' del_target static asdl_seq * -_loop0_141_rule(Parser *p) +_loop0_140_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29471,30 +30683,30 @@ _loop0_141_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' target + { // ',' del_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target")); + D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = target_rule(p)) // target + (elem = del_target_rule(p)) // del_target ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -29503,7 +30715,7 @@ _loop0_141_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -29512,99 +30724,105 @@ _loop0_141_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_141[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' target")); + D(fprintf(stderr, "%*c%s _loop0_140[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_141_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_140_type, _seq); + p->level--; return _seq; } -// _gather_140: target _loop0_141 +// _gather_139: del_target _loop0_140 static asdl_seq * -_gather_140_rule(Parser *p) +_gather_139_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // target _loop0_141 + { // del_target _loop0_140 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_141")); + D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); expr_ty elem; asdl_seq * seq; if ( - (elem = target_rule(p)) // target + (elem = del_target_rule(p)) // del_target && - (seq = _loop0_141_rule(p)) // _loop0_141 + (seq = _loop0_140_rule(p)) // _loop0_140 ) { - D(fprintf(stderr, "%*c+ _gather_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_141")); + D(fprintf(stderr, "%*c+ _gather_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_140[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_141")); + D(fprintf(stderr, "%*c%s _gather_139[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_140")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_142: args | expression for_if_clauses +// _tmp_141: args | expression for_if_clauses static void * -_tmp_142_rule(Parser *p) +_tmp_141_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // args if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } { // expression for_if_clauses if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( @@ -29613,37 +30831,159 @@ _tmp_142_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; done: - D(p->level--); + p->level--; + return _res; +} + +// _tmp_142: 'True' | 'False' | 'None' +static void * +_tmp_142_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'True' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 524)) // token='True' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); + } + { // 'False' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 525)) // token='False' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); + } + { // 'None' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 523)) // token='None' + ) + { + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); + } + _res = NULL; + done: + p->level--; return _res; } -// _tmp_143: NAME STRING | SOFT_KEYWORD +// _tmp_143: NAME '=' static void * _tmp_143_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // NAME '=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + Token * _literal; + expr_ty name_var; + if ( + (name_var = _PyPegen_name_token(p)) // NAME + && + (_literal = _PyPegen_expect_token(p, 22)) // token='=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + _res = _PyPegen_dummy_name(p, name_var, _literal); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_144: NAME STRING | SOFT_KEYWORD +static void * +_tmp_144_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // NAME STRING if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -29652,325 +30992,357 @@ _tmp_143_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_144: '=' | ':=' | ',' +// _tmp_145: 'else' | ':' static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; - { // '=' + { // 'else' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 516)) // token='else' + ) + { + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); + } + { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - { // ':=' + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_146: '=' | ':=' +static void * +_tmp_146_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 53)) // token=':=' + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } - { // ',' + { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_145: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_147: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_145_rule(Parser *p) +_tmp_147_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // list if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 524)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 523)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 525)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_146: '=' | ':=' | ',' +// _tmp_148: '=' | ':=' static void * -_tmp_146_rule(Parser *p) +_tmp_148_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '=' if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); - } - { // ':=' - if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 53)) // token=':=' + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } - { // ',' + { // ':=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_147: star_named_expressions +// _loop0_149: star_named_expressions static asdl_seq * -_loop0_147_rule(Parser *p) +_loop0_149_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -29980,17 +31352,17 @@ _loop0_147_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // star_named_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -30003,7 +31375,7 @@ _loop0_147_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30012,7 +31384,7 @@ _loop0_147_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30020,23 +31392,26 @@ _loop0_147_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_147_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); + p->level--; return _seq; } -// _loop0_148: (star_targets '=') +// _loop0_150: (star_targets '=') static asdl_seq * -_loop0_148_rule(Parser *p) +_loop0_150_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30046,30 +31421,30 @@ _loop0_148_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_190_var; + D(fprintf(stderr, "%*c> _loop0_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_194_var; while ( - (_tmp_190_var = _tmp_190_rule(p)) // star_targets '=' + (_tmp_194_var = _tmp_194_rule(p)) // star_targets '=' ) { - _res = _tmp_190_var; + _res = _tmp_194_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30078,7 +31453,7 @@ _loop0_148_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30086,23 +31461,26 @@ _loop0_148_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_148_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); + p->level--; return _seq; } -// _loop0_149: (star_targets '=') +// _loop0_151: (star_targets '=') static asdl_seq * -_loop0_149_rule(Parser *p) +_loop0_151_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30112,30 +31490,30 @@ _loop0_149_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // (star_targets '=') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_191_var; + D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_195_var; while ( - (_tmp_191_var = _tmp_191_rule(p)) // star_targets '=' + (_tmp_195_var = _tmp_195_rule(p)) // star_targets '=' ) { - _res = _tmp_191_var; + _res = _tmp_195_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30144,7 +31522,7 @@ _loop0_149_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30152,262 +31530,277 @@ _loop0_149_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); + p->level--; return _seq; } -// _tmp_150: yield_expr | star_expressions +// _tmp_152: yield_expr | star_expressions static void * -_tmp_150_rule(Parser *p) +_tmp_152_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // yield_expr if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_151: '[' | '(' | '{' +// _tmp_153: '[' | '(' | '{' static void * -_tmp_151_rule(Parser *p) +_tmp_153_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_152: '[' | '{' +// _tmp_154: '[' | '{' static void * -_tmp_152_rule(Parser *p) +_tmp_154_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_153: '[' | '{' +// _tmp_155: '[' | '{' static void * -_tmp_153_rule(Parser *p) +_tmp_155_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '[' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_154: param_no_default +// _loop0_156: param_no_default static asdl_seq * -_loop0_154_rule(Parser *p) +_loop0_156_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30417,17 +31810,17 @@ _loop0_154_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -30440,7 +31833,7 @@ _loop0_154_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30449,7 +31842,7 @@ _loop0_154_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30457,23 +31850,26 @@ _loop0_154_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_154_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); + p->level--; return _seq; } -// _loop1_155: param_with_default +// _loop1_157: param_with_default static asdl_seq * -_loop1_155_rule(Parser *p) +_loop1_157_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30483,17 +31879,17 @@ _loop1_155_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -30506,7 +31902,7 @@ _loop1_155_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30515,12 +31911,12 @@ _loop1_155_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30528,23 +31924,26 @@ _loop1_155_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_155_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); + p->level--; return _seq; } -// _loop0_156: lambda_param_no_default +// _loop0_158: lambda_param_no_default static asdl_seq * -_loop0_156_rule(Parser *p) +_loop0_158_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30554,17 +31953,17 @@ _loop0_156_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_no_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30577,7 +31976,7 @@ _loop0_156_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30586,7 +31985,7 @@ _loop0_156_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30594,23 +31993,26 @@ _loop0_156_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); + p->level--; return _seq; } -// _loop1_157: lambda_param_with_default +// _loop1_159: lambda_param_with_default static asdl_seq * -_loop1_157_rule(Parser *p) +_loop1_159_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30620,17 +32022,17 @@ _loop1_157_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // lambda_param_with_default if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30643,7 +32045,7 @@ _loop1_157_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30652,12 +32054,12 @@ _loop1_157_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30665,213 +32067,225 @@ _loop1_157_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); + p->level--; return _seq; } -// _tmp_158: ')' | ',' (')' | '**') +// _tmp_160: ')' | ',' (')' | '**') static void * -_tmp_158_rule(Parser *p) +_tmp_160_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_192_var; + void *_tmp_196_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_192_var = _tmp_192_rule(p)) // ')' | '**' + (_tmp_196_var = _tmp_196_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_192_var); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_196_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_159: ':' | ',' (':' | '**') +// _tmp_161: ':' | ',' (':' | '**') static void * -_tmp_159_rule(Parser *p) +_tmp_161_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_193_var; + void *_tmp_197_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_193_var = _tmp_193_rule(p)) // ':' | '**' + (_tmp_197_var = _tmp_197_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_193_var); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_197_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_160: ',' | ')' | ':' +// _tmp_162: ',' | ')' | ':' static void * -_tmp_160_rule(Parser *p) +_tmp_162_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_162: ',' (expression ['as' star_target]) +// _loop0_164: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_162_rule(Parser *p) +_loop0_164_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30881,30 +32295,30 @@ _loop0_162_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_194_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -30913,7 +32327,7 @@ _loop0_162_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -30922,7 +32336,7 @@ _loop0_162_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30930,62 +32344,68 @@ _loop0_162_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_162_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); + p->level--; return _seq; } -// _gather_161: (expression ['as' star_target]) _loop0_162 +// _gather_163: (expression ['as' star_target]) _loop0_164 static asdl_seq * -_gather_161_rule(Parser *p) +_gather_163_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_162 + { // (expression ['as' star_target]) _loop0_164 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_162")); + D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_194_rule(p)) // expression ['as' star_target] + (elem = _tmp_198_rule(p)) // expression ['as' star_target] && - (seq = _loop0_162_rule(p)) // _loop0_162 + (seq = _loop0_164_rule(p)) // _loop0_164 ) { - D(fprintf(stderr, "%*c+ _gather_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_162")); + D(fprintf(stderr, "%*c+ _gather_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_161[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_162")); + D(fprintf(stderr, "%*c%s _gather_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_164")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_164: ',' (expressions ['as' star_target]) +// _loop0_166: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_164_rule(Parser *p) +_loop0_166_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -30995,30 +32415,30 @@ _loop0_164_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_195_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31027,7 +32447,7 @@ _loop0_164_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31036,7 +32456,7 @@ _loop0_164_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31044,62 +32464,68 @@ _loop0_164_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); + p->level--; return _seq; } -// _gather_163: (expressions ['as' star_target]) _loop0_164 +// _gather_165: (expressions ['as' star_target]) _loop0_166 static asdl_seq * -_gather_163_rule(Parser *p) +_gather_165_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_164 + { // (expressions ['as' star_target]) _loop0_166 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_195_rule(p)) // expressions ['as' star_target] + (elem = _tmp_199_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_164_rule(p)) // _loop0_164 + (seq = _loop0_166_rule(p)) // _loop0_166 ) { - D(fprintf(stderr, "%*c+ _gather_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c+ _gather_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_163[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_164")); + D(fprintf(stderr, "%*c%s _gather_165[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_166")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_166: ',' (expression ['as' star_target]) +// _loop0_168: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_166_rule(Parser *p) +_loop0_168_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31109,30 +32535,30 @@ _loop0_166_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expression ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_196_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31141,7 +32567,7 @@ _loop0_166_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31150,7 +32576,7 @@ _loop0_166_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31158,62 +32584,68 @@ _loop0_166_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); + p->level--; return _seq; } -// _gather_165: (expression ['as' star_target]) _loop0_166 +// _gather_167: (expression ['as' star_target]) _loop0_168 static asdl_seq * -_gather_165_rule(Parser *p) +_gather_167_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_166 + { // (expression ['as' star_target]) _loop0_168 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_196_rule(p)) // expression ['as' star_target] + (elem = _tmp_200_rule(p)) // expression ['as' star_target] && - (seq = _loop0_166_rule(p)) // _loop0_166 + (seq = _loop0_168_rule(p)) // _loop0_168 ) { - D(fprintf(stderr, "%*c+ _gather_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c+ _gather_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_165[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_166")); + D(fprintf(stderr, "%*c%s _gather_167[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_168")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_168: ',' (expressions ['as' star_target]) +// _loop0_170: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_168_rule(Parser *p) +_loop0_170_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31223,30 +32655,30 @@ _loop0_168_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' (expressions ['as' star_target]) if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_197_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] ) { _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31255,7 +32687,7 @@ _loop0_168_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31264,7 +32696,7 @@ _loop0_168_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31272,72 +32704,178 @@ _loop0_168_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_170_type, _seq); + p->level--; return _seq; } -// _gather_167: (expressions ['as' star_target]) _loop0_168 +// _gather_169: (expressions ['as' star_target]) _loop0_170 static asdl_seq * -_gather_167_rule(Parser *p) +_gather_169_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_168 + { // (expressions ['as' star_target]) _loop0_170 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c> _gather_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_197_rule(p)) // expressions ['as' star_target] + (elem = _tmp_201_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_168_rule(p)) // _loop0_168 + (seq = _loop0_170_rule(p)) // _loop0_170 ) { - D(fprintf(stderr, "%*c+ _gather_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c+ _gather_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_168")); + D(fprintf(stderr, "%*c%s _gather_169[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_170")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_171: 'except' | 'finally' +static void * +_tmp_171_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'except' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 521)) // token='except' + ) + { + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); + } + { // 'finally' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 522)) // token='finally' + ) + { + D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_172: 'as' NAME +static void * +_tmp_172_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // 'as' NAME + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + Token * _keyword; + expr_ty name_var; + if ( + (_keyword = _PyPegen_expect_token(p, 520)) // token='as' + && + (name_var = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + _res = _PyPegen_dummy_name(p, _keyword, name_var); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_169: 'as' NAME +// _tmp_173: 'as' NAME static void * -_tmp_169_rule(Parser *p) +_tmp_173_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31346,37 +32884,40 @@ _tmp_169_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_170: 'as' NAME +// _tmp_174: 'as' NAME static void * -_tmp_170_rule(Parser *p) +_tmp_174_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' NAME if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -31385,76 +32926,82 @@ _tmp_170_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_171: 'as' NAME +// _tmp_175: positional_patterns ',' static void * -_tmp_171_rule(Parser *p) +_tmp_175_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // positional_patterns ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + Token * _literal; + asdl_pattern_seq* positional_patterns_var; if ( - (_keyword = _PyPegen_expect_token(p, 520)) // token='as' + (positional_patterns_var = positional_patterns_rule(p)) // positional_patterns && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_172: '->' expression +// _tmp_176: '->' expression static void * -_tmp_172_rule(Parser *p) +_tmp_176_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '->' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -31463,37 +33010,40 @@ _tmp_172_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_172[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_173: '(' arguments? ')' +// _tmp_177: '(' arguments? ')' static void * -_tmp_173_rule(Parser *p) +_tmp_177_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '(' arguments? ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -31501,32 +33051,35 @@ _tmp_173_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_opt_var = arguments_rule(p), 1) // arguments? + (_opt_var = arguments_rule(p), !p->error_indicator) // arguments? && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _loop0_175: ',' double_starred_kvpair +// _loop0_179: ',' double_starred_kvpair static asdl_seq * -_loop0_175_rule(Parser *p) +_loop0_179_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void *_res = NULL; @@ -31536,17 +33089,17 @@ _loop0_175_rule(Parser *p) if (!_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; { // ',' double_starred_kvpair if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -31559,7 +33112,7 @@ _loop0_175_rule(Parser *p) if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; PyMem_Free(_children); - D(p->level--); + p->level--; return NULL; } if (_n == _children_capacity) { @@ -31568,7 +33121,7 @@ _loop0_175_rule(Parser *p) if (!_new_children) { p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } _children = _new_children; @@ -31577,7 +33130,7 @@ _loop0_175_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31585,127 +33138,136 @@ _loop0_175_rule(Parser *p) PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); - D(p->level--); + p->level--; return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_175_type, _seq); - D(p->level--); + _PyPegen_insert_memo(p, _start_mark, _loop0_179_type, _seq); + p->level--; return _seq; } -// _gather_174: double_starred_kvpair _loop0_175 +// _gather_178: double_starred_kvpair _loop0_179 static asdl_seq * -_gather_174_rule(Parser *p) +_gather_178_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_175 + { // double_starred_kvpair _loop0_179 if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_175")); + D(fprintf(stderr, "%*c> _gather_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_175_rule(p)) // _loop0_175 + (seq = _loop0_179_rule(p)) // _loop0_179 ) { - D(fprintf(stderr, "%*c+ _gather_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_175")); + D(fprintf(stderr, "%*c+ _gather_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_179")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_174[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_175")); + D(fprintf(stderr, "%*c%s _gather_178[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_179")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_176: '}' | ',' +// _tmp_180: '}' | ',' static void * -_tmp_176_rule(Parser *p) +_tmp_180_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '}' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_177: star_targets '=' +// _tmp_181: star_targets '=' static void * -_tmp_177_rule(Parser *p) +_tmp_181_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -31714,152 +33276,161 @@ _tmp_177_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_178: '.' | '...' +// _tmp_182: '.' | '...' static void * -_tmp_178_rule(Parser *p) +_tmp_182_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_179: '.' | '...' +// _tmp_183: '.' | '...' static void * -_tmp_179_rule(Parser *p) +_tmp_183_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '.' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_180: '@' named_expression NEWLINE +// _tmp_184: '@' named_expression NEWLINE static void * -_tmp_180_rule(Parser *p) +_tmp_184_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // '@' named_expression NEWLINE if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -31871,42 +33442,45 @@ _tmp_180_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_181: ',' star_expression +// _tmp_185: ',' star_expression static void * -_tmp_181_rule(Parser *p) +_tmp_185_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -31915,42 +33489,45 @@ _tmp_181_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_182: ',' expression +// _tmp_186: ',' expression static void * -_tmp_182_rule(Parser *p) +_tmp_186_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -31959,42 +33536,45 @@ _tmp_182_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_183: 'or' conjunction +// _tmp_187: 'or' conjunction static void * -_tmp_183_rule(Parser *p) +_tmp_187_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'or' conjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -32003,42 +33583,45 @@ _tmp_183_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_184: 'and' inversion +// _tmp_188: 'and' inversion static void * -_tmp_184_rule(Parser *p) +_tmp_188_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'and' inversion if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -32047,42 +33630,45 @@ _tmp_184_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_185: 'if' disjunction +// _tmp_189: 'if' disjunction static void * -_tmp_185_rule(Parser *p) +_tmp_189_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32091,42 +33677,45 @@ _tmp_185_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_186: 'if' disjunction +// _tmp_190: 'if' disjunction static void * -_tmp_186_rule(Parser *p) +_tmp_190_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'if' disjunction if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -32135,99 +33724,105 @@ _tmp_186_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_187: starred_expression | direct_named_expression !'=' +// _tmp_191: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_187_rule(Parser *p) +_tmp_191_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // starred_expression if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } - { // direct_named_expression !'=' + { // (assignment_expression | expression !':=') !'=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "direct_named_expression !'='")); - expr_ty direct_named_expression_var; + D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_202_var; if ( - (direct_named_expression_var = direct_named_expression_rule(p)) // direct_named_expression + (_tmp_202_var = _tmp_202_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "direct_named_expression !'='")); - _res = direct_named_expression_var; + D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_202_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_187[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "direct_named_expression !'='")); + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_188: ',' star_target +// _tmp_192: ',' star_target static void * -_tmp_188_rule(Parser *p) +_tmp_192_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32236,42 +33831,45 @@ _tmp_188_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_189: ',' star_target +// _tmp_193: ',' star_target static void * -_tmp_189_rule(Parser *p) +_tmp_193_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ',' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -32280,42 +33878,45 @@ _tmp_189_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; - D(p->level--); + p->level--; return NULL; } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_190: star_targets '=' +// _tmp_194: star_targets '=' static void * -_tmp_190_rule(Parser *p) +_tmp_194_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32324,37 +33925,40 @@ _tmp_190_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_191: star_targets '=' +// _tmp_195: star_targets '=' static void * -_tmp_191_rule(Parser *p) +_tmp_195_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // star_targets '=' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -32363,307 +33967,388 @@ _tmp_191_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_192: ')' | '**' +// _tmp_196: ')' | '**' static void * -_tmp_192_rule(Parser *p) +_tmp_196_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ')' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_193: ':' | '**' +// _tmp_197: ':' | '**' static void * -_tmp_193_rule(Parser *p) +_tmp_197_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // ':' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_194: expression ['as' star_target] +// _tmp_198: expression ['as' star_target] static void * -_tmp_194_rule(Parser *p) +_tmp_198_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_198_rule(p), 1) // ['as' star_target] + (_opt_var = _tmp_203_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_195: expressions ['as' star_target] +// _tmp_199: expressions ['as' star_target] static void * -_tmp_195_rule(Parser *p) +_tmp_199_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_199_rule(p), 1) // ['as' star_target] + (_opt_var = _tmp_204_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_196: expression ['as' star_target] +// _tmp_200: expression ['as' star_target] static void * -_tmp_196_rule(Parser *p) +_tmp_200_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expression ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_200_rule(p), 1) // ['as' star_target] + (_opt_var = _tmp_205_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_197: expressions ['as' star_target] +// _tmp_201: expressions ['as' star_target] static void * -_tmp_197_rule(Parser *p) +_tmp_201_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // expressions ['as' star_target] if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_201_rule(p), 1) // ['as' star_target] + (_opt_var = _tmp_206_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_198: 'as' star_target +// _tmp_202: assignment_expression | expression !':=' static void * -_tmp_198_rule(Parser *p) +_tmp_202_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // assignment_expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; + if ( + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); + } + { // expression !':=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + expr_ty expression_var; + if ( + (expression_var = expression_rule(p)) // expression + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + _res = expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_203: 'as' star_target +static void * +_tmp_203_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -32672,37 +34357,40 @@ _tmp_198_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_199: 'as' star_target +// _tmp_204: 'as' star_target static void * -_tmp_199_rule(Parser *p) +_tmp_204_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -32711,37 +34399,40 @@ _tmp_199_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_200: 'as' star_target +// _tmp_205: 'as' star_target static void * -_tmp_200_rule(Parser *p) +_tmp_205_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -32750,37 +34441,40 @@ _tmp_200_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } -// _tmp_201: 'as' star_target +// _tmp_206: 'as' star_target static void * -_tmp_201_rule(Parser *p) +_tmp_206_rule(Parser *p) { - D(p->level++); + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } void * _res = NULL; int _mark = p->mark; { // 'as' star_target if (p->error_indicator) { - D(p->level--); + p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -32789,17 +34483,17 @@ _tmp_201_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_206[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; done: - D(p->level--); + p->level--; return _res; } diff --git a/Parser/pegen.c b/Parser/pegen.c index e32b2710dbda26..e507415f6d14ce 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -7,7 +7,7 @@ #include "string_parser.h" PyObject * -_PyPegen_new_type_comment(Parser *p, char *s) +_PyPegen_new_type_comment(Parser *p, const char *s) { PyObject *res = PyUnicode_DecodeUTF8(s, strlen(s), NULL); if (res == NULL) { @@ -26,7 +26,7 @@ _PyPegen_add_type_comment_to_arg(Parser *p, arg_ty a, Token *tc) if (tc == NULL) { return a; } - char *bytes = PyBytes_AsString(tc->bytes); + const char *bytes = PyBytes_AsString(tc->bytes); if (bytes == NULL) { return NULL; } @@ -66,7 +66,7 @@ _PyPegen_check_barry_as_flufl(Parser *p, Token* t) { assert(t->bytes != NULL); assert(t->type == NOTEQUAL); - char* tok_str = PyBytes_AS_STRING(t->bytes); + const char* tok_str = PyBytes_AS_STRING(t->bytes); if (p->flags & PyPARSE_BARRY_AS_BDFL && strcmp(tok_str, "<>") != 0) { RAISE_SYNTAX_ERROR("with Barry as BDFL, use '<>' instead of '!='"); return -1; @@ -77,8 +77,22 @@ _PyPegen_check_barry_as_flufl(Parser *p, Token* t) { return 0; } +int +_PyPegen_check_legacy_stmt(Parser *p, expr_ty name) { + if (name->kind != Name_kind) { + return 0; + } + const char* candidates[2] = {"print", "exec"}; + for (int i=0; i<2; i++) { + if (PyUnicode_CompareWithASCIIString(name->v.Name.id, candidates[i]) == 0) { + return 1; + } + } + return 0; +} + PyObject * -_PyPegen_new_identifier(Parser *p, char *n) +_PyPegen_new_identifier(Parser *p, const char *n) { PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); if (!id) { @@ -217,7 +231,7 @@ _PyPegen_get_expr_name(expr_ty e) return "True"; } if (value == Py_Ellipsis) { - return "Ellipsis"; + return "ellipsis"; } return "literal"; } @@ -283,6 +297,7 @@ static void raise_tokenizer_init_error(PyObject *filename) { if (!(PyErr_ExceptionMatches(PyExc_LookupError) + || PyErr_ExceptionMatches(PyExc_SyntaxError) || PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { return; @@ -358,27 +373,42 @@ tokenizer_error(Parser *p) errtype = PyExc_IndentationError; msg = "too many levels of indentation"; break; - case E_LINECONT: - col_offset = strlen(strtok(p->tok->buf, "\n")) - 1; + case E_LINECONT: { + col_offset = p->tok->cur - p->tok->buf - 1; msg = "unexpected character after line continuation character"; break; + } default: msg = "unknown parsing error"; } - RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, col_offset, p->tok->lineno, -1, msg); + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); return -1; } void * _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) { + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Py_ssize_t col_offset; Py_ssize_t end_col_offset = -1; if (t->col_offset == -1) { - col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf, - intptr_t, int); + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } } else { col_offset = t->col_offset + 1; } @@ -402,9 +432,10 @@ get_error_line(Parser *p, Py_ssize_t lineno) * (multi-line) statement are stored in p->tok->interactive_src_start. * If not, we're parsing from a string, which means that the whole source * is stored in p->tok->str. */ - assert(p->tok->fp == NULL || p->tok->fp == stdin); + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); for (int i = 0; i < lineno - 1; i++) { cur_line = strchr(cur_line, '\n') + 1; @@ -460,7 +491,8 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, error_line = get_error_line(p, lineno); } else if (p->start_rule == Py_file_input) { - error_line = PyErr_ProgramTextObject(p->tok->filename, (int) lineno); + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); } if (!error_line) { @@ -473,13 +505,16 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, does not physically exist */ assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); - if (p->tok->lineno <= lineno) { + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { Py_ssize_t size = p->tok->inp - p->tok->buf; error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); } - else { + else if (p->tok->fp == NULL || p->tok->fp == stdin) { error_line = get_error_line(p, lineno); } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } if (!error_line) { goto error; } @@ -657,6 +692,8 @@ initialize_token(Parser *p, Token *token, const char *start, const char *end, in return -1; } + token->level = p->tok->level; + const char *line_start = token_type == STRING ? p->tok->multi_line_start : p->tok->line_start; int lineno = token_type == STRING ? p->tok->first_lineno : p->tok->lineno; int end_lineno = p->tok->lineno; @@ -664,10 +701,10 @@ initialize_token(Parser *p, Token *token, const char *start, const char *end, in int col_offset = (start != NULL && start >= line_start) ? (int)(start - line_start) : -1; int end_col_offset = (end != NULL && end >= p->tok->line_start) ? (int)(end - p->tok->line_start) : -1; - token->lineno = p->starting_lineno + lineno; - token->col_offset = p->tok->lineno == 1 ? p->starting_col_offset + col_offset : col_offset; - token->end_lineno = p->starting_lineno + end_lineno; - token->end_col_offset = p->tok->lineno == 1 ? p->starting_col_offset + end_col_offset : end_col_offset; + token->lineno = lineno; + token->col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + col_offset : col_offset; + token->end_lineno = end_lineno; + token->end_col_offset = p->tok->lineno == p->starting_lineno ? p->starting_col_offset + end_col_offset : end_col_offset; p->fill += 1; @@ -908,7 +945,7 @@ _PyPegen_expect_soft_keyword(Parser *p, const char *keyword) if (t->type != NAME) { return NULL; } - char *s = PyBytes_AsString(t->bytes); + const char *s = PyBytes_AsString(t->bytes); if (!s) { p->error_indicator = 1; return NULL; @@ -933,14 +970,13 @@ _PyPegen_get_last_nonnwhitespace_token(Parser *p) return token; } -expr_ty -_PyPegen_name_token(Parser *p) +static expr_ty +_PyPegen_name_from_token(Parser *p, Token* t) { - Token *t = _PyPegen_expect_token(p, NAME); if (t == NULL) { return NULL; } - char* s = PyBytes_AsString(t->bytes); + const char *s = PyBytes_AsString(t->bytes); if (!s) { p->error_indicator = 1; return NULL; @@ -954,6 +990,14 @@ _PyPegen_name_token(Parser *p) t->end_col_offset, p->arena); } + +expr_ty +_PyPegen_name_token(Parser *p) +{ + Token *t = _PyPegen_expect_token(p, NAME); + return _PyPegen_name_from_token(p, t); +} + void * _PyPegen_string_token(Parser *p) { @@ -971,7 +1015,7 @@ expr_ty _PyPegen_soft_keyword_token(Parser *p) { PyBytes_AsStringAndSize(t->bytes, &the_token, &size); for (char **keyword = p->soft_keywords; *keyword != NULL; keyword++) { if (strncmp(*keyword, the_token, size) == 0) { - return _PyPegen_name_token(p); + return _PyPegen_name_from_token(p, t); } } return NULL; @@ -1058,7 +1102,7 @@ _PyPegen_number_token(Parser *p) return NULL; } - char *num_raw = PyBytes_AsString(t->bytes); + const char *num_raw = PyBytes_AsString(t->bytes); if (num_raw == NULL) { p->error_indicator = 1; return NULL; @@ -1087,31 +1131,13 @@ _PyPegen_number_token(Parser *p) t->end_col_offset, p->arena); } -static int // bool -newline_in_string(Parser *p, const char *cur) -{ - for (const char *c = cur; c >= p->tok->buf; c--) { - if (*c == '\'' || *c == '"') { - return 1; - } - } - return 0; -} - /* Check that the source for a single input statement really is a single statement by looking at what is left in the buffer after parsing. Trailing whitespace and comments are OK. */ static int // bool bad_single_statement(Parser *p) { - const char *cur = strchr(p->tok->buf, '\n'); - - /* Newlines are allowed if preceded by a line continuation character - or if they appear inside a string. */ - if (!cur || (cur != p->tok->buf && *(cur - 1) == '\\') - || newline_in_string(p, cur)) { - return 0; - } + char *cur = p->tok->cur; char c = *cur; for (;;) { @@ -1222,7 +1248,7 @@ _PyPegen_Parser_New(struct tok_state *tok, int start_rule, int flags, p->known_err_token = NULL; p->level = 0; p->call_invalid_rules = 0; - + p->in_raw_rule = 0; return p; } @@ -1234,6 +1260,9 @@ reset_parser_state(Parser *p) } p->mark = 0; p->call_invalid_rules = 1; + // Don't try to get extra tokens in interactive mode when trying to + // raise specialized errors in the second pass. + p->tok->interactive_underflow = IUNDERFLOW_STOP; } static int @@ -1248,9 +1277,14 @@ _PyPegen_check_tokenizer_errors(Parser *p) { return 0; } + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Py_ssize_t current_err_line = current_token->lineno; + int ret = 0; + for (;;) { const char *start; const char *end; @@ -1260,7 +1294,8 @@ _PyPegen_check_tokenizer_errors(Parser *p) { int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; if (current_err_line > error_lineno) { raise_unclosed_parentheses_error(p); - return -1; + ret = -1; + goto exit; } } break; @@ -1272,23 +1307,42 @@ _PyPegen_check_tokenizer_errors(Parser *p) { break; } - return 0; + +exit: + if (PyErr_Occurred()) { + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(traceback); + } else { + PyErr_Restore(type, value, traceback); + } + return ret; } void * _PyPegen_run_parser(Parser *p) { void *res = _PyPegen_parse(p); + assert(p->level == 0); if (res == NULL) { + if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_SyntaxError)) { + return NULL; + } + Token *last_token = p->tokens[p->fill - 1]; reset_parser_state(p); _PyPegen_parse(p); if (PyErr_Occurred()) { + // Prioritize tokenizer errors to custom syntax errors raised + // on the second phase only if the errors come from the parser. + if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { + _PyPegen_check_tokenizer_errors(p); + } return NULL; } if (p->fill == 0) { RAISE_SYNTAX_ERROR("error at start before reading any input"); } - else if (p->tok->done == E_EOF) { + else if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) { if (p->tok->level) { raise_unclosed_parentheses_error(p); } else { @@ -1303,7 +1357,11 @@ _PyPegen_run_parser(Parser *p) RAISE_INDENTATION_ERROR("unexpected unindent"); } else { - RAISE_SYNTAX_ERROR("invalid syntax"); + // Use the last token we found on the first pass to avoid reporting + // incorrect locations for generic syntax errors just because we reached + // further away when trying to find specific syntax errors in the second + // pass. + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); // _PyPegen_check_tokenizer_errors will override the existing // generic SyntaxError we just raised if errors are found. _PyPegen_check_tokenizer_errors(p); @@ -1377,7 +1435,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen int exec_input = start_rule == Py_file_input; struct tok_state *tok; - if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { + if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) { tok = PyTokenizer_FromUTF8(str, exec_input); } else { tok = PyTokenizer_FromString(str, exec_input); @@ -1518,6 +1576,13 @@ _PyPegen_seq_last_item(asdl_seq *seq) return asdl_seq_GET_UNTYPED(seq, len - 1); } +void * +_PyPegen_seq_first_item(asdl_seq *seq) +{ + return asdl_seq_GET_UNTYPED(seq, 0); +} + + /* Creates a new name of the form . */ expr_ty _PyPegen_join_names_with_dot(Parser *p, expr_ty first_name, expr_ty second_name) @@ -2472,8 +2537,17 @@ void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { return RAISE_SYNTAX_ERROR(msg); } + +static inline expr_ty +_PyPegen_get_last_comprehension_item(comprehension_ty comprehension) { + if (comprehension->ifs == NULL || asdl_seq_LEN(comprehension->ifs) == 0) { + return comprehension->iter; + } + return PyPegen_last_item(comprehension->ifs, expr_ty); +} + void * -_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args) +_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions) { /* The rule that calls this function is 'args for_if_clauses'. For the input f(L, x for x in y), L and x are in args and @@ -2487,8 +2561,11 @@ _PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args) return NULL; } - return RAISE_SYNTAX_ERROR_STARTING_FROM( + comprehension_ty last_comprehension = PyPegen_last_item(comprehensions, comprehension_ty); + + return RAISE_SYNTAX_ERROR_KNOWN_RANGE( (expr_ty) asdl_seq_GET(args->v.Call.args, len - 1), + _PyPegen_get_last_comprehension_item(last_comprehension), "Generator expression must be parenthesized" ); } diff --git a/Parser/pegen.h b/Parser/pegen.h index d591c566968c78..29d48052e4bc9b 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -33,6 +33,7 @@ typedef struct _memo { typedef struct { int type; PyObject *bytes; + int level; int lineno, col_offset, end_lineno, end_col_offset; Memo *memo; } Token; @@ -74,6 +75,7 @@ typedef struct { Token *known_err_token; int level; int call_invalid_rules; + int in_raw_rule; } Parser; typedef struct { @@ -148,6 +150,9 @@ void *_PyPegen_dummy_name(Parser *p, ...); void * _PyPegen_seq_last_item(asdl_seq *seq); #define PyPegen_last_item(seq, type) ((type)_PyPegen_seq_last_item((asdl_seq*)seq)) +void * _PyPegen_seq_first_item(asdl_seq *seq); +#define PyPegen_first_item(seq, type) ((type)_PyPegen_seq_first_item((asdl_seq*)seq)) + #define CURRENT_POS (-5) Py_LOCAL_INLINE(void *) @@ -201,7 +206,7 @@ CHECK_CALL_NULL_ALLOWED(Parser *p, void *result) #define CHECK(type, result) ((type) CHECK_CALL(p, result)) #define CHECK_NULL_ALLOWED(type, result) ((type) CHECK_CALL_NULL_ALLOWED(p, result)) -PyObject *_PyPegen_new_type_comment(Parser *, char *); +PyObject *_PyPegen_new_type_comment(Parser *, const char *); Py_LOCAL_INLINE(PyObject *) NEW_TYPE_COMMENT(Parser *p, Token *tc) @@ -209,7 +214,7 @@ NEW_TYPE_COMMENT(Parser *p, Token *tc) if (tc == NULL) { return NULL; } - char *bytes = PyBytes_AsString(tc->bytes); + const char *bytes = PyBytes_AsString(tc->bytes); if (bytes == NULL) { goto error; } @@ -241,7 +246,7 @@ INVALID_VERSION_CHECK(Parser *p, int version, char *msg, void *node) #define CHECK_VERSION(type, version, msg, node) ((type) INVALID_VERSION_CHECK(p, version, msg, node)) arg_ty _PyPegen_add_type_comment_to_arg(Parser *, arg_ty, Token *); -PyObject *_PyPegen_new_identifier(Parser *, char *); +PyObject *_PyPegen_new_identifier(Parser *, const char *); Parser *_PyPegen_Parser_New(struct tok_state *, int, int, int, int *, PyArena *); void _PyPegen_Parser_Free(Parser *); mod_ty _PyPegen_run_parser_from_file_pointer(FILE *, int, PyObject *, const char *, @@ -287,6 +292,7 @@ expr_ty _PyPegen_ensure_imaginary(Parser *p, expr_ty); expr_ty _PyPegen_ensure_real(Parser *p, expr_ty); asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *); int _PyPegen_check_barry_as_flufl(Parser *, Token *); +int _PyPegen_check_legacy_stmt(Parser *p, expr_ty t); mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *); // Error reporting helpers @@ -315,12 +321,13 @@ _RAISE_SYNTAX_ERROR_INVALID_TARGET(Parser *p, TARGETS_TYPE type, void *e) msg, _PyPegen_get_expr_name(invalid_target) ); + return RAISE_SYNTAX_ERROR_KNOWN_LOCATION(invalid_target, "invalid syntax"); } - return RAISE_SYNTAX_ERROR("invalid syntax"); + return NULL; } void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); -void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args); +void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions); // Generated function in parse.c - function definition in python.gram diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c new file mode 100644 index 00000000000000..93057d151db386 --- /dev/null +++ b/Parser/pegen_errors.c @@ -0,0 +1,425 @@ +#include +#include + +#include "tokenizer.h" +#include "pegen.h" + +// 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); + errstr = PyObject_Str(value); + if (!errstr) { + goto error; + } + + PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); + if (!tmp) { + goto error; + } + + tuple = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + 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]; + int error_col = p->tok->parencolstack[p->tok->level-1]; + RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, + error_lineno, error_col, error_lineno, -1, + "'%c' was never closed", + p->tok->parenstack[p->tok->level-1]); +} + +int +_Pypegen_tokenizer_error(Parser *p) +{ + if (PyErr_Occurred()) { + return -1; + } + + const char *msg = NULL; + PyObject* errtype = PyExc_SyntaxError; + Py_ssize_t col_offset = -1; + switch (p->tok->done) { + case E_TOKEN: + msg = "invalid token"; + break; + case E_EOF: + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return -1; + case E_DEDENT: + RAISE_INDENTATION_ERROR("unindent does not match any outer indentation level"); + return -1; + case E_INTR: + if (!PyErr_Occurred()) { + PyErr_SetNone(PyExc_KeyboardInterrupt); + } + return -1; + case E_NOMEM: + PyErr_NoMemory(); + return -1; + case E_TABSPACE: + errtype = PyExc_TabError; + msg = "inconsistent use of tabs and spaces in indentation"; + break; + case E_TOODEEP: + errtype = PyExc_IndentationError; + msg = "too many levels of indentation"; + break; + case E_LINECONT: { + col_offset = p->tok->cur - p->tok->buf - 1; + msg = "unexpected character after line continuation character"; + break; + } + default: + msg = "unknown parsing error"; + } + + RAISE_ERROR_KNOWN_LOCATION(p, errtype, p->tok->lineno, + col_offset >= 0 ? col_offset : 0, + p->tok->lineno, -1, msg); + return -1; +} + +int +_Pypegen_raise_decode_error(Parser *p) +{ + assert(PyErr_Occurred()); + const char *errtype = NULL; + if (PyErr_ExceptionMatches(PyExc_UnicodeError)) { + errtype = "unicode error"; + } + else if (PyErr_ExceptionMatches(PyExc_ValueError)) { + errtype = "value error"; + } + if (errtype) { + PyObject *type; + PyObject *value; + PyObject *tback; + PyObject *errstr; + PyErr_Fetch(&type, &value, &tback); + errstr = PyObject_Str(value); + if (errstr) { + RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr); + Py_DECREF(errstr); + } + else { + PyErr_Clear(); + RAISE_SYNTAX_ERROR("(%s) unknown error", errtype); + } + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + } + + return -1; +} + +static int +_PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { + // Tokenize the whole input to see if there are any tokenization + // errors such as mistmatching parentheses. These will get priority + // over generic syntax errors only if the line number of the error is + // before the one that we had for the generic error. + + // We don't want to tokenize to the end for interactive input + if (p->tok->prompt != NULL) { + return 0; + } + + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + + Token *current_token = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t current_err_line = current_token->lineno; + + int ret = 0; + + for (;;) { + const char *start; + const char *end; + switch (_PyTokenizer_Get(p->tok, &start, &end)) { + case ERRORTOKEN: + if (p->tok->level != 0) { + int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; + if (current_err_line > error_lineno) { + raise_unclosed_parentheses_error(p); + ret = -1; + goto exit; + } + } + break; + case ENDMARKER: + break; + default: + continue; + } + break; + } + + +exit: + if (PyErr_Occurred()) { + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(traceback); + } else { + PyErr_Restore(type, value, traceback); + } + return ret; +} + +// PARSER ERRORS + +void * +_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) +{ + if (p->fill == 0) { + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, 0, 0, 0, -1, errmsg, va); + va_end(va); + return NULL; + } + + Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; + Py_ssize_t col_offset; + Py_ssize_t end_col_offset = -1; + if (t->col_offset == -1) { + if (p->tok->cur == p->tok->buf) { + col_offset = 0; + } else { + const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); + } + } else { + col_offset = t->col_offset + 1; + } + + if (t->end_col_offset != -1) { + end_col_offset = t->end_col_offset + 1; + } + + va_list va; + va_start(va, errmsg); + _PyPegen_raise_error_known_location(p, errtype, t->lineno, col_offset, t->end_lineno, end_col_offset, errmsg, va); + va_end(va); + + return NULL; +} + +static PyObject * +get_error_line_from_tokenizer_buffers(Parser *p, Py_ssize_t lineno) +{ + /* If the file descriptor is interactive, the source lines of the current + * (multi-line) statement are stored in p->tok->interactive_src_start. + * If not, we're parsing from a string, which means that the whole source + * is stored in p->tok->str. */ + assert((p->tok->fp == NULL && p->tok->str != NULL) || p->tok->fp == stdin); + + char *cur_line = p->tok->fp_interactive ? p->tok->interactive_src_start : p->tok->str; + assert(cur_line != NULL); + + for (int i = 0; i < lineno - 1; i++) { + cur_line = strchr(cur_line, '\n') + 1; + } + + char *next_newline; + if ((next_newline = strchr(cur_line, '\n')) == NULL) { // This is the last line + next_newline = cur_line + strlen(cur_line); + } + return PyUnicode_DecodeUTF8(cur_line, next_newline - cur_line, "replace"); +} + +void * +_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, + Py_ssize_t lineno, Py_ssize_t col_offset, + Py_ssize_t end_lineno, Py_ssize_t end_col_offset, + const char *errmsg, va_list va) +{ + PyObject *value = NULL; + PyObject *errstr = NULL; + PyObject *error_line = NULL; + PyObject *tmp = NULL; + p->error_indicator = 1; + + if (end_lineno == CURRENT_POS) { + end_lineno = p->tok->lineno; + } + if (end_col_offset == CURRENT_POS) { + end_col_offset = p->tok->cur - p->tok->line_start; + } + + if (p->start_rule == Py_fstring_input) { + const char *fstring_msg = "f-string: "; + Py_ssize_t len = strlen(fstring_msg) + strlen(errmsg); + + char *new_errmsg = PyMem_Malloc(len + 1); // Lengths of both strings plus NULL character + if (!new_errmsg) { + return (void *) PyErr_NoMemory(); + } + + // Copy both strings into new buffer + memcpy(new_errmsg, fstring_msg, strlen(fstring_msg)); + memcpy(new_errmsg + strlen(fstring_msg), errmsg, strlen(errmsg)); + new_errmsg[len] = 0; + errmsg = new_errmsg; + } + errstr = PyUnicode_FromFormatV(errmsg, va); + if (!errstr) { + goto error; + } + + if (p->tok->fp_interactive) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else if (p->start_rule == Py_file_input) { + error_line = _PyErr_ProgramDecodedTextObject(p->tok->filename, + (int) lineno, p->tok->encoding); + } + + if (!error_line) { + /* PyErr_ProgramTextObject was not called or returned NULL. If it was not called, + then we need to find the error line from some other source, because + p->start_rule != Py_file_input. If it returned NULL, then it either unexpectedly + failed or we're parsing from a string or the REPL. There's a third edge case where + we're actually parsing from a file, which has an E_EOF SyntaxError and in that case + `PyErr_ProgramTextObject` fails because lineno points to last_file_line + 1, which + does not physically exist */ + assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); + + if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { + Py_ssize_t size = p->tok->inp - p->tok->buf; + error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); + } + else if (p->tok->fp == NULL || p->tok->fp == stdin) { + error_line = get_error_line_from_tokenizer_buffers(p, lineno); + } + else { + error_line = PyUnicode_FromStringAndSize("", 0); + } + if (!error_line) { + goto error; + } + } + + if (p->start_rule == Py_fstring_input) { + col_offset -= p->starting_col_offset; + end_col_offset -= p->starting_col_offset; + } + + Py_ssize_t col_number = col_offset; + Py_ssize_t end_col_number = end_col_offset; + + if (p->tok->encoding != NULL) { + col_number = _PyPegen_byte_offset_to_character_offset(error_line, col_offset); + if (col_number < 0) { + goto error; + } + if (end_col_number > 0) { + Py_ssize_t end_col_offset = _PyPegen_byte_offset_to_character_offset(error_line, end_col_number); + if (end_col_offset < 0) { + goto error; + } else { + end_col_number = end_col_offset; + } + } + } + tmp = Py_BuildValue("(OiiNii)", p->tok->filename, lineno, col_number, error_line, end_lineno, end_col_number); + if (!tmp) { + goto error; + } + value = PyTuple_Pack(2, errstr, tmp); + Py_DECREF(tmp); + if (!value) { + goto error; + } + PyErr_SetObject(errtype, value); + + Py_DECREF(errstr); + Py_DECREF(value); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; + +error: + Py_XDECREF(errstr); + Py_XDECREF(error_line); + if (p->start_rule == Py_fstring_input) { + PyMem_Free((void *)errmsg); + } + return NULL; +} + +void +_Pypegen_set_syntax_error(Parser* p, Token* last_token) { + // Existing sintax error + if (PyErr_Occurred()) { + // Prioritize tokenizer errors to custom syntax errors raised + // on the second phase only if the errors come from the parser. + if (p->tok->done == E_DONE && PyErr_ExceptionMatches(PyExc_SyntaxError)) { + _PyPegen_tokenize_full_source_to_check_for_errors(p); + } + // Propagate the existing syntax error. + return; + } + // Initialization error + if (p->fill == 0) { + RAISE_SYNTAX_ERROR("error at start before reading any input"); + } + // Parser encountered EOF (End of File) unexpectedtly + if (last_token->type == ERRORTOKEN && p->tok->done == E_EOF) { + if (p->tok->level) { + raise_unclosed_parentheses_error(p); + } else { + RAISE_SYNTAX_ERROR("unexpected EOF while parsing"); + } + return; + } + // Indentation error in the tokenizer + if (last_token->type == INDENT || last_token->type == DEDENT) { + RAISE_INDENTATION_ERROR(last_token->type == INDENT ? "unexpected indent" : "unexpected unindent"); + return; + } + // Unknown error (generic case) + + // Use the last token we found on the first pass to avoid reporting + // incorrect locations for generic syntax errors just because we reached + // further away when trying to find specific syntax errors in the second + // pass. + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(last_token, "invalid syntax"); + // _PyPegen_tokenize_full_source_to_check_for_errors will override the existing + // generic SyntaxError we just raised if errors are found. + _PyPegen_tokenize_full_source_to_check_for_errors(p); +} diff --git a/Parser/string_parser.c b/Parser/string_parser.c index b919633ded8d9d..c83e63fc6f8f2b 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -12,7 +12,7 @@ static int warn_invalid_escape_sequence(Parser *p, unsigned char first_invalid_escape_char, Token *t) { PyObject *msg = - PyUnicode_FromFormat("invalid escape sequence \\%c", first_invalid_escape_char); + PyUnicode_FromFormat("invalid escape sequence '\\%c'", first_invalid_escape_char); if (msg == NULL) { return -1; } @@ -27,7 +27,7 @@ warn_invalid_escape_sequence(Parser *p, unsigned char first_invalid_escape_char, since _PyPegen_raise_error uses p->tokens[p->fill - 1] for the error location, if p->known_err_token is not set. */ p->known_err_token = t; - RAISE_SYNTAX_ERROR("invalid escape sequence \\%c", first_invalid_escape_char); + RAISE_SYNTAX_ERROR("invalid escape sequence '\\%c'", first_invalid_escape_char); } Py_DECREF(msg); return -1; @@ -87,7 +87,7 @@ decode_unicode_with_escapes(Parser *parser, const char *s, size_t len, Token *t) if (*s & 0x80) { PyObject *w; int kind; - void *data; + const void *data; Py_ssize_t w_len; Py_ssize_t i; w = decode_utf8(&s, end); @@ -115,7 +115,7 @@ decode_unicode_with_escapes(Parser *parser, const char *s, size_t len, Token *t) s = buf; const char *first_invalid_escape; - v = _PyUnicode_DecodeUnicodeEscape(s, len, NULL, &first_invalid_escape); + v = _PyUnicode_DecodeUnicodeEscapeInternal(s, len, NULL, NULL, &first_invalid_escape); if (v != NULL && first_invalid_escape != NULL) { if (warn_invalid_escape_sequence(parser, *first_invalid_escape, t) < 0) { @@ -279,49 +279,48 @@ _PyPegen_parsestr(Parser *p, int *bytesmode, int *rawmode, PyObject **result, /* Fix locations for the given node and its children. `parent` is the enclosing node. + `expr_start` is the starting position of the expression (pointing to the open brace). `n` is the node which locations are going to be fixed relative to parent. `expr_str` is the child node's string representation, including braces. */ static bool -fstring_find_expr_location(Token *parent, char *expr_str, int *p_lines, int *p_cols) +fstring_find_expr_location(Token *parent, const char* expr_start, char *expr_str, int *p_lines, int *p_cols) { *p_lines = 0; *p_cols = 0; + assert(expr_start != NULL && *expr_start == '{'); if (parent && parent->bytes) { - char *parent_str = PyBytes_AsString(parent->bytes); + const char *parent_str = PyBytes_AsString(parent->bytes); if (!parent_str) { return false; } - char *substr = strstr(parent_str, expr_str); - if (substr) { - // The following is needed, in order to correctly shift the column - // offset, in the case that (disregarding any whitespace) a newline - // immediately follows the opening curly brace of the fstring expression. - bool newline_after_brace = 1; - char *start = substr + 1; - while (start && *start != '}' && *start != '\n') { - if (*start != ' ' && *start != '\t' && *start != '\f') { - newline_after_brace = 0; - break; - } - start++; + // The following is needed, in order to correctly shift the column + // offset, in the case that (disregarding any whitespace) a newline + // immediately follows the opening curly brace of the fstring expression. + bool newline_after_brace = 1; + const char *start = expr_start + 1; + while (start && *start != '}' && *start != '\n') { + if (*start != ' ' && *start != '\t' && *start != '\f') { + newline_after_brace = 0; + break; } + start++; + } - // Account for the characters from the last newline character to our - // left until the beginning of substr. - if (!newline_after_brace) { - start = substr; - while (start > parent_str && *start != '\n') { - start--; - } - *p_cols += (int)(substr - start); + // Account for the characters from the last newline character to our + // left until the beginning of expr_start. + if (!newline_after_brace) { + start = expr_start; + while (start > parent_str && *start != '\n') { + start--; } - /* adjust the start based on the number of newlines encountered - before the f-string expression */ - for (char* p = parent_str; p < substr; p++) { - if (*p == '\n') { - (*p_lines)++; - } + *p_cols += (int)(expr_start - start); + } + /* adjust the start based on the number of newlines encountered + before the f-string expression */ + for (const char *p = parent_str; p < expr_start; p++) { + if (*p == '\n') { + (*p_lines)++; } } } @@ -365,7 +364,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end, len = expr_end - expr_start; /* Allocate 3 extra bytes: open paren, close paren, null byte. */ - str = PyMem_Malloc(len + 3); + str = PyMem_Calloc(len + 3, sizeof(char)); if (str == NULL) { PyErr_NoMemory(); return NULL; @@ -373,17 +372,10 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end, // The call to fstring_find_expr_location is responsible for finding the column offset // the generated AST nodes need to be shifted to the right, which is equal to the number - // of the f-string characters before the expression starts. In order to correctly compute - // this offset, strstr gets called in fstring_find_expr_location which only succeeds - // if curly braces appear before and after the f-string expression (exactly like they do - // in the f-string itself), hence the following lines. - str[0] = '{'; + // of the f-string characters before the expression starts. memcpy(str+1, expr_start, len); - str[len+1] = '}'; - str[len+2] = 0; - int lines, cols; - if (!fstring_find_expr_location(t, str, &lines, &cols)) { + if (!fstring_find_expr_location(t, expr_start-1, str+1, &lines, &cols)) { PyMem_Free(str); return NULL; } @@ -400,11 +392,14 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end, return NULL; } Py_INCREF(p->tok->filename); + tok->filename = p->tok->filename; + tok->lineno = t->lineno + lines - 1; Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version, NULL, p->arena); - p2->starting_lineno = t->lineno + lines - 1; + + p2->starting_lineno = t->lineno + lines; p2->starting_col_offset = t->col_offset + cols; expr = _PyPegen_run_parser(p2); diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index ad32293d70b785..8e9c69d0785afd 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -85,7 +85,8 @@ tok_new(void) tok->async_def = 0; tok->async_def_indent = 0; tok->async_def_nl = 0; - + tok->interactive_underflow = IUNDERFLOW_NORMAL; + tok->str = NULL; return tok; } @@ -371,6 +372,8 @@ tok_reserve_buf(struct tok_state *tok, Py_ssize_t size) if (newsize > tok->end - tok->buf) { char *newbuf = tok->buf; Py_ssize_t start = tok->start == NULL ? -1 : tok->start - tok->buf; + Py_ssize_t line_start = tok->start == NULL ? -1 : tok->line_start - tok->buf; + Py_ssize_t multi_line_start = tok->multi_line_start - tok->buf; newbuf = (char *)PyMem_Realloc(newbuf, newsize); if (newbuf == NULL) { tok->done = E_NOMEM; @@ -381,6 +384,8 @@ tok_reserve_buf(struct tok_state *tok, Py_ssize_t size) tok->inp = tok->buf + oldsize; tok->end = tok->buf + newsize; tok->start = start < 0 ? NULL : tok->buf + start; + tok->line_start = line_start < 0 ? NULL : tok->buf + line_start; + tok->multi_line_start = multi_line_start < 0 ? NULL : tok->buf + multi_line_start; } return 1; } @@ -540,7 +545,7 @@ ensure_utf8(char *line, struct tok_state *tok) "Non-UTF-8 code starting with '\\x%.2x' " "in file %U on line %i, " "but no encoding declared; " - "see http://python.org/dev/peps/pep-0263/ for details", + "see https://python.org/dev/peps/pep-0263/ for details", badchar, tok->filename, tok->lineno + 1); return 0; } @@ -813,10 +818,10 @@ tok_readline_raw(struct tok_state *tok) tok_concatenate_interactive_new_line(tok, line) == -1) { return 0; } - if (*tok->inp == '\0') { + tok->inp = strchr(tok->inp, '\0'); + if (tok->inp == tok->buf) { return 0; } - tok->inp = strchr(tok->inp, '\0'); } while (tok->inp[-1] != '\n'); return 1; } @@ -845,6 +850,10 @@ tok_underflow_string(struct tok_state *tok) { static int tok_underflow_interactive(struct tok_state *tok) { + if (tok->interactive_underflow == IUNDERFLOW_STOP) { + tok->done = E_INTERACT_STOP; + return 1; + } char *newtok = PyOS_Readline(stdin, stdout, tok->prompt); if (newtok != NULL) { char *translated = translate_newlines(newtok, 0, tok); @@ -974,17 +983,15 @@ tok_underflow_file(struct tok_state *tok) { } /* The default encoding is UTF-8, so make sure we don't have any non-UTF-8 sequences in it. */ - if (!tok->encoding - && (tok->decoding_state != STATE_NORMAL || tok->lineno >= 2)) { - if (!ensure_utf8(tok->cur, tok)) { - error_ret(tok); - return 0; - } + if (!tok->encoding && !ensure_utf8(tok->cur, tok)) { + error_ret(tok); + return 0; } assert(tok->done == E_OK); return tok->done == E_OK; } +#if defined(Py_DEBUG) static void print_escape(FILE *f, const char *s, Py_ssize_t size) { @@ -1011,6 +1018,7 @@ print_escape(FILE *f, const char *s, Py_ssize_t size) } putc('"', f); } +#endif /* Get next char, updating state; error code goes into tok->done */ @@ -1033,11 +1041,13 @@ tok_nextc(struct tok_state *tok) else { rc = tok_underflow_file(tok); } +#if defined(Py_DEBUG) if (Py_DebugFlag) { - printf("line[%d] = ", tok->lineno); - print_escape(stdout, tok->cur, tok->inp - tok->cur); - printf(" tok->done = %d\n", tok->done); + fprintf(stderr, "line[%d] = ", tok->lineno); + print_escape(stderr, tok->cur, tok->inp - tok->cur); + fprintf(stderr, " tok->done = %d\n", tok->done); } +#endif if (!rc) { tok->cur = tok->inp; return EOF; @@ -1062,19 +1072,13 @@ tok_backup(struct tok_state *tok, int c) } } - static int -syntaxerror(struct tok_state *tok, const char *format, ...) +_syntaxerror_range(struct tok_state *tok, const char *format, + int col_offset, int end_col_offset, + va_list vargs) { PyObject *errmsg, *errtext, *args; - va_list vargs; -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif errmsg = PyUnicode_FromFormatV(format, vargs); - va_end(vargs); if (!errmsg) { goto error; } @@ -1084,7 +1088,14 @@ syntaxerror(struct tok_state *tok, const char *format, ...) if (!errtext) { goto error; } - int offset = (int)PyUnicode_GET_LENGTH(errtext); + + if (col_offset == -1) { + col_offset = (int)PyUnicode_GET_LENGTH(errtext); + } + if (end_col_offset == -1) { + end_col_offset = col_offset; + } + Py_ssize_t line_len = strcspn(tok->line_start, "\n"); if (line_len != tok->cur - tok->line_start) { Py_DECREF(errtext); @@ -1095,8 +1106,8 @@ syntaxerror(struct tok_state *tok, const char *format, ...) goto error; } - args = Py_BuildValue("(O(OiiN))", errmsg, - tok->filename, tok->lineno, offset, errtext); + args = Py_BuildValue("(O(OiiNii))", errmsg, tok->filename, tok->lineno, + col_offset, errtext, tok->lineno, end_col_offset); if (args) { PyErr_SetObject(PyExc_SyntaxError, args); Py_DECREF(args); @@ -1108,6 +1119,38 @@ syntaxerror(struct tok_state *tok, const char *format, ...) return ERRORTOKEN; } +static int +syntaxerror(struct tok_state *tok, const char *format, ...) +{ + va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + int ret = _syntaxerror_range(tok, format, -1, -1, vargs); + va_end(vargs); + return ret; +} + +static int +syntaxerror_known_range(struct tok_state *tok, + int col_offset, int end_col_offset, + const char *format, ...) +{ + va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + int ret = _syntaxerror_range(tok, format, col_offset, end_col_offset, vargs); + va_end(vargs); + return ret; +} + + + static int indenterror(struct tok_state *tok) { @@ -1116,6 +1159,113 @@ indenterror(struct tok_state *tok) return ERRORTOKEN; } +static int +parser_warn(struct tok_state *tok, const char *format, ...) +{ + PyObject *errmsg; + va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + errmsg = PyUnicode_FromFormatV(format, vargs); + va_end(vargs); + if (!errmsg) { + goto error; + } + + if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, errmsg, tok->filename, + tok->lineno, NULL, NULL) < 0) { + if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { + /* Replace the DeprecationWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); + syntaxerror(tok, "%U", errmsg); + } + goto error; + } + Py_DECREF(errmsg); + return 0; + +error: + Py_XDECREF(errmsg); + tok->done = E_ERROR; + return -1; +} + +static int +lookahead(struct tok_state *tok, const char *test) +{ + const char *s = test; + int res = 0; + while (1) { + int c = tok_nextc(tok); + if (*s == 0) { + res = !is_potential_identifier_char(c); + } + else if (c == *s) { + s++; + continue; + } + + tok_backup(tok, c); + while (s != test) { + tok_backup(tok, *--s); + } + return res; + } +} + +static int +verify_end_of_number(struct tok_state *tok, int c, const char *kind) +{ + /* Emit a deprecation warning only if the numeric literal is immediately + * followed by one of keywords which can occurr after a numeric literal + * in valid code: "and", "else", "for", "if", "in", "is" and "or". + * It allows to gradually deprecate existing valid code without adding + * warning before error in most cases of invalid numeric literal (which + * would be confusiong and break existing tests). + * Raise a syntax error with slighly better message than plain + * "invalid syntax" if the numeric literal is immediately followed by + * other keyword or identifier. + */ + int r = 0; + if (c == 'a') { + r = lookahead(tok, "nd"); + } + else if (c == 'e') { + r = lookahead(tok, "lse"); + } + else if (c == 'f') { + r = lookahead(tok, "or"); + } + else if (c == 'i') { + int c2 = tok_nextc(tok); + if (c2 == 'f' || c2 == 'n' || c2 == 's') { + r = 1; + } + tok_backup(tok, c2); + } + else if (c == 'o') { + r = lookahead(tok, "r"); + } + if (r) { + tok_backup(tok, c); + if (parser_warn(tok, "invalid %s literal", kind)) { + return 0; + } + tok_nextc(tok); + } + else /* In future releases, only error will remain. */ + if (is_potential_identifier_char(c)) { + tok_backup(tok, c); + syntaxerror(tok, "invalid %s literal", kind); + return 0; + } + return 1; +} + /* Verify that the identifier follows PEP 3131. All identifier strings are guaranteed to be "ready" unicode objects. */ @@ -1399,6 +1549,10 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) } } + if (tok->done == E_INTERACT_STOP) { + return ENDMARKER; + } + /* Check for EOF and errors now */ if (c == EOF) { if (tok->level) { @@ -1560,6 +1714,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); } while (isxdigit(c)); } while (c == '_'); + if (!verify_end_of_number(tok, c, "hexadecimal")) { + return ERRORTOKEN; + } } else if (c == 'o' || c == 'O') { /* Octal */ @@ -1569,12 +1726,12 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); } if (c < '0' || c >= '8') { - tok_backup(tok, c); if (isdigit(c)) { return syntaxerror(tok, "invalid digit '%c' in octal literal", c); } else { + tok_backup(tok, c); return syntaxerror(tok, "invalid octal literal"); } } @@ -1586,6 +1743,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) return syntaxerror(tok, "invalid digit '%c' in octal literal", c); } + if (!verify_end_of_number(tok, c, "octal")) { + return ERRORTOKEN; + } } else if (c == 'b' || c == 'B') { /* Binary */ @@ -1595,12 +1755,12 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); } if (c != '0' && c != '1') { - tok_backup(tok, c); if (isdigit(c)) { return syntaxerror(tok, "invalid digit '%c' in binary literal", c); } else { + tok_backup(tok, c); return syntaxerror(tok, "invalid binary literal"); } } @@ -1612,6 +1772,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) return syntaxerror(tok, "invalid digit '%c' in binary literal", c); } + if (!verify_end_of_number(tok, c, "binary")) { + return ERRORTOKEN; + } } else { int nonzero = 0; @@ -1630,6 +1793,7 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) } c = tok_nextc(tok); } + char* zeros_end = tok->cur; if (isdigit(c)) { nonzero = 1; c = tok_decimal_tail(tok); @@ -1650,10 +1814,15 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) else if (nonzero) { /* Old-style octal: now disallowed. */ tok_backup(tok, c); - return syntaxerror(tok, - "leading zeros in decimal integer " - "literals are not permitted; " - "use an 0o prefix for octal integers"); + return syntaxerror_known_range( + tok, (int)(tok->start + 1 - tok->line_start), + (int)(zeros_end - tok->line_start), + "leading zeros in decimal integer " + "literals are not permitted; " + "use an 0o prefix for octal integers"); + } + if (!verify_end_of_number(tok, c, "decimal")) { + return ERRORTOKEN; } } } @@ -1690,6 +1859,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) } } else if (!isdigit(c)) { tok_backup(tok, c); + if (!verify_end_of_number(tok, e, "decimal")) { + return ERRORTOKEN; + } tok_backup(tok, e); *p_start = tok->start; *p_end = tok->cur; @@ -1704,6 +1876,12 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) /* Imaginary part */ imaginary: c = tok_nextc(tok); + if (!verify_end_of_number(tok, c, "imaginary")) { + return ERRORTOKEN; + } + } + else if (!verify_end_of_number(tok, c, "decimal")) { + return ERRORTOKEN; } } } @@ -1746,6 +1924,7 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) while (end_quote_size != quote_size) { c = tok_nextc(tok); if (c == EOF || (quote_size == 1 && c == '\n')) { + assert(tok->multi_line_start != NULL); // shift the tok_state's location into // the start of string, and report the error // from the initial quote character @@ -1787,7 +1966,6 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) c = tok_nextc(tok); if (c != '\n') { tok->done = E_LINECONT; - tok->cur = tok->inp; return ERRORTOKEN; } c = tok_nextc(tok); @@ -1950,9 +2128,9 @@ PyTokenizer_FindEncoding(int fd) void tok_dump(int type, char *start, char *end) { - printf("%s", _PyParser_TokenNames[type]); + fprintf(stderr, "%s", _PyParser_TokenNames[type]); if (type == NAME || type == NUMBER || type == STRING || type == OP) - printf("(%.*s)", (int)(end - start), start); + fprintf(stderr, "(%.*s)", (int)(end - start), start); } #endif diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index aaa31f37962076..61f0a6138f676b 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -19,6 +19,14 @@ enum decoding_state { STATE_NORMAL }; +enum interactive_underflow_t { + /* Normal mode of operation: return a new token when asked in interactie mode */ + IUNDERFLOW_NORMAL, + /* Forcefully return ENDMARKER when asked for a new token in interactive mode. This + * can be used to prevent the tokenizer to prompt the user for new tokens */ + IUNDERFLOW_STOP, +}; + /* Tokenizer state */ struct tok_state { /* Input state; buf <= cur <= inp <= end */ @@ -63,7 +71,7 @@ struct tok_state { PyObject *decoding_readline; /* open(...).readline */ PyObject *decoding_buffer; const char* enc; /* Encoding for the current str. */ - char* str; + char* str; /* Source string being tokenized (if tokenizing from a string)*/ char* input; /* Tokenizer's newline translated copy of the string. */ int type_comments; /* Whether to look for type comments */ @@ -74,6 +82,8 @@ struct tok_state { int async_def_indent; /* Indentation level of the outermost 'async def'. */ int async_def_nl; /* =1 if the outermost 'async def' had at least one NEWLINE token after it. */ + /* How to proceed when asked for a new token in interactive mode */ + enum interactive_underflow_t interactive_underflow; }; extern struct tok_state *PyTokenizer_FromString(const char *, int); diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 0901933bfbb857..b7d4675a955a50 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -22,6 +22,9 @@ /* Use path starting with "./" avoids a search along the PATH */ #define PROGRAM_NAME L"./_testembed" +#define INIT_LOOPS 16 + + static void _testembed_Py_Initialize(void) { Py_SetProgramName(PROGRAM_NAME); @@ -54,9 +57,8 @@ static int test_repeated_init_and_subinterpreters(void) { PyThreadState *mainstate, *substate; PyGILState_STATE gilstate; - int i, j; - for (i=0; i<15; i++) { + for (int i=1; i <= INIT_LOOPS; i++) { printf("--- Pass %d ---\n", i); _testembed_Py_Initialize(); mainstate = PyThreadState_Get(); @@ -67,7 +69,7 @@ static int test_repeated_init_and_subinterpreters(void) print_subinterp(); PyThreadState_Swap(NULL); - for (j=0; j<3; j++) { + for (int j=0; j<3; j++) { substate = Py_NewInterpreter(); print_subinterp(); Py_EndInterpreter(substate); @@ -83,6 +85,20 @@ static int test_repeated_init_and_subinterpreters(void) return 0; } +#define EMBEDDED_EXT_NAME "embedded_ext" + +static PyModuleDef embedded_ext = { + PyModuleDef_HEAD_INIT, + .m_name = EMBEDDED_EXT_NAME, + .m_size = 0, +}; + +static PyObject* +PyInit_embedded_ext(void) +{ + return PyModule_Create(&embedded_ext); +} + /***************************************************** * Test forcing a particular IO encoding *****************************************************/ @@ -1646,15 +1662,26 @@ static int test_run_main(void) } +static int test_run_main_loop(void) +{ + // bpo-40413: Calling Py_InitializeFromConfig()+Py_RunMain() multiple + // times must not crash. + for (int i=0; i<5; i++) { + int exitcode = test_run_main(); + if (exitcode != 0) { + return exitcode; + } + } + return 0; +} + + static int test_get_argc_argv(void) { PyConfig config; PyConfig_InitPythonConfig(&config); - wchar_t *argv[] = {L"python3", L"-c", - (L"import sys; " - L"print(f'Py_RunMain(): sys.argv={sys.argv}')"), - L"arg2"}; + wchar_t *argv[] = {L"python3", L"-c", L"pass", L"arg2"}; config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); config_set_string(&config, &config.program_name, L"./python3"); @@ -1735,6 +1762,38 @@ static int list_frozen(void) } +static int test_repeated_init_and_inittab(void) +{ + // bpo-44441: Py_RunMain() must reset PyImport_Inittab at exit. + // It must be possible to call PyImport_AppendInittab() or + // PyImport_ExtendInittab() before each Python initialization. + for (int i=1; i <= INIT_LOOPS; i++) { + printf("--- Pass %d ---\n", i); + + // Call PyImport_AppendInittab() at each iteration + if (PyImport_AppendInittab(EMBEDDED_EXT_NAME, + &PyInit_embedded_ext) != 0) { + fprintf(stderr, "PyImport_AppendInittab() failed\n"); + return 1; + } + + // Initialize Python + wchar_t* argv[] = {PROGRAM_NAME, L"-c", L"pass"}; + PyConfig config; + PyConfig_InitPythonConfig(&config); + config.isolated = 1; + config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); + init_from_config_clear(&config); + + // Py_RunMain() calls _PyImport_Fini2() which resets PyImport_Inittab + int exitcode = Py_RunMain(); + if (exitcode != 0) { + return exitcode; + } + } + return 0; +} + /* ********************************************************* * List of test cases and the function that implements it. @@ -1755,8 +1814,10 @@ struct TestCase }; static struct TestCase TestCases[] = { + // Python initialization {"test_forced_io_encoding", test_forced_io_encoding}, {"test_repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters}, + {"test_repeated_init_and_inittab", test_repeated_init_and_inittab}, {"test_pre_initialization_api", test_pre_initialization_api}, {"test_pre_initialization_sys_options", test_pre_initialization_sys_options}, {"test_bpo20891", test_bpo20891}, @@ -1794,8 +1855,10 @@ static struct TestCase TestCases[] = { {"test_init_warnoptions", test_init_warnoptions}, {"test_init_set_config", test_init_set_config}, {"test_run_main", test_run_main}, + {"test_run_main_loop", test_run_main_loop}, {"test_get_argc_argv", test_get_argc_argv}, + // Audit {"test_open_code_hook", test_open_code_hook}, {"test_audit", test_audit}, {"test_audit_subinterpreter", test_audit_subinterpreter}, @@ -1805,8 +1868,10 @@ static struct TestCase TestCases[] = { {"test_audit_run_startup", test_audit_run_startup}, {"test_audit_run_stdin", test_audit_run_stdin}, + // Specific C API {"test_unicode_id_init", test_unicode_id_init}, + // Command {"list_frozen", list_frozen}, {NULL, NULL} }; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 5d7a0aed9beffc..2f84cad7749dd8 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1312,7 +1312,7 @@ init_types(struct ast_state *state) " | YieldFrom(expr value)\n" " | Compare(expr left, cmpop* ops, expr* comparators)\n" " | Call(expr func, expr* args, keyword* keywords)\n" - " | FormattedValue(expr value, int? conversion, expr? format_spec)\n" + " | FormattedValue(expr value, int conversion, expr? format_spec)\n" " | JoinedStr(expr* values)\n" " | Constant(constant value, string? kind)\n" " | Attribute(expr value, identifier attr, expr_context ctx)\n" @@ -1402,11 +1402,8 @@ init_types(struct ast_state *state) state->FormattedValue_type = make_type(state, "FormattedValue", state->expr_type, FormattedValue_fields, 3, - "FormattedValue(expr value, int? conversion, expr? format_spec)"); + "FormattedValue(expr value, int conversion, expr? format_spec)"); if (!state->FormattedValue_type) return 0; - if (PyObject_SetAttr(state->FormattedValue_type, state->conversion, - Py_None) == -1) - return 0; if (PyObject_SetAttr(state->FormattedValue_type, state->format_spec, Py_None) == -1) return 0; @@ -5373,7 +5370,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Module' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5406,7 +5407,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) type_ignore_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Module' node")) { + goto failed; + } res = obj2ast_type_ignore(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5451,7 +5456,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Interactive' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5483,7 +5492,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Expression' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &body, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5522,7 +5535,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5542,7 +5559,11 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &returns, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5583,7 +5604,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5596,7 +5621,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5609,7 +5638,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5622,7 +5655,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'stmt' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5648,7 +5685,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5661,7 +5702,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_arguments(state, tmp, &args, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5687,7 +5732,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5720,7 +5769,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5740,7 +5793,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &returns, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5753,7 +5810,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5785,7 +5846,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5798,7 +5863,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_arguments(state, tmp, &args, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5824,7 +5893,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5857,7 +5930,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5877,7 +5954,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &returns, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5890,7 +5971,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5922,7 +6007,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -5948,7 +6037,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -5981,7 +6074,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* keyword_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } res = obj2ast_keyword(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6014,7 +6111,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6047,7 +6148,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6081,7 +6186,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Return' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6120,7 +6229,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Delete' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6168,7 +6281,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6188,7 +6305,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6201,7 +6322,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Assign' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6229,7 +6354,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6242,7 +6371,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { + goto failed; + } res = obj2ast_operator(state, tmp, &op, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6255,7 +6388,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6284,7 +6421,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6297,7 +6438,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &annotation, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6310,7 +6455,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6323,7 +6472,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &simple, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6353,7 +6506,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'For' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6366,7 +6523,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'For' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &iter, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6392,7 +6553,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'For' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6425,7 +6590,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'For' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6445,7 +6614,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'For' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6475,7 +6648,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6488,7 +6665,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &iter, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6514,7 +6695,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6547,7 +6732,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6567,7 +6756,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6596,7 +6789,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'While' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &test, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6622,7 +6819,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'While' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6655,7 +6856,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'While' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6690,7 +6895,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'If' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &test, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6716,7 +6925,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'If' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6749,7 +6962,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'If' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6797,7 +7014,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* withitem_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'With' node")) { + goto failed; + } res = obj2ast_withitem(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6830,7 +7051,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'With' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6850,7 +7075,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'With' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6891,7 +7120,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* withitem_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { + goto failed; + } res = obj2ast_withitem(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6924,7 +7157,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -6944,7 +7181,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6971,7 +7212,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Match' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &subject, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -6997,7 +7242,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* match_case_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Match' node")) { + goto failed; + } res = obj2ast_match_case(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7031,7 +7280,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Raise' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &exc, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7044,7 +7297,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Raise' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &cause, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7086,7 +7343,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Try' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7119,7 +7380,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* excepthandler_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Try' node")) { + goto failed; + } res = obj2ast_excepthandler(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7152,7 +7417,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Try' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7185,7 +7454,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Try' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7219,7 +7492,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Assert' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &test, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7232,7 +7509,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Assert' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &msg, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7271,7 +7552,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* alias_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Import' node")) { + goto failed; + } res = obj2ast_alias(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7306,7 +7591,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &module, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7332,7 +7621,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* alias_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { + goto failed; + } res = obj2ast_alias(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7352,7 +7645,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &level, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7391,7 +7688,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* identifier val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Global' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7437,7 +7738,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* identifier val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Nonlocal' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7470,7 +7775,11 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Expr' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7548,7 +7857,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'expr' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7561,7 +7874,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'expr' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7574,7 +7891,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'expr' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7587,7 +7908,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'expr' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7609,7 +7934,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { + goto failed; + } res = obj2ast_boolop(state, tmp, &op, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7635,7 +7964,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7669,7 +8002,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7682,7 +8019,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7710,7 +8051,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &left, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7723,7 +8068,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { + goto failed; + } res = obj2ast_operator(state, tmp, &op, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7736,7 +8085,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &right, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7763,7 +8116,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { + goto failed; + } res = obj2ast_unaryop(state, tmp, &op, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7776,7 +8133,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &operand, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7803,7 +8164,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { + goto failed; + } res = obj2ast_arguments(state, tmp, &args, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7816,7 +8181,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &body, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7844,7 +8213,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &test, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7857,7 +8230,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &body, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7870,7 +8247,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &orelse, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -7910,7 +8291,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Dict' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7943,7 +8328,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Dict' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -7989,7 +8378,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Set' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8023,7 +8416,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &elt, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8049,7 +8446,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* comprehension_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { + goto failed; + } res = obj2ast_comprehension(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8083,7 +8484,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &elt, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8109,7 +8514,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* comprehension_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { + goto failed; + } res = obj2ast_comprehension(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8144,7 +8553,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &key, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8157,7 +8570,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8183,7 +8600,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* comprehension_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { + goto failed; + } res = obj2ast_comprehension(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8217,7 +8638,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &elt, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8243,7 +8668,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* comprehension_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { + goto failed; + } res = obj2ast_comprehension(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8276,7 +8705,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Await' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8302,7 +8735,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Yield' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8328,7 +8765,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'YieldFrom' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8356,7 +8797,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &left, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8382,7 +8827,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* cmpop_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) { + goto failed; + } res = obj2ast_cmpop(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8415,7 +8864,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Compare' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8450,7 +8903,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Call' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &func, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8476,7 +8933,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Call' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8509,7 +8970,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* keyword_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Call' node")) { + goto failed; + } res = obj2ast_keyword(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8544,20 +9009,28 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } if (_PyObject_LookupAttr(obj, state->conversion, &tmp) < 0) { return 1; } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - conversion = 0; + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"conversion\" missing from FormattedValue"); + return 1; } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &conversion, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8570,7 +9043,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &format_spec, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8610,7 +9087,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'JoinedStr' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8644,7 +9125,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Constant' node")) { + goto failed; + } res = obj2ast_constant(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8657,7 +9142,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Constant' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &kind, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8685,7 +9174,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8698,7 +9191,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &attr, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8711,7 +9208,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8739,7 +9240,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8752,7 +9257,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &slice, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8765,7 +9274,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8792,7 +9305,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Starred' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8805,7 +9322,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Starred' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8832,7 +9353,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Name' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &id, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8845,7 +9370,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Name' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8885,7 +9414,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'List' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8905,7 +9438,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'List' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8945,7 +9482,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -8965,7 +9506,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { + goto failed; + } res = obj2ast_expr_context(state, tmp, &ctx, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -8993,7 +9538,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &lower, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9006,7 +9555,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &upper, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9019,7 +9572,11 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'Slice' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &step, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9365,7 +9922,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &target, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9378,7 +9939,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &iter, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9404,7 +9969,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9424,7 +9993,11 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &is_async, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9461,7 +10034,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9474,7 +10051,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9487,7 +10068,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9500,7 +10085,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9523,7 +10112,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &type, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9536,7 +10129,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9562,7 +10159,11 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9620,7 +10221,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, arg_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_arg(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9653,7 +10258,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, arg_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_arg(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9673,7 +10282,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_arg(state, tmp, &vararg, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9699,7 +10312,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, arg_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_arg(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9732,7 +10349,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9752,7 +10373,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_arg(state, tmp, &kwarg, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9778,7 +10403,11 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'arguments' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -9818,7 +10447,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &arg, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9831,7 +10464,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &annotation, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9844,7 +10481,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &type_comment, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9857,7 +10498,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9870,7 +10515,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9883,7 +10532,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9896,7 +10549,11 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'arg' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9929,7 +10586,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &arg, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9942,7 +10603,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9955,7 +10620,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9968,7 +10637,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9981,7 +10654,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -9994,7 +10671,11 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'keyword' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10027,7 +10708,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10040,7 +10725,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &asname, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10053,7 +10742,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10066,7 +10759,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10079,7 +10776,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10092,7 +10793,11 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'alias' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10121,7 +10826,11 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'withitem' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &context_expr, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10134,7 +10843,11 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'withitem' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &optional_vars, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10163,7 +10876,11 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'match_case' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp, &pattern, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10176,7 +10893,11 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'match_case' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &guard, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10202,7 +10923,11 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, stmt_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'match_case' node")) { + goto failed; + } res = obj2ast_stmt(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10246,7 +10971,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'pattern' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10259,7 +10988,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'pattern' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10272,7 +11005,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'pattern' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10285,7 +11022,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'pattern' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &end_col_offset, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10306,7 +11047,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchValue' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10332,7 +11077,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchSingleton' node")) { + goto failed; + } res = obj2ast_constant(state, tmp, &value, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10371,7 +11120,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, pattern_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchSequence' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10419,7 +11172,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, expr_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { + goto failed; + } res = obj2ast_expr(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10452,7 +11209,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, pattern_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10472,7 +11233,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &rest, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10501,7 +11266,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { + goto failed; + } res = obj2ast_expr(state, tmp, &cls, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10527,7 +11296,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, pattern_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10560,7 +11333,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, identifier val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10593,7 +11370,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, pattern_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10627,7 +11408,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchStar' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10654,7 +11439,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp, &pattern, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10667,7 +11456,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { + goto failed; + } res = obj2ast_identifier(state, tmp, &name, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10706,7 +11499,11 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, pattern_ty val; PyObject *tmp2 = PyList_GET_ITEM(tmp, i); Py_INCREF(tmp2); + if (Py_EnterRecursiveCall(" while traversing 'MatchOr' node")) { + goto failed; + } res = obj2ast_pattern(state, tmp2, &val, arena); + Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; if (len != PyList_GET_SIZE(tmp)) { @@ -10760,7 +11557,11 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { + goto failed; + } res = obj2ast_int(state, tmp, &lineno, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } @@ -10773,7 +11574,11 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* } else { int res; + if (Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { + goto failed; + } res = obj2ast_string(state, tmp, &tag, arena); + Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); } diff --git a/Python/ast.c b/Python/ast.c index 1fc83f6301962d..2113124dbd51c2 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -15,11 +15,12 @@ struct validator { }; static int validate_stmts(struct validator *, asdl_stmt_seq *); -static int validate_exprs(struct validator *, asdl_expr_seq*, expr_context_ty, int); +static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int); +static int validate_patterns(struct validator *, asdl_pattern_seq *, int); static int _validate_nonempty_seq(asdl_seq *, const char *, const char *); static int validate_stmt(struct validator *, stmt_ty); static int validate_expr(struct validator *, expr_ty, expr_context_ty); -static int validate_pattern(struct validator *, pattern_ty); +static int validate_pattern(struct validator *, pattern_ty, int); static int validate_name(PyObject *name) @@ -33,7 +34,7 @@ validate_name(PyObject *name) }; for (int i = 0; forbidden[i] != NULL; i++) { if (_PyUnicode_EqualToASCIIString(name, forbidden[i])) { - PyErr_Format(PyExc_ValueError, "Name node can't be used with '%s' constant", forbidden[i]); + PyErr_Format(PyExc_ValueError, "identifier field can't represent '%s' constant", forbidden[i]); return 0; } } @@ -448,6 +449,21 @@ validate_pattern_match_value(struct validator *state, expr_ty exp) switch (exp->kind) { case Constant_kind: + /* Ellipsis and immutable sequences are not allowed. + For True, False and None, MatchSingleton() should + be used */ + if (!validate_expr(state, exp, Load)) { + return 0; + } + PyObject *literal = exp->v.Constant.value; + if (PyLong_CheckExact(literal) || PyFloat_CheckExact(literal) || + PyBytes_CheckExact(literal) || PyComplex_CheckExact(literal) || + PyUnicode_CheckExact(literal)) { + return 1; + } + PyErr_SetString(PyExc_ValueError, + "unexpected constant inside of a literal pattern"); + return 0; case Attribute_kind: // Constants and attribute lookups are always permitted return 1; @@ -465,16 +481,29 @@ validate_pattern_match_value(struct validator *state, expr_ty exp) return 1; } break; + case JoinedStr_kind: + // Handled in the later stages + return 1; default: break; } - PyErr_SetString(PyExc_SyntaxError, - "patterns may only match literals and attribute lookups"); + PyErr_SetString(PyExc_ValueError, + "patterns may only match literals and attribute lookups"); return 0; } static int -validate_pattern(struct validator *state, pattern_ty p) +validate_capture(PyObject *name) +{ + if (_PyUnicode_EqualToASCIIString(name, "_")) { + PyErr_Format(PyExc_ValueError, "can't capture name '_' in patterns"); + return 0; + } + return validate_name(name); +} + +static int +validate_pattern(struct validator *state, pattern_ty p, int star_ok) { int ret = -1; if (++state->recursion_depth > state->recursion_limit) { @@ -482,74 +511,131 @@ validate_pattern(struct validator *state, pattern_ty p) "maximum recursion depth exceeded during compilation"); return 0; } - // Coming soon: https://bugs.python.org/issue43897 (thanks Batuhan)! - // TODO: Ensure no subnodes use "_" as an ordinary identifier switch (p->kind) { case MatchValue_kind: ret = validate_pattern_match_value(state, p->v.MatchValue.value); break; case MatchSingleton_kind: - // TODO: Check constant is specifically None, True, or False - ret = validate_constant(state, p->v.MatchSingleton.value); + ret = p->v.MatchSingleton.value == Py_None || PyBool_Check(p->v.MatchSingleton.value); + if (!ret) { + PyErr_SetString(PyExc_ValueError, + "MatchSingleton can only contain True, False and None"); + } break; case MatchSequence_kind: - // TODO: Validate all subpatterns - // return validate_patterns(state, p->v.MatchSequence.patterns); - ret = 1; + ret = validate_patterns(state, p->v.MatchSequence.patterns, /*star_ok=*/1); break; case MatchMapping_kind: - // TODO: check "rest" target name is valid if (asdl_seq_LEN(p->v.MatchMapping.keys) != asdl_seq_LEN(p->v.MatchMapping.patterns)) { PyErr_SetString(PyExc_ValueError, "MatchMapping doesn't have the same number of keys as patterns"); - return 0; + ret = 0; + break; } - // null_ok=0 for key expressions, as rest-of-mapping is captured in "rest" - // TODO: replace with more restrictive expression validator, as per MatchValue above - if (!validate_exprs(state, p->v.MatchMapping.keys, Load, /*null_ok=*/ 0)) { - return 0; + + if (p->v.MatchMapping.rest && !validate_capture(p->v.MatchMapping.rest)) { + ret = 0; + break; } - // TODO: Validate all subpatterns - // ret = validate_patterns(state, p->v.MatchMapping.patterns); - ret = 1; + + asdl_expr_seq *keys = p->v.MatchMapping.keys; + for (Py_ssize_t i = 0; i < asdl_seq_LEN(keys); i++) { + expr_ty key = asdl_seq_GET(keys, i); + if (key->kind == Constant_kind) { + PyObject *literal = key->v.Constant.value; + if (literal == Py_None || PyBool_Check(literal)) { + /* validate_pattern_match_value will ensure the key + doesn't contain True, False and None but it is + syntactically valid, so we will pass those on in + a special case. */ + continue; + } + } + if (!validate_pattern_match_value(state, key)) { + ret = 0; + break; + } + } + + ret = validate_patterns(state, p->v.MatchMapping.patterns, /*star_ok=*/0); break; case MatchClass_kind: if (asdl_seq_LEN(p->v.MatchClass.kwd_attrs) != asdl_seq_LEN(p->v.MatchClass.kwd_patterns)) { PyErr_SetString(PyExc_ValueError, "MatchClass doesn't have the same number of keyword attributes as patterns"); - return 0; + ret = 0; + break; } - // TODO: Restrict cls lookup to being a name or attribute if (!validate_expr(state, p->v.MatchClass.cls, Load)) { - return 0; + ret = 0; + break; } - // TODO: Validate all subpatterns - // return validate_patterns(state, p->v.MatchClass.patterns) && - // validate_patterns(state, p->v.MatchClass.kwd_patterns); - ret = 1; + + expr_ty cls = p->v.MatchClass.cls; + while (1) { + if (cls->kind == Name_kind) { + break; + } + else if (cls->kind == Attribute_kind) { + cls = cls->v.Attribute.value; + continue; + } + else { + PyErr_SetString(PyExc_ValueError, + "MatchClass cls field can only contain Name or Attribute nodes."); + ret = 0; + break; + } + } + + for (Py_ssize_t i = 0; i < asdl_seq_LEN(p->v.MatchClass.kwd_attrs); i++) { + PyObject *identifier = asdl_seq_GET(p->v.MatchClass.kwd_attrs, i); + if (!validate_name(identifier)) { + ret = 0; + break; + } + } + + if (!validate_patterns(state, p->v.MatchClass.patterns, /*star_ok=*/0)) { + ret = 0; + break; + } + + ret = validate_patterns(state, p->v.MatchClass.kwd_patterns, /*star_ok=*/0); break; case MatchStar_kind: - // TODO: check target name is valid - ret = 1; + if (!star_ok) { + PyErr_SetString(PyExc_ValueError, "can't use MatchStar here"); + ret = 0; + break; + } + ret = p->v.MatchStar.name == NULL || validate_capture(p->v.MatchStar.name); break; case MatchAs_kind: - // TODO: check target name is valid + if (p->v.MatchAs.name && !validate_capture(p->v.MatchAs.name)) { + ret = 0; + break; + } if (p->v.MatchAs.pattern == NULL) { ret = 1; } else if (p->v.MatchAs.name == NULL) { PyErr_SetString(PyExc_ValueError, "MatchAs must specify a target name if a pattern is given"); - return 0; + ret = 0; } else { - ret = validate_pattern(state, p->v.MatchAs.pattern); + ret = validate_pattern(state, p->v.MatchAs.pattern, /*star_ok=*/0); } break; case MatchOr_kind: - // TODO: Validate all subpatterns - // return validate_patterns(state, p->v.MatchOr.patterns); - ret = 1; + if (asdl_seq_LEN(p->v.MatchOr.patterns) < 2) { + PyErr_SetString(PyExc_ValueError, + "MatchOr requires at least 2 patterns"); + ret = 0; + break; + } + ret = validate_patterns(state, p->v.MatchOr.patterns, /*star_ok=*/0); break; // No default case, so the compiler will emit a warning if new pattern // kinds are added without being handled here @@ -686,7 +772,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) } for (i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) { match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i); - if (!validate_pattern(state, m->pattern) + if (!validate_pattern(state, m->pattern, /*star_ok=*/0) || (m->guard && !validate_expr(state, m->guard, Load)) || !validate_body(state, m->body, "match_case")) { return 0; @@ -815,6 +901,20 @@ validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ct return 1; } +static int +validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ok) +{ + Py_ssize_t i; + for (i = 0; i < asdl_seq_LEN(patterns); i++) { + pattern_ty pattern = asdl_seq_GET(patterns, i); + if (!validate_pattern(state, pattern, star_ok)) { + return 0; + } + } + return 1; +} + + /* See comments in symtable.c. */ #define COMPILER_STACK_FRAME_SCALE 3 diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 66a74cbdef6104..b0162e5e87217a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -72,6 +72,7 @@ update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs) /* If this is a first successful replacement, create new_bases list and copy previously encountered bases. */ if (!(new_bases = PyList_New(i))) { + Py_DECREF(new_base); goto error; } for (j = 0; j < i; j++) { @@ -82,6 +83,7 @@ update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs) } j = PyList_GET_SIZE(new_bases); if (PyList_SetSlice(new_bases, j, j, new_base) < 0) { + Py_DECREF(new_base); goto error; } Py_DECREF(new_base); @@ -103,8 +105,9 @@ static PyObject * builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *orig_bases; - PyObject *cls = NULL, *cell = NULL; + PyObject *func, *name, *winner, *prep; + PyObject *cls = NULL, *cell = NULL, *ns = NULL, *meta = NULL, *orig_bases = NULL; + PyObject *mkw = NULL, *bases = NULL; int isclass = 0; /* initialize to prevent gcc warning */ if (nargs < 2) { @@ -141,26 +144,20 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, else { mkw = _PyStack_AsDict(args + nargs, kwnames); if (mkw == NULL) { - Py_DECREF(bases); - return NULL; + goto error; } meta = _PyDict_GetItemIdWithError(mkw, &PyId_metaclass); if (meta != NULL) { Py_INCREF(meta); if (_PyDict_DelItemId(mkw, &PyId_metaclass) < 0) { - Py_DECREF(meta); - Py_DECREF(mkw); - Py_DECREF(bases); - return NULL; + goto error; } /* metaclass is explicitly given, check if it's indeed a class */ isclass = PyType_Check(meta); } else if (PyErr_Occurred()) { - Py_DECREF(mkw); - Py_DECREF(bases); - return NULL; + goto error; } } if (meta == NULL) { @@ -183,10 +180,7 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, winner = (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)meta, bases); if (winner == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; + goto error; } if (winner != meta) { Py_DECREF(meta); @@ -208,10 +202,7 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py_DECREF(prep); } if (ns == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; + goto error; } if (!PyMapping_Check(ns)) { PyErr_Format(PyExc_TypeError, @@ -252,13 +243,13 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, } error: Py_XDECREF(cell); - Py_DECREF(ns); - Py_DECREF(meta); + Py_XDECREF(ns); + Py_XDECREF(meta); Py_XDECREF(mkw); - Py_DECREF(bases); if (bases != orig_bases) { Py_DECREF(orig_bases); } + Py_DECREF(bases); return cls; } @@ -1619,7 +1610,7 @@ static PyObject * builtin_aiter(PyObject *module, PyObject *async_iterable) /*[clinic end generated code: output=1bae108d86f7960e input=473993d0cacc7d23]*/ { - return PyObject_GetAiter(async_iterable); + return PyObject_GetAIter(async_iterable); } PyObject *PyAnextAwaitable_New(PyObject *, PyObject *); diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index a212f69870ed10..e189ce0d9014bf 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -25,7 +25,7 @@ # include #endif -#if defined(__APPLE__) && defined(__has_builtin) +#if defined(__APPLE__) && defined(__has_builtin) # if __has_builtin(__builtin_available) # define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *) # endif @@ -221,7 +221,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise) #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability) static int -py_getentropy(char *buffer, Py_ssize_t size, int raise) +py_getentropy(char *buffer, Py_ssize_t size, int raise) __attribute__((availability(macos,introduced=10.12))) __attribute__((availability(ios,introduced=10.0))) __attribute__((availability(tvos,introduced=10.0))) diff --git a/Python/ceval.c b/Python/ceval.c index 25548e34db246b..ab10b4166d6d21 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -35,7 +35,6 @@ typedef struct { PyCodeObject *code; // The code object for the bounds. May be NULL. - int instr_prev; // Only valid if code != NULL. PyCodeAddressRange bounds; // Only valid if code != NULL. CFrame cframe; } PyTraceInfo; @@ -78,8 +77,8 @@ static void call_exc_trace(Py_tracefunc, PyObject *, PyTraceInfo *trace_info); static int maybe_call_line_trace(Py_tracefunc, PyObject *, PyThreadState *, PyFrameObject *, - PyTraceInfo *); -static void maybe_dtrace_line(PyFrameObject *, PyTraceInfo *); + PyTraceInfo *, int); +static void maybe_dtrace_line(PyFrameObject *, PyTraceInfo *, int); static void dtrace_function_entry(PyFrameObject *); static void dtrace_function_return(PyFrameObject *); @@ -1298,12 +1297,6 @@ eval_frame_handle_pending(PyThreadState *tstate) #if USE_COMPUTED_GOTOS #define TARGET(op) op: TARGET_##op -#define DISPATCH_GOTO() goto *opcode_targets[opcode] -#else -#define TARGET(op) op -#define DISPATCH_GOTO() goto dispatch_opcode -#endif - #define DISPATCH() \ { \ if (trace_info.cframe.use_tracing OR_DTRACE_LINE OR_LLTRACE) { \ @@ -1311,8 +1304,13 @@ eval_frame_handle_pending(PyThreadState *tstate) } \ f->f_lasti = INSTR_OFFSET(); \ NEXTOPARG(); \ - DISPATCH_GOTO(); \ + goto *opcode_targets[opcode]; \ } +#else +#define TARGET(op) op +#define DISPATCH() goto predispatch; +#endif + #define CHECK_EVAL_BREAKER() \ if (_Py_atomic_load_relaxed(eval_breaker)) { \ @@ -1781,11 +1779,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) } tracing_dispatch: + { + int instr_prev = f->f_lasti; f->f_lasti = INSTR_OFFSET(); NEXTOPARG(); if (PyDTrace_LINE_ENABLED()) - maybe_dtrace_line(f, &trace_info); + maybe_dtrace_line(f, &trace_info, instr_prev); /* line-by-line tracing support */ @@ -1799,7 +1799,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) err = maybe_call_line_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f, - &trace_info); + &trace_info, instr_prev); /* Reload possibly changed frame fields */ JUMPTO(f->f_lasti); stack_pointer = f->f_valuestack+f->f_stackdepth; @@ -1810,6 +1810,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) } NEXTOPARG(); } + } #ifdef LLTRACE /* Instruction tracing */ @@ -1825,7 +1826,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) } } #endif +#if USE_COMPUTED_GOTOS == 0 + goto dispatch_opcode; + predispatch: + if (trace_info.cframe.use_tracing OR_DTRACE_LINE OR_LLTRACE) { + goto tracing_dispatch; + } + f->f_lasti = INSTR_OFFSET(); + NEXTOPARG(); +#endif dispatch_opcode: #ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DXPAIRS @@ -2639,25 +2649,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) case TARGET(GEN_START): { PyObject *none = POP(); + assert(none == Py_None); + assert(oparg < 3); Py_DECREF(none); - if (!Py_IsNone(none)) { - if (oparg > 2) { - _PyErr_SetString(tstate, PyExc_SystemError, - "Illegal kind for GEN_START"); - } - else { - static const char *gen_kind[3] = { - "generator", - "coroutine", - "async generator" - }; - _PyErr_Format(tstate, PyExc_TypeError, - "can't send non-None value to a " - "just-started %s", - gen_kind[oparg]); - } - goto error; - } DISPATCH(); } @@ -3757,14 +3751,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) if (Py_IsFalse(cond)) { Py_DECREF(cond); JUMPTO(oparg); + CHECK_EVAL_BREAKER(); DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); if (err > 0) ; - else if (err == 0) + else if (err == 0) { JUMPTO(oparg); + CHECK_EVAL_BREAKER(); + } else goto error; DISPATCH(); @@ -3781,12 +3778,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) if (Py_IsTrue(cond)) { Py_DECREF(cond); JUMPTO(oparg); + CHECK_EVAL_BREAKER(); DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); if (err > 0) { JUMPTO(oparg); + CHECK_EVAL_BREAKER(); } else if (err == 0) ; @@ -4502,9 +4501,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) PUSH(val); PUSH(exc); JUMPTO(handler); - if (trace_info.cframe.use_tracing) { - trace_info.instr_prev = INT_MAX; - } /* Resume normal execution */ f->f_state = FRAME_EXECUTING; goto main_loop; @@ -5094,7 +5090,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, PyObject *kwdefs, PyObject *closure) { PyThreadState *tstate = _PyThreadState_GET(); - PyObject *res; + PyObject *res = NULL; PyObject *defaults = _PyTuple_FromArray(defs, defcount); if (defaults == NULL) { return NULL; @@ -5107,23 +5103,19 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, if (locals == NULL) { locals = globals; } - PyObject *kwnames; + PyObject *kwnames = NULL; PyObject *const *allargs; - PyObject **newargs; + PyObject **newargs = NULL; if (kwcount == 0) { allargs = args; - kwnames = NULL; } else { kwnames = PyTuple_New(kwcount); if (kwnames == NULL) { - res = NULL; goto fail; } newargs = PyMem_Malloc(sizeof(PyObject *)*(kwcount+argcount)); if (newargs == NULL) { - res = NULL; - Py_DECREF(kwnames); goto fail; } for (int i = 0; i < argcount; i++) { @@ -5136,16 +5128,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } allargs = newargs; } - PyObject **kwargs = PyMem_Malloc(sizeof(PyObject *)*kwcount); - if (kwargs == NULL) { - res = NULL; - Py_DECREF(kwnames); - goto fail; - } for (int i = 0; i < kwcount; i++) { Py_INCREF(kws[2*i]); PyTuple_SET_ITEM(kwnames, i, kws[2*i]); - kwargs[i] = kws[2*i+1]; } PyFrameConstructor constr = { .fc_globals = globals, @@ -5160,11 +5145,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, res = _PyEval_Vector(tstate, &constr, locals, allargs, argcount, kwnames); - if (kwcount) { - Py_DECREF(kwnames); - PyMem_Free(newargs); - } fail: + Py_XDECREF(kwnames); + PyMem_Free(newargs); Py_DECREF(defaults); return res; } @@ -5386,11 +5369,14 @@ static int prtrace(PyThreadState *tstate, PyObject *v, const char *str) { printf("%s ", str); + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); if (PyObject_Print(v, stdout, 0) != 0) { /* Don't know what else to do */ _PyErr_Clear(tstate); } printf("\n"); + PyErr_Restore(type, value, traceback); return 1; } #endif @@ -5455,7 +5441,6 @@ initialize_trace_info(PyTraceInfo *trace_info, PyFrameObject *frame) { if (trace_info->code != frame->f_code) { trace_info->code = frame->f_code; - trace_info->instr_prev = -1; _PyCode_InitAddressRange(frame->f_code, &trace_info->bounds); } } @@ -5476,7 +5461,7 @@ call_trace(Py_tracefunc func, PyObject *obj, } else { initialize_trace_info(trace_info, frame); - frame->f_lineno = _PyCode_CheckLineNumber(frame->f_lasti*2, &trace_info->bounds); + frame->f_lineno = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds); } result = func(obj, frame, what, arg); frame->f_lineno = 0; @@ -5507,7 +5492,7 @@ _PyEval_CallTracing(PyObject *func, PyObject *args) static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, PyThreadState *tstate, PyFrameObject *frame, - PyTraceInfo *trace_info) + PyTraceInfo *trace_info, int instr_prev) { int result = 0; @@ -5516,13 +5501,11 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, then call the trace function if we're tracing source lines. */ initialize_trace_info(trace_info, frame); - int lastline = trace_info->bounds.ar_line; - int line = _PyCode_CheckLineNumber(frame->f_lasti*2, &trace_info->bounds); + int lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &trace_info->bounds); + int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds); if (line != -1 && frame->f_trace_lines) { - /* Trace backward edges or first instruction of a new line */ - if (frame->f_lasti < trace_info->instr_prev || - (line != lastline && frame->f_lasti*2 == trace_info->bounds.ar_start)) - { + /* Trace backward edges or if line number has changed */ + if (frame->f_lasti < instr_prev || line != lastline) { result = call_trace(func, obj, tstate, frame, trace_info, PyTrace_LINE, Py_None); } } @@ -5530,7 +5513,6 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, if (frame->f_trace_opcodes) { result = call_trace(func, obj, tstate, frame, trace_info, PyTrace_OPCODE, Py_None); } - trace_info->instr_prev = frame->f_lasti; return result; } @@ -6475,7 +6457,7 @@ dtrace_function_return(PyFrameObject *f) /* DTrace equivalent of maybe_call_line_trace. */ static void maybe_dtrace_line(PyFrameObject *frame, - PyTraceInfo *trace_info) + PyTraceInfo *trace_info, int instr_prev) { const char *co_filename, *co_name; @@ -6483,11 +6465,11 @@ maybe_dtrace_line(PyFrameObject *frame, instruction window, reset the window. */ initialize_trace_info(trace_info, frame); - int line = _PyCode_CheckLineNumber(frame->f_lasti*2, &trace_info->bounds); + int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds); /* If the last instruction falls at the start of a line or if it represents a jump backwards, update the frame's line number and call the trace function. */ - if (line != frame->f_lineno || frame->f_lasti < trace_info->instr_prev) { + if (line != frame->f_lineno || frame->f_lasti < instr_prev) { if (line != -1) { frame->f_lineno = line; co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); @@ -6499,7 +6481,6 @@ maybe_dtrace_line(PyFrameObject *frame, PyDTrace_LINE(co_filename, co_name, line); } } - trace_info->instr_prev = frame->f_lasti; } diff --git a/Python/compile.c b/Python/compile.c index 4fc8b38d978289..3eb34d89cc55fe 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -21,6 +21,8 @@ * objects. */ +#include + #include "Python.h" #include "pycore_ast.h" // _PyAST_GetDocString() #include "pycore_compile.h" // _PyFuture_FromAST() @@ -862,7 +864,7 @@ compiler_copy_block(struct compiler *c, basicblock *block) * a block can only have one fallthrough predecessor. */ assert(block->b_nofallthrough); - basicblock *result = compiler_next_block(c); + basicblock *result = compiler_new_block(c); if (result == NULL) { return NULL; } @@ -1568,12 +1570,14 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) } #define ADDOP_O(C, OP, O, TYPE) { \ + assert((OP) != LOAD_CONST); /* use ADDOP_LOAD_CONST */ \ if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ return 0; \ } /* Same as ADDOP_O, but steals a reference. */ #define ADDOP_N(C, OP, O, TYPE) { \ + assert((OP) != LOAD_CONST); /* use ADDOP_LOAD_CONST_NEW */ \ if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) { \ Py_DECREF((O)); \ return 0; \ @@ -1751,7 +1755,7 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) static int compiler_call_exit_with_nones(struct compiler *c) { - ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP_LOAD_CONST(c, Py_None); ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP); ADDOP_I(c, CALL_FUNCTION, 3); @@ -1767,7 +1771,6 @@ static int compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, int preserve_tos) { - int loc; switch (info->fb_type) { case WHILE_LOOP: case EXCEPTION_HANDLER: @@ -1820,7 +1823,6 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, case WITH: case ASYNC_WITH: - loc = c->u->u_lineno; SET_LOC(c, (stmt_ty)info->fb_datum); ADDOP(c, POP_BLOCK); if (preserve_tos) { @@ -1835,7 +1837,10 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP(c, YIELD_FROM); } ADDOP(c, POP_TOP); - c->u->u_lineno = loc; + /* The exit block should appear to execute after the + * statement causing the unwinding, so make the unwinding + * instruction artificial */ + c->u->u_lineno = -1; return 1; case HANDLER_CLEANUP: @@ -2263,6 +2268,10 @@ forbidden_name(struct compiler *c, identifier name, expr_context_ty ctx) compiler_error(c, "cannot assign to __debug__"); return 1; } + if (ctx == Del && _PyUnicode_EqualToASCIIString(name, "__debug__")) { + compiler_error(c, "cannot delete __debug__"); + return 1; + } return 0; } @@ -2922,7 +2931,9 @@ compiler_async_for(struct compiler *c, stmt_ty s) /* Except block for __anext__ */ compiler_use_next_block(c, except); - c->u->u_lineno = -1; + /* Use same line number as the iterator, + * as the END_ASYNC_FOR succeeds the `for`, not the body. */ + SET_LOC(c, s->v.AsyncFor.iter); ADDOP(c, END_ASYNC_FOR); /* `else` block */ @@ -2986,12 +2997,17 @@ compiler_return(struct compiler *c, stmt_ty s) if (preserve_tos) { VISIT(c, expr, s->v.Return.value); } else { - /* Emit instruction with line number for expression */ + /* Emit instruction with line number for return value */ if (s->v.Return.value != NULL) { SET_LOC(c, s->v.Return.value); ADDOP(c, NOP); } } + if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) { + SET_LOC(c, s); + ADDOP(c, NOP); + } + if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL)) return 0; if (s->v.Return.value == NULL) { @@ -3010,6 +3026,8 @@ static int compiler_break(struct compiler *c) { struct fblockinfo *loop = NULL; + /* Emit instruction with line number */ + ADDOP(c, NOP); if (!compiler_unwind_fblock_stack(c, 0, &loop)) { return 0; } @@ -3028,6 +3046,8 @@ static int compiler_continue(struct compiler *c) { struct fblockinfo *loop = NULL; + /* Emit instruction with line number */ + ADDOP(c, NOP); if (!compiler_unwind_fblock_stack(c, 0, &loop)) { return 0; } @@ -3165,9 +3185,9 @@ compiler_try_except(struct compiler *c, stmt_ty s) for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.Try.handlers, i); + SET_LOC(c, handler); if (!handler->v.ExceptHandler.type && i < n-1) return compiler_error(c, "default 'except:' must be last"); - SET_LOC(c, handler); except = compiler_new_block(c); if (except == NULL) return 0; @@ -3210,10 +3230,10 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* second # body */ VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); - ADDOP(c, POP_BLOCK); - ADDOP(c, POP_EXCEPT); /* name = None; del name; # Mark as artificial */ c->u->u_lineno = -1; + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT); ADDOP_LOAD_CONST(c, Py_None); compiler_nameop(c, handler->v.ExceptHandler.name, Store); compiler_nameop(c, handler->v.ExceptHandler.name, Del); @@ -3244,7 +3264,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) return 0; VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); - /* name = None; del name; # Mark as artificial */ c->u->u_lineno = -1; ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP_FORWARD, end); @@ -4261,7 +4280,7 @@ validate_keywords(struct compiler *c, asdl_keyword_seq *keywords) for (Py_ssize_t j = i + 1; j < nkeywords; j++) { keyword_ty other = ((keyword_ty)asdl_seq_GET(keywords, j)); if (other->arg && !PyUnicode_Compare(key->arg, other->arg)) { - c->u->u_col_offset = other->col_offset; + SET_LOC(c, other); compiler_error(c, "keyword argument repeated: %U", key->arg); return -1; } @@ -4789,6 +4808,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, { goto error; } + SET_LOC(c, e); is_async_generator = c->u->u_ste->ste_coroutine; @@ -5046,7 +5066,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) if(!compiler_call_exit_with_nones(c)) return 0; ADDOP(c, GET_AWAITABLE); - ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP_LOAD_CONST(c, Py_None); ADDOP(c, YIELD_FROM); ADDOP(c, POP_TOP); @@ -5297,11 +5317,15 @@ static int compiler_visit_expr(struct compiler *c, expr_ty e) { int old_lineno = c->u->u_lineno; + int old_end_lineno = c->u->u_end_lineno; int old_col_offset = c->u->u_col_offset; + int old_end_col_offset = c->u->u_end_col_offset; SET_LOC(c, e); int res = compiler_visit_expr1(c, e); c->u->u_lineno = old_lineno; + c->u->u_end_lineno = old_end_lineno; c->u->u_col_offset = old_col_offset; + c->u->u_end_col_offset = old_end_col_offset; return res; } @@ -5312,7 +5336,9 @@ compiler_augassign(struct compiler *c, stmt_ty s) expr_ty e = s->v.AugAssign.target; int old_lineno = c->u->u_lineno; + int old_end_lineno = c->u->u_end_lineno; int old_col_offset = c->u->u_col_offset; + int old_end_col_offset = c->u->u_end_col_offset; SET_LOC(c, e); switch (e->kind) { @@ -5342,7 +5368,9 @@ compiler_augassign(struct compiler *c, stmt_ty s) } c->u->u_lineno = old_lineno; + c->u->u_end_lineno = old_end_lineno; c->u->u_col_offset = old_col_offset; + c->u->u_end_col_offset = old_end_col_offset; VISIT(c, expr, s->v.AugAssign.value); ADDOP(c, inplace_binop(s->v.AugAssign.op)); @@ -5863,14 +5891,14 @@ validate_kwd_attrs(struct compiler *c, asdl_identifier_seq *attrs, asdl_pattern_ Py_ssize_t nattrs = asdl_seq_LEN(attrs); for (Py_ssize_t i = 0; i < nattrs; i++) { identifier attr = ((identifier)asdl_seq_GET(attrs, i)); - c->u->u_col_offset = ((pattern_ty) asdl_seq_GET(patterns, i))->col_offset; + SET_LOC(c, ((pattern_ty) asdl_seq_GET(patterns, i))); if (forbidden_name(c, attr, Store)) { return -1; } for (Py_ssize_t j = i + 1; j < nattrs; j++) { identifier other = ((identifier)asdl_seq_GET(attrs, j)); if (!PyUnicode_Compare(attr, other)) { - c->u->u_col_offset = ((pattern_ty) asdl_seq_GET(patterns, j))->col_offset; + SET_LOC(c, ((pattern_ty) asdl_seq_GET(patterns, j))); compiler_error(c, "attribute name repeated in class pattern: %U", attr); return -1; } @@ -5901,7 +5929,7 @@ compiler_pattern_class(struct compiler *c, pattern_ty p, pattern_context *pc) } if (nattrs) { RETURN_IF_FALSE(!validate_kwd_attrs(c, kwd_attrs, kwd_patterns)); - c->u->u_col_offset = p->col_offset; // validate_kwd_attrs moves this + SET_LOC(c, p); } VISIT(c, expr, p->v.MatchClass.cls); PyObject *attr_names; @@ -5980,20 +6008,53 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc) } // Collect all of the keys into a tuple for MATCH_KEYS and // COPY_DICT_WITHOUT_KEYS. They can either be dotted names or literals: + + // Maintaining a set of Constant_kind kind keys allows us to raise a + // SyntaxError in the case of duplicates. + PyObject *seen = PySet_New(NULL); + if (seen == NULL) { + return 0; + } + + // NOTE: goto error on failure in the loop below to avoid leaking `seen` for (Py_ssize_t i = 0; i < size; i++) { expr_ty key = asdl_seq_GET(keys, i); if (key == NULL) { const char *e = "can't use NULL keys in MatchMapping " "(set 'rest' parameter instead)"; - c->u->u_col_offset = ((pattern_ty) asdl_seq_GET(patterns, i))->col_offset; - return compiler_error(c, e); + SET_LOC(c, ((pattern_ty) asdl_seq_GET(patterns, i))); + compiler_error(c, e); + goto error; + } + + if (key->kind == Constant_kind) { + int in_seen = PySet_Contains(seen, key->v.Constant.value); + if (in_seen < 0) { + goto error; + } + if (in_seen) { + const char *e = "mapping pattern checks duplicate key (%R)"; + compiler_error(c, e, key->v.Constant.value); + goto error; + } + if (PySet_Add(seen, key->v.Constant.value)) { + goto error; + } } - if (!MATCH_VALUE_EXPR(key)) { + + else if (key->kind != Attribute_kind) { const char *e = "mapping pattern keys may only match literals and attribute lookups"; - return compiler_error(c, e); + compiler_error(c, e); + goto error; + } + if (!compiler_visit_expr(c, key)) { + goto error; } - VISIT(c, expr, key); } + + // all keys have been checked; there are no duplicates + Py_DECREF(seen); + ADDOP_I(c, BUILD_TUPLE, size); ADDOP(c, MATCH_KEYS); // There's now a tuple of keys and a tuple of values on top of the subject: @@ -6028,6 +6089,10 @@ compiler_pattern_mapping(struct compiler *c, pattern_ty p, pattern_context *pc) pc->on_top--; ADDOP(c, POP_TOP); return 1; + +error: + Py_DECREF(seen); + return 0; } static int @@ -6094,7 +6159,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) // cases, though. assert(istores < icontrol); Py_ssize_t rotations = istores + 1; - // Perfom the same rotation on pc->stores: + // Perform the same rotation on pc->stores: PyObject *rotated = PyList_GetSlice(pc->stores, 0, rotations); if (rotated == NULL || @@ -6341,17 +6406,25 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) } VISIT_SEQ(c, stmt, m->body); ADDOP_JUMP(c, JUMP_FORWARD, end); + // If the pattern fails to match, we want the line number of the + // cleanup to be associated with the failed pattern, not the last line + // of the body + SET_LOC(c, m->pattern); RETURN_IF_FALSE(emit_and_reset_fail_pop(c, pc)); } if (has_default) { - if (cases == 1) { - // No matches. Done with the subject: - ADDOP(c, POP_TOP); - } // A trailing "case _" is common, and lets us save a bit of redundant // pushing and popping in the loop above: m = asdl_seq_GET(s->v.Match.cases, cases - 1); SET_LOC(c, m->pattern); + if (cases == 1) { + // No matches. Done with the subject: + ADDOP(c, POP_TOP); + } + else { + // Show line coverage for default case (it doesn't create bytecode) + ADDOP(c, NOP); + } if (m->guard) { RETURN_IF_FALSE(compiler_jump_if(c, m->guard, end, 0)); } @@ -6548,7 +6621,7 @@ static int assemble_line_range(struct assembler *a) { int ldelta, bdelta; - bdelta = (a->a_offset - a->a_lineno_start) * 2; + bdelta = (a->a_offset - a->a_lineno_start) * sizeof(_Py_CODEUNIT); if (bdelta == 0) { return 1; } @@ -6714,7 +6787,7 @@ consts_dict_keys_inorder(PyObject *dict) return NULL; while (PyDict_Next(dict, &pos, &k, &v)) { i = PyLong_AS_LONG(v); - /* The keys of the dictionary can be tuples wrapping a contant. + /* The keys of the dictionary can be tuples wrapping a constant. * (see compiler_add_o and _PyCode_ConstantKey). In that case * the object we want is always second. */ if (PyTuple_CheckExact(k)) { @@ -6877,10 +6950,11 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts) /* For debugging purposes only */ #if 0 static void -dump_instr(const struct instr *i) +dump_instr(struct instr *i) { - const char *jrel = (is_relative_jump(instr)) ? "jrel " : ""; - const char *jabs = (is_jump(instr) && !is_relative_jump(instr))? "jabs " : ""; + const char *jrel = (is_relative_jump(i)) ? "jrel " : ""; + const char *jabs = (is_jump(i) && !is_relative_jump(i))? "jabs " : ""; + char arg[128]; *arg = '\0'; @@ -6915,7 +6989,14 @@ static int optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts); static int -ensure_exits_have_lineno(struct compiler *c); +trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts); + +/* Duplicates exit BBs, so that line numbers can be propagated to them */ +static int +duplicate_exits_without_lineno(struct compiler *c); + +static int +extend_block(basicblock *bb); static int insert_generator_prefix(struct compiler *c, basicblock *entryblock) { @@ -6952,6 +7033,37 @@ insert_generator_prefix(struct compiler *c, basicblock *entryblock) { return 0; } +/* Make sure that all returns have a line number, even if early passes + * have failed to propagate a correct line number. + * The resulting line number may not be correct according to PEP 626, + * but should be "good enough", and no worse than in older versions. */ +static void +guarantee_lineno_for_exits(struct assembler *a, int firstlineno) { + int lineno = firstlineno; + assert(lineno > 0); + for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { + if (b->b_iused == 0) { + continue; + } + struct instr *last = &b->b_instr[b->b_iused-1]; + if (last->i_lineno < 0) { + if (last->i_opcode == RETURN_VALUE) { + for (int i = 0; i < b->b_iused; i++) { + assert(b->b_instr[i].i_lineno < 0); + + b->b_instr[i].i_lineno = lineno; + } + } + } + else { + lineno = last->i_lineno; + } + } +} + +static void +propagate_line_numbers(struct assembler *a); + static PyCodeObject * assemble(struct compiler *c, int addNone) { @@ -6978,8 +7090,10 @@ assemble(struct compiler *c, int addNone) } } - if (ensure_exits_have_lineno(c)) { - return NULL; + for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { + if (extend_block(b)) { + return NULL; + } } nblocks = 0; @@ -7011,10 +7125,18 @@ assemble(struct compiler *c, int addNone) if (consts == NULL) { goto error; } + if (optimize_cfg(c, &a, consts)) { goto error; } - + if (duplicate_exits_without_lineno(c)) { + return NULL; + } + if (trim_unused_consts(c, &a, consts)) { + goto error; + } + propagate_line_numbers(&a); + guarantee_lineno_for_exits(&a, c->u->u_firstlineno); /* Can't modify the bytecode after computing jump offsets. */ assemble_jump_offsets(&a, c); @@ -7144,25 +7266,24 @@ fold_rotations(struct instr *inst, int n) } } - -static int -eliminate_jump_to_jump(basicblock *bb, int opcode) { - assert (bb->b_iused > 0); - struct instr *inst = &bb->b_instr[bb->b_iused-1]; - assert (is_jump(inst)); - assert (inst->i_target->b_iused > 0); - struct instr *target = &inst->i_target->b_instr[0]; - if (inst->i_target == target->i_target) { - /* Nothing to do */ - return 0; - } - int lineno = target->i_lineno; - if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) { - return -1; +// Attempt to eliminate jumps to jumps by updating inst to jump to +// target->i_target using the provided opcode. Return whether or not the +// optimization was successful. +static bool +jump_thread(struct instr *inst, struct instr *target, int opcode) +{ + assert(is_jump(inst)); + assert(is_jump(target)); + // bpo-45773: If inst->i_target == target->i_target, then nothing actually + // changes (and we fall into an infinite loop): + if (inst->i_lineno == target->i_lineno && + inst->i_target != target->i_target) + { + inst->i_target = target->i_target; + inst->i_opcode = opcode; + return true; } - assert (bb->b_iused >= 2); - bb->b_instr[bb->b_iused-2].i_opcode = NOP; - return 0; + return false; } /* Maximum size of basic block that should be copied in optimizer */ @@ -7279,25 +7400,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) where y+1 is the instruction following the second test. */ case JUMP_IF_FALSE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_FALSE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_FALSE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; case JUMP_IF_TRUE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_TRUE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_FALSE; inst->i_target = inst->i_target->b_next; --i; @@ -7305,27 +7422,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case JUMP_IF_TRUE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_TRUE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_TRUE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; case JUMP_IF_FALSE_OR_POP: - assert (inst->i_target->b_iused == 1); + case POP_JUMP_IF_FALSE: if (inst->i_lineno == target->i_lineno) { + // We don't need to bother checking for loops here, + // since a block's b_next cannot point to itself: + assert(inst->i_target != inst->i_target->b_next); inst->i_opcode = POP_JUMP_IF_TRUE; inst->i_target = inst->i_target->b_next; --i; @@ -7333,59 +7445,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case POP_JUMP_IF_FALSE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_FALSE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; - case POP_JUMP_IF_TRUE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_TRUE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; - case JUMP_ABSOLUTE: case JUMP_FORWARD: - assert (i == bb->b_iused-1); - switch(target->i_opcode) { - case JUMP_FORWARD: - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } - break; - + switch (target->i_opcode) { case JUMP_ABSOLUTE: - if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) { - goto error; - } - break; - default: - if (inst->i_target->b_exit && inst->i_target->b_iused <= MAX_COPY_SIZE) { - basicblock *to_copy = inst->i_target; - inst->i_opcode = NOP; - for (i = 0; i < to_copy->b_iused; i++) { - int index = compiler_next_instr(bb); - if (index < 0) { - return -1; - } - bb->b_instr[index] = to_copy->b_instr[i]; - } - bb->b_exit = 1; - } + case JUMP_FORWARD: + i -= jump_thread(inst, target, JUMP_ABSOLUTE); + } + break; + case FOR_ITER: + if (target->i_opcode == JUMP_FORWARD) { + i -= jump_thread(inst, target, FOR_ITER); } break; case ROT_N: @@ -7415,6 +7501,32 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) return -1; } +/* If this block ends with an unconditional jump to an exit block, + * then remove the jump and extend this block with the target. + */ +static int +extend_block(basicblock *bb) { + if (bb->b_iused == 0) { + return 0; + } + struct instr *last = &bb->b_instr[bb->b_iused-1]; + if (last->i_opcode != JUMP_ABSOLUTE && last->i_opcode != JUMP_FORWARD) { + return 0; + } + if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) { + basicblock *to_copy = last->i_target; + last->i_opcode = NOP; + for (int i = 0; i < to_copy->b_iused; i++) { + int index = compiler_next_instr(bb); + if (index < 0) { + return -1; + } + bb->b_instr[index] = to_copy->b_instr[i]; + } + bb->b_exit = 1; + } + return 0; +} static void clean_basic_block(basicblock *bb, int prev_lineno) { @@ -7565,7 +7677,7 @@ eliminate_empty_basic_blocks(basicblock *entry) { * but has no impact on the generated line number events. */ static void -propogate_line_numbers(struct assembler *a) { +propagate_line_numbers(struct assembler *a) { for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { if (b->b_iused == 0) { continue; @@ -7622,6 +7734,11 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) clean_basic_block(b, -1); assert(b->b_predecessors == 0); } + for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { + if (extend_block(b)) { + return -1; + } + } if (mark_reachable(a)) { return -1; } @@ -7666,7 +7783,33 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) if (maybe_empty_blocks) { eliminate_empty_basic_blocks(a->a_entry); } - propogate_line_numbers(a); + return 0; +} + +// Remove trailing unused constants. +static int +trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts) +{ + assert(PyList_CheckExact(consts)); + + // The first constant may be docstring; keep it always. + int max_const_index = 0; + for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { + for (int i = 0; i < b->b_iused; i++) { + if (b->b_instr[i].i_opcode == LOAD_CONST && + b->b_instr[i].i_oparg > max_const_index) { + max_const_index = b->b_instr[i].i_oparg; + } + } + } + if (max_const_index+1 < PyList_GET_SIZE(consts)) { + //fprintf(stderr, "removing trailing consts: max=%d, size=%d\n", + // max_const_index, (int)PyList_GET_SIZE(consts)); + if (PyList_SetSlice(consts, max_const_index+1, + PyList_GET_SIZE(consts), NULL) < 0) { + return 1; + } + } return 0; } @@ -7685,9 +7828,8 @@ is_exit_without_lineno(basicblock *b) { * copy the line number from the sole predecessor block. */ static int -ensure_exits_have_lineno(struct compiler *c) +duplicate_exits_without_lineno(struct compiler *c) { - basicblock *entry = NULL; /* Copy all exit blocks without line number that are targets of a jump. */ for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { @@ -7700,20 +7842,19 @@ ensure_exits_have_lineno(struct compiler *c) continue; } basicblock *target = b->b_instr[b->b_iused-1].i_target; - if (is_exit_without_lineno(target)) { + if (is_exit_without_lineno(target) && target->b_predecessors > 1) { basicblock *new_target = compiler_copy_block(c, target); if (new_target == NULL) { return -1; } new_target->b_instr[0].i_lineno = b->b_instr[b->b_iused-1].i_lineno; b->b_instr[b->b_iused-1].i_target = new_target; + target->b_predecessors--; + new_target->b_predecessors = 1; + new_target->b_next = target->b_next; + target->b_next = new_target; } } - entry = b; - } - assert(entry != NULL); - if (is_exit_without_lineno(entry)) { - entry->b_instr[0].i_lineno = c->u->u_firstlineno; } /* Eliminate empty blocks */ for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { diff --git a/Python/condvar.h b/Python/condvar.h index 8cba19b84612dc..e5df7ff132802f 100644 --- a/Python/condvar.h +++ b/Python/condvar.h @@ -99,7 +99,7 @@ PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us) http://birrell.org/andrew/papers/ImplementingCVs.pdf Generic emulations of the pthread_cond_* API using - earlier Win32 functions can be found on the Web. + earlier Win32 functions can be found on the web. The following read can be give background information to these issues, but the implementations are all broken in some way. http://www.cse.wustl.edu/~schmidt/win32-cv-1.html diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index e36d608c6dca44..a53373038ed859 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -13,7 +13,7 @@ #define FUNCNAME_PATTERN "%.20s_%.200s" #endif -const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL}; +const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, ".sl", NULL}; dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, const char *shortname, diff --git a/Python/errors.c b/Python/errors.c index f743d3089e20ba..bc1b55e440e8a0 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_initconfig.h" +#include "pycore_object.h" // _PyType_GetQualName #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_sysmodule.h" @@ -85,17 +86,29 @@ _PyErr_GetTopmostException(PyThreadState *tstate) } static PyObject* -_PyErr_CreateException(PyObject *exception, PyObject *value) +_PyErr_CreateException(PyObject *exception_type, PyObject *value) { + PyObject *exc; + if (value == NULL || value == Py_None) { - return _PyObject_CallNoArg(exception); + exc = _PyObject_CallNoArg(exception_type); } else if (PyTuple_Check(value)) { - return PyObject_Call(exception, value, NULL); + exc = PyObject_Call(exception_type, value, NULL); } else { - return PyObject_CallOneArg(exception, value); + exc = PyObject_CallOneArg(exception_type, value); + } + + if (exc != NULL && !PyExceptionInstance_Check(exc)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %s", + exception_type, Py_TYPE(exc)->tp_name); + Py_CLEAR(exc); } + + return exc; } void @@ -136,12 +149,16 @@ _PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value) value = fixed_value; } - /* Avoid reference cycles through the context chain. + /* Avoid creating new reference cycles through the + context chain, while taking care not to hang on + pre-existing ones. This is O(chain length) but context chains are usually very short. Sensitive readers may try to inline the call to PyException_GetContext. */ if (exc_value != value) { PyObject *o = exc_value, *context; + PyObject *slow_o = o; /* Floyd's cycle detection algo */ + int slow_update_toggle = 0; while ((context = PyException_GetContext(o))) { Py_DECREF(context); if (context == value) { @@ -149,6 +166,16 @@ _PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value) break; } o = context; + if (o == slow_o) { + /* pre-existing cycle - all exceptions on the + path were visited and checked. */ + break; + } + if (slow_update_toggle) { + slow_o = PyException_GetContext(slow_o); + Py_DECREF(slow_o); + } + slow_update_toggle = !slow_update_toggle; } PyException_SetContext(value, exc_value); } @@ -1297,46 +1324,45 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, } assert(PyExceptionClass_Check(exc_type)); - const char *className = PyExceptionClass_Name(exc_type); - if (className != NULL) { - const char *dot = strrchr(className, '.'); - if (dot != NULL) { - className = dot+1; - } - } - PyObject *moduleName = _PyObject_GetAttrId(exc_type, &PyId___module__); - if (moduleName == NULL || !PyUnicode_Check(moduleName)) { - Py_XDECREF(moduleName); + PyObject *modulename = _PyObject_GetAttrId(exc_type, &PyId___module__); + if (modulename == NULL || !PyUnicode_Check(modulename)) { + Py_XDECREF(modulename); _PyErr_Clear(tstate); if (PyFile_WriteString("", file) < 0) { return -1; } } else { - if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) { - if (PyFile_WriteObject(moduleName, file, Py_PRINT_RAW) < 0) { - Py_DECREF(moduleName); + if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins)) { + if (PyFile_WriteObject(modulename, file, Py_PRINT_RAW) < 0) { + Py_DECREF(modulename); return -1; } - Py_DECREF(moduleName); + Py_DECREF(modulename); if (PyFile_WriteString(".", file) < 0) { return -1; } } else { - Py_DECREF(moduleName); + Py_DECREF(modulename); } } - if (className == NULL) { + + PyObject *qualname = _PyType_GetQualName((PyTypeObject *)exc_type); + if (qualname == NULL || !PyUnicode_Check(qualname)) { + Py_XDECREF(qualname); + _PyErr_Clear(tstate); if (PyFile_WriteString("", file) < 0) { return -1; } } else { - if (PyFile_WriteString(className, file) < 0) { + if (PyFile_WriteObject(qualname, file, Py_PRINT_RAW) < 0) { + Py_DECREF(qualname); return -1; } + Py_DECREF(qualname); } if (exc_value && exc_value != Py_None) { @@ -1698,7 +1724,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) functionality in tb_displayline() in traceback.c. */ static PyObject * -err_programtext(PyThreadState *tstate, FILE *fp, int lineno) +err_programtext(PyThreadState *tstate, FILE *fp, int lineno, const char* encoding) { int i; char linebuf[1000]; @@ -1726,7 +1752,11 @@ err_programtext(PyThreadState *tstate, FILE *fp, int lineno) fclose(fp); if (i == lineno) { PyObject *res; - res = PyUnicode_FromString(linebuf); + if (encoding != NULL) { + res = PyUnicode_Decode(linebuf, strlen(linebuf), encoding, "replace"); + } else { + res = PyUnicode_FromString(linebuf); + } if (res == NULL) _PyErr_Clear(tstate); return res; @@ -1752,7 +1782,7 @@ PyErr_ProgramText(const char *filename, int lineno) } PyObject * -PyErr_ProgramTextObject(PyObject *filename, int lineno) +_PyErr_ProgramDecodedTextObject(PyObject *filename, int lineno, const char* encoding) { if (filename == NULL || lineno <= 0) { return NULL; @@ -1764,7 +1794,13 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno) _PyErr_Clear(tstate); return NULL; } - return err_programtext(tstate, fp, lineno); + return err_programtext(tstate, fp, lineno, encoding); +} + +PyObject * +PyErr_ProgramTextObject(PyObject *filename, int lineno) +{ + return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL); } #ifdef __cplusplus diff --git a/Python/fileutils.c b/Python/fileutils.c index a8fab00629da41..c3144ee40782e8 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -67,9 +67,11 @@ PyObject * _Py_device_encoding(int fd) { int valid; + Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH valid = isatty(fd); _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS if (!valid) Py_RETURN_NONE; @@ -218,7 +220,7 @@ check_force_ascii(void) ch = (unsigned char)0xA7; res = _Py_mbstowcs(&wch, (char*)&ch, 1); if (res != DECODE_ERROR && wch == L'\xA7') { - /* On HP-UX withe C locale or the POSIX locale, + /* On HP-UX with C locale or the POSIX locale, nl_langinfo(CODESET) announces "roman8", whereas mbstowcs() uses Latin1 encoding in practice. Force ASCII in this case. @@ -1374,10 +1376,11 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) return 0; } -#ifdef __linux__ +#ifdef O_PATH if (errno == EBADF) { - // On Linux, ioctl(FIOCLEX) will fail with EBADF for O_PATH file descriptors - // Fall through to the fcntl() path + // bpo-44849: On Linux and FreeBSD, ioctl(FIOCLEX) fails with EBADF + // on O_PATH file descriptors. Fall through to the fcntl() + // implementation. } else #endif @@ -1775,12 +1778,22 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held) _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS - if (count > 32767 && isatty(fd)) { + if (count > 32767) { /* Issue #11395: the Windows console returns an error (12: not enough space error) on writing into stdout if stdout mode is binary and the length is greater than 66,000 bytes (or less, depending on heap usage). */ - count = 32767; + if (gil_held) { + Py_BEGIN_ALLOW_THREADS + if (isatty(fd)) { + count = 32767; + } + Py_END_ALLOW_THREADS + } else { + if (isatty(fd)) { + count = 32767; + } + } } #endif if (count > _PY_WRITE_MAX) { diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 5ccf9d303e34ec..7b5a7bd04eb3aa 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -773,8 +773,14 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format, /* sign is not allowed on strings */ if (format->sign != '\0') { - PyErr_SetString(PyExc_ValueError, - "Sign not allowed in string format specifier"); + if (format->sign == ' ') { + PyErr_SetString(PyExc_ValueError, + "Space not allowed in string format specifier"); + } + else { + PyErr_SetString(PyExc_ValueError, + "Sign not allowed in string format specifier"); + } goto done; } diff --git a/Python/getargs.c b/Python/getargs.c index b85b575a147fe6..d5e083509efefc 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2532,15 +2532,12 @@ skipitem(const char **p_format, va_list *p_va, int flags) } if (*format == '#') { if (p_va != NULL) { - if (flags & FLAG_SIZE_T) - (void) va_arg(*p_va, Py_ssize_t *); - else { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { - return NULL; - } - (void) va_arg(*p_va, int *); + if (!(flags & FLAG_SIZE_T)) { + PyErr_SetString(PyExc_SystemError, + "PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); + return NULL; } + (void) va_arg(*p_va, Py_ssize_t *); } format++; } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index 7fdeb314d5261b..88d1d0536253ac 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static const char cprt[] = "\ -Copyright (c) 2001-2021 Python Software Foundation.\n\ +Copyright (c) 2001-2022 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ diff --git a/Python/import.c b/Python/import.c index c4878c628bedcf..acfe96963ca34e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -255,6 +255,9 @@ _PyImport_Fini2(void) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + // Reset PyImport_Inittab + PyImport_Inittab = _PyImport_Inittab; + /* Free memory allocated by PyImport_ExtendInittab() */ PyMem_RawFree(inittab_copy); inittab_copy = NULL; @@ -438,7 +441,9 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, return -1; } - if (_Py_IsMainInterpreter(tstate->interp)) { + // bpo-44050: Extensions and def->m_base.m_copy can be updated + // when the extension module doesn't support sub-interpreters. + if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { if (def->m_size == -1) { if (def->m_base.m_copy) { /* Somebody already imported the module, @@ -553,6 +558,23 @@ import_find_extension(PyThreadState *tstate, PyObject *name, return mod; } +PyObject * +_PyImport_FindExtensionObject(PyObject *name, PyObject *filename) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *mod = import_find_extension(tstate, name, filename); + if (mod) { + PyObject *ref = PyWeakref_NewRef(mod, NULL); + Py_DECREF(mod); + if (ref == NULL) { + return NULL; + } + mod = PyWeakref_GetObject(ref); + Py_DECREF(ref); + } + return mod; /* borrowed reference */ +} + /* Get the module object corresponding to a module name. First check the modules dictionary if there's one there, @@ -2173,7 +2195,7 @@ _PyImport_BootstrapImp(PyThreadState *tstate) // Mock a ModuleSpec object just good enough for PyModule_FromDefAndSpec(): // an object with just a name attribute. // - // _imp.__spec__ is overriden by importlib._bootstrap._instal() anyway. + // _imp.__spec__ is overridden by importlib._bootstrap._instal() anyway. PyObject *attrs = Py_BuildValue("{sO}", "name", name); if (attrs == NULL) { goto error; diff --git a/Python/importdl.c b/Python/importdl.c index 1847eba74aef45..6d2554741f9822 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -42,6 +42,9 @@ get_encoded_name(PyObject *name, const char **hook_prefix) { /* Get the short name (substring after last dot) */ name_len = PyUnicode_GetLength(name); + if (name_len < 0) { + return NULL; + } lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1); if (lastdot < -1) { return NULL; @@ -121,7 +124,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) if (PySys_Audit("import", "OOOOO", name_unicode, path, Py_None, Py_None, Py_None) < 0) { - return NULL; + goto error; } #ifdef MS_WINDOWS @@ -204,7 +207,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) /* don't allow legacy init for non-ASCII module names */ PyErr_Format( PyExc_SystemError, - "initialization of * did not return PyModuleDef", + "initialization of %s did not return PyModuleDef", name_buf); goto error; } diff --git a/Python/importlib.h b/Python/importlib.h index 8156973bdeaaf7..ab3e69b22b6625 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -182,641 +182,646 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 218,7,97,99,113,117,105,114,101,114,31,0,0,0,218,7, 114,101,108,101,97,115,101,169,2,114,33,0,0,0,114,40, 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,114,43,0,0,0,100,0,0,0,115,44,0,0,0, + 0,0,114,43,0,0,0,100,0,0,0,115,42,0,0,0, 8,6,8,1,2,1,2,1,8,1,20,1,6,1,14,1, - 2,1,12,252,2,4,10,9,8,248,12,1,12,1,14,1, - 2,128,28,248,10,10,10,1,2,244,8,14,122,19,95,77, - 111,100,117,108,101,76,111,99,107,46,97,99,113,117,105,114, - 101,99,1,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,8,0,0,0,67,0,0,0,115,144,0,0,0,116, - 0,160,1,161,0,125,1,124,0,106,2,143,55,1,0,124, - 0,106,3,124,1,107,3,114,17,116,4,100,1,131,1,130, - 1,124,0,106,5,100,2,107,4,115,24,74,0,130,1,124, - 0,4,0,106,5,100,3,56,0,2,0,95,5,124,0,106, - 5,100,2,107,2,114,54,100,0,124,0,95,3,124,0,106, - 6,114,54,124,0,4,0,106,6,100,3,56,0,2,0,95, - 6,124,0,106,7,160,8,161,0,1,0,87,0,100,0,4, - 0,4,0,131,3,1,0,100,0,83,0,49,0,115,65,119, - 1,1,0,1,0,1,0,89,0,1,0,100,0,83,0,41, - 4,78,250,31,99,97,110,110,111,116,32,114,101,108,101,97, - 115,101,32,117,110,45,97,99,113,117,105,114,101,100,32,108, - 111,99,107,114,25,0,0,0,114,42,0,0,0,41,9,114, - 26,0,0,0,114,35,0,0,0,114,27,0,0,0,114,29, - 0,0,0,218,12,82,117,110,116,105,109,101,69,114,114,111, - 114,114,30,0,0,0,114,31,0,0,0,114,28,0,0,0, - 114,44,0,0,0,114,45,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,114,44,0,0,0,125,0, - 0,0,115,26,0,0,0,8,1,8,1,10,1,8,1,14, - 1,14,1,10,1,6,1,6,1,14,1,10,1,2,128,34, - 247,122,19,95,77,111,100,117,108,101,76,111,99,107,46,114, - 101,108,101,97,115,101,99,1,0,0,0,0,0,0,0,0, - 0,0,0,1,0,0,0,5,0,0,0,67,0,0,0,243, - 18,0,0,0,100,1,160,0,124,0,106,1,116,2,124,0, - 131,1,161,2,83,0,41,2,78,122,23,95,77,111,100,117, - 108,101,76,111,99,107,40,123,33,114,125,41,32,97,116,32, - 123,125,169,3,218,6,102,111,114,109,97,116,114,20,0,0, - 0,218,2,105,100,169,1,114,33,0,0,0,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,218,8,95,95,114, - 101,112,114,95,95,138,0,0,0,243,2,0,0,0,18,1, - 122,20,95,77,111,100,117,108,101,76,111,99,107,46,95,95, - 114,101,112,114,95,95,78,41,9,114,9,0,0,0,114,8, - 0,0,0,114,1,0,0,0,114,10,0,0,0,114,34,0, - 0,0,114,41,0,0,0,114,43,0,0,0,114,44,0,0, - 0,114,53,0,0,0,114,5,0,0,0,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,114,23,0,0,0,65, - 0,0,0,115,14,0,0,0,8,0,4,1,8,5,8,8, - 8,21,8,25,12,13,114,23,0,0,0,99,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 64,0,0,0,115,48,0,0,0,101,0,90,1,100,0,90, - 2,100,1,90,3,100,2,100,3,132,0,90,4,100,4,100, - 5,132,0,90,5,100,6,100,7,132,0,90,6,100,8,100, - 9,132,0,90,7,100,10,83,0,41,11,218,16,95,68,117, - 109,109,121,77,111,100,117,108,101,76,111,99,107,122,86,65, - 32,115,105,109,112,108,101,32,95,77,111,100,117,108,101,76, - 111,99,107,32,101,113,117,105,118,97,108,101,110,116,32,102, - 111,114,32,80,121,116,104,111,110,32,98,117,105,108,100,115, - 32,119,105,116,104,111,117,116,10,32,32,32,32,109,117,108, - 116,105,45,116,104,114,101,97,100,105,110,103,32,115,117,112, - 112,111,114,116,46,99,2,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,2,0,0,0,67,0,0,0,115,16, - 0,0,0,124,1,124,0,95,0,100,1,124,0,95,1,100, - 0,83,0,114,24,0,0,0,41,2,114,20,0,0,0,114, - 30,0,0,0,114,32,0,0,0,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,114,34,0,0,0,146,0,0, - 0,243,4,0,0,0,6,1,10,1,122,25,95,68,117,109, - 109,121,77,111,100,117,108,101,76,111,99,107,46,95,95,105, - 110,105,116,95,95,99,1,0,0,0,0,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,18, - 0,0,0,124,0,4,0,106,0,100,1,55,0,2,0,95, - 0,100,2,83,0,41,3,78,114,42,0,0,0,84,41,1, - 114,30,0,0,0,114,52,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,114,43,0,0,0,150,0, - 0,0,115,4,0,0,0,14,1,4,1,122,24,95,68,117, - 109,109,121,77,111,100,117,108,101,76,111,99,107,46,97,99, - 113,117,105,114,101,99,1,0,0,0,0,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,36, - 0,0,0,124,0,106,0,100,1,107,2,114,9,116,1,100, - 2,131,1,130,1,124,0,4,0,106,0,100,3,56,0,2, - 0,95,0,100,0,83,0,41,4,78,114,25,0,0,0,114, - 46,0,0,0,114,42,0,0,0,41,2,114,30,0,0,0, - 114,47,0,0,0,114,52,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,114,44,0,0,0,154,0, - 0,0,115,6,0,0,0,10,1,8,1,18,1,122,24,95, - 68,117,109,109,121,77,111,100,117,108,101,76,111,99,107,46, - 114,101,108,101,97,115,101,99,1,0,0,0,0,0,0,0, - 0,0,0,0,1,0,0,0,5,0,0,0,67,0,0,0, - 114,48,0,0,0,41,2,78,122,28,95,68,117,109,109,121, + 2,1,14,252,10,13,8,248,12,1,12,1,14,1,2,128, + 28,248,10,10,10,1,2,244,8,14,122,19,95,77,111,100, + 117,108,101,76,111,99,107,46,97,99,113,117,105,114,101,99, + 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 8,0,0,0,67,0,0,0,115,176,0,0,0,116,0,160, + 1,161,0,125,1,124,0,106,2,143,71,1,0,124,0,106, + 3,124,1,107,3,114,17,116,4,100,1,131,1,130,1,124, + 0,106,5,100,2,107,4,115,24,74,0,130,1,124,0,4, + 0,106,5,100,3,56,0,2,0,95,5,124,0,106,5,100, + 2,107,2,114,62,100,0,124,0,95,3,124,0,106,6,114, + 70,124,0,4,0,106,6,100,3,56,0,2,0,95,6,124, + 0,106,7,160,8,161,0,1,0,87,0,100,0,4,0,4, + 0,131,3,1,0,100,0,83,0,87,0,100,0,4,0,4, + 0,131,3,1,0,100,0,83,0,87,0,100,0,4,0,4, + 0,131,3,1,0,100,0,83,0,49,0,115,81,119,1,1, + 0,1,0,1,0,89,0,1,0,100,0,83,0,41,4,78, + 250,31,99,97,110,110,111,116,32,114,101,108,101,97,115,101, + 32,117,110,45,97,99,113,117,105,114,101,100,32,108,111,99, + 107,114,25,0,0,0,114,42,0,0,0,41,9,114,26,0, + 0,0,114,35,0,0,0,114,27,0,0,0,114,29,0,0, + 0,218,12,82,117,110,116,105,109,101,69,114,114,111,114,114, + 30,0,0,0,114,31,0,0,0,114,28,0,0,0,114,44, + 0,0,0,114,45,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,44,0,0,0,125,0,0,0, + 115,32,0,0,0,8,1,8,1,10,1,8,1,14,1,14, + 1,10,1,6,1,6,1,14,1,12,1,14,247,2,5,14, + 251,2,7,34,249,122,19,95,77,111,100,117,108,101,76,111, + 99,107,46,114,101,108,101,97,115,101,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,67, + 0,0,0,243,18,0,0,0,100,1,160,0,124,0,106,1, + 116,2,124,0,131,1,161,2,83,0,41,2,78,122,23,95, 77,111,100,117,108,101,76,111,99,107,40,123,33,114,125,41, - 32,97,116,32,123,125,114,49,0,0,0,114,52,0,0,0, - 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,114, - 53,0,0,0,159,0,0,0,114,54,0,0,0,122,25,95, - 68,117,109,109,121,77,111,100,117,108,101,76,111,99,107,46, - 95,95,114,101,112,114,95,95,78,41,8,114,9,0,0,0, - 114,8,0,0,0,114,1,0,0,0,114,10,0,0,0,114, - 34,0,0,0,114,43,0,0,0,114,44,0,0,0,114,53, - 0,0,0,114,5,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,114,55,0,0,0,142,0,0,0, - 115,12,0,0,0,8,0,4,1,8,3,8,4,8,4,12, - 5,114,55,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, - 36,0,0,0,101,0,90,1,100,0,90,2,100,1,100,2, - 132,0,90,3,100,3,100,4,132,0,90,4,100,5,100,6, - 132,0,90,5,100,7,83,0,41,8,218,18,95,77,111,100, - 117,108,101,76,111,99,107,77,97,110,97,103,101,114,99,2, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2, - 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, - 95,0,100,0,124,0,95,1,100,0,83,0,114,0,0,0, - 0,41,2,218,5,95,110,97,109,101,218,5,95,108,111,99, - 107,114,32,0,0,0,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,114,34,0,0,0,165,0,0,0,114,56, - 0,0,0,122,27,95,77,111,100,117,108,101,76,111,99,107, - 77,97,110,97,103,101,114,46,95,95,105,110,105,116,95,95, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,2,0,0,0,67,0,0,0,115,26,0,0,0,116,0, - 124,0,106,1,131,1,124,0,95,2,124,0,106,2,160,3, - 161,0,1,0,100,0,83,0,114,0,0,0,0,41,4,218, - 16,95,103,101,116,95,109,111,100,117,108,101,95,108,111,99, - 107,114,58,0,0,0,114,59,0,0,0,114,43,0,0,0, - 114,52,0,0,0,114,5,0,0,0,114,5,0,0,0,114, - 6,0,0,0,218,9,95,95,101,110,116,101,114,95,95,169, - 0,0,0,115,4,0,0,0,12,1,14,1,122,28,95,77, - 111,100,117,108,101,76,111,99,107,77,97,110,97,103,101,114, - 46,95,95,101,110,116,101,114,95,95,99,1,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,79, - 0,0,0,115,14,0,0,0,124,0,106,0,160,1,161,0, - 1,0,100,0,83,0,114,0,0,0,0,41,2,114,59,0, - 0,0,114,44,0,0,0,41,3,114,33,0,0,0,218,4, - 97,114,103,115,90,6,107,119,97,114,103,115,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,218,8,95,95,101, - 120,105,116,95,95,173,0,0,0,115,2,0,0,0,14,1, - 122,27,95,77,111,100,117,108,101,76,111,99,107,77,97,110, - 97,103,101,114,46,95,95,101,120,105,116,95,95,78,41,6, - 114,9,0,0,0,114,8,0,0,0,114,1,0,0,0,114, - 34,0,0,0,114,61,0,0,0,114,63,0,0,0,114,5, - 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,114,57,0,0,0,163,0,0,0,115,8,0,0,0, - 8,0,8,2,8,4,12,4,114,57,0,0,0,99,1,0, - 0,0,0,0,0,0,0,0,0,0,3,0,0,0,8,0, - 0,0,67,0,0,0,115,132,0,0,0,116,0,160,1,161, - 0,1,0,122,55,122,7,116,2,124,0,25,0,131,0,125, - 1,87,0,110,9,4,0,116,3,121,65,1,0,1,0,1, - 0,100,1,125,1,89,0,124,1,100,1,117,0,114,53,116, - 4,100,1,117,0,114,35,116,5,124,0,131,1,125,1,110, - 4,116,6,124,0,131,1,125,1,124,0,102,1,100,2,100, - 3,132,1,125,2,116,7,160,8,124,1,124,2,161,2,116, - 2,124,0,60,0,87,0,116,0,160,9,161,0,1,0,124, - 1,83,0,116,0,160,9,161,0,1,0,119,0,119,0,41, - 4,122,139,71,101,116,32,111,114,32,99,114,101,97,116,101, - 32,116,104,101,32,109,111,100,117,108,101,32,108,111,99,107, - 32,102,111,114,32,97,32,103,105,118,101,110,32,109,111,100, - 117,108,101,32,110,97,109,101,46,10,10,32,32,32,32,65, - 99,113,117,105,114,101,47,114,101,108,101,97,115,101,32,105, - 110,116,101,114,110,97,108,108,121,32,116,104,101,32,103,108, - 111,98,97,108,32,105,109,112,111,114,116,32,108,111,99,107, - 32,116,111,32,112,114,111,116,101,99,116,10,32,32,32,32, - 95,109,111,100,117,108,101,95,108,111,99,107,115,46,78,99, - 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 8,0,0,0,83,0,0,0,115,54,0,0,0,116,0,160, - 1,161,0,1,0,122,17,116,2,160,3,124,1,161,1,124, - 0,117,0,114,15,116,2,124,1,61,0,87,0,116,0,160, - 4,161,0,1,0,100,0,83,0,116,0,160,4,161,0,1, - 0,119,0,114,0,0,0,0,41,5,218,4,95,105,109,112, - 218,12,97,99,113,117,105,114,101,95,108,111,99,107,218,13, - 95,109,111,100,117,108,101,95,108,111,99,107,115,114,38,0, - 0,0,218,12,114,101,108,101,97,115,101,95,108,111,99,107, - 41,2,218,3,114,101,102,114,20,0,0,0,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,218,2,99,98,198, - 0,0,0,115,12,0,0,0,8,1,2,1,14,4,6,1, - 2,128,22,2,122,28,95,103,101,116,95,109,111,100,117,108, - 101,95,108,111,99,107,46,60,108,111,99,97,108,115,62,46, - 99,98,41,10,114,64,0,0,0,114,65,0,0,0,114,66, - 0,0,0,218,8,75,101,121,69,114,114,111,114,114,26,0, - 0,0,114,55,0,0,0,114,23,0,0,0,218,8,95,119, - 101,97,107,114,101,102,114,68,0,0,0,114,67,0,0,0, - 41,3,114,20,0,0,0,114,27,0,0,0,114,69,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, - 114,60,0,0,0,179,0,0,0,115,34,0,0,0,8,6, - 2,1,2,1,14,1,12,1,6,1,8,2,8,1,10,1, - 8,2,12,2,16,11,2,128,8,2,4,2,10,254,2,234, - 114,60,0,0,0,99,1,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,8,0,0,0,67,0,0,0,115,54, - 0,0,0,116,0,124,0,131,1,125,1,122,6,124,1,160, - 1,161,0,1,0,87,0,110,9,4,0,116,2,121,26,1, - 0,1,0,1,0,89,0,100,1,83,0,124,1,160,3,161, - 0,1,0,100,1,83,0,119,0,41,2,122,189,65,99,113, - 117,105,114,101,115,32,116,104,101,110,32,114,101,108,101,97, - 115,101,115,32,116,104,101,32,109,111,100,117,108,101,32,108, - 111,99,107,32,102,111,114,32,97,32,103,105,118,101,110,32, - 109,111,100,117,108,101,32,110,97,109,101,46,10,10,32,32, - 32,32,84,104,105,115,32,105,115,32,117,115,101,100,32,116, - 111,32,101,110,115,117,114,101,32,97,32,109,111,100,117,108, - 101,32,105,115,32,99,111,109,112,108,101,116,101,108,121,32, - 105,110,105,116,105,97,108,105,122,101,100,44,32,105,110,32, - 116,104,101,10,32,32,32,32,101,118,101,110,116,32,105,116, - 32,105,115,32,98,101,105,110,103,32,105,109,112,111,114,116, - 101,100,32,98,121,32,97,110,111,116,104,101,114,32,116,104, - 114,101,97,100,46,10,32,32,32,32,78,41,4,114,60,0, - 0,0,114,43,0,0,0,114,22,0,0,0,114,44,0,0, - 0,41,2,114,20,0,0,0,114,27,0,0,0,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,218,19,95,108, - 111,99,107,95,117,110,108,111,99,107,95,109,111,100,117,108, - 101,216,0,0,0,115,14,0,0,0,8,6,2,1,12,1, - 12,1,6,3,12,2,2,251,114,72,0,0,0,99,1,0, - 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, - 0,0,79,0,0,0,115,14,0,0,0,124,0,124,1,105, - 0,124,2,164,1,142,1,83,0,41,2,97,46,1,0,0, - 114,101,109,111,118,101,95,105,109,112,111,114,116,108,105,98, - 95,102,114,97,109,101,115,32,105,110,32,105,109,112,111,114, - 116,46,99,32,119,105,108,108,32,97,108,119,97,121,115,32, - 114,101,109,111,118,101,32,115,101,113,117,101,110,99,101,115, - 10,32,32,32,32,111,102,32,105,109,112,111,114,116,108,105, - 98,32,102,114,97,109,101,115,32,116,104,97,116,32,101,110, - 100,32,119,105,116,104,32,97,32,99,97,108,108,32,116,111, - 32,116,104,105,115,32,102,117,110,99,116,105,111,110,10,10, - 32,32,32,32,85,115,101,32,105,116,32,105,110,115,116,101, - 97,100,32,111,102,32,97,32,110,111,114,109,97,108,32,99, - 97,108,108,32,105,110,32,112,108,97,99,101,115,32,119,104, - 101,114,101,32,105,110,99,108,117,100,105,110,103,32,116,104, - 101,32,105,109,112,111,114,116,108,105,98,10,32,32,32,32, - 102,114,97,109,101,115,32,105,110,116,114,111,100,117,99,101, - 115,32,117,110,119,97,110,116,101,100,32,110,111,105,115,101, - 32,105,110,116,111,32,116,104,101,32,116,114,97,99,101,98, - 97,99,107,32,40,101,46,103,46,32,119,104,101,110,32,101, - 120,101,99,117,116,105,110,103,10,32,32,32,32,109,111,100, - 117,108,101,32,99,111,100,101,41,10,32,32,32,32,78,114, - 5,0,0,0,41,3,218,1,102,114,62,0,0,0,90,4, - 107,119,100,115,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,25,95,99,97,108,108,95,119,105,116,104,95, - 102,114,97,109,101,115,95,114,101,109,111,118,101,100,233,0, - 0,0,115,2,0,0,0,14,8,114,74,0,0,0,114,42, - 0,0,0,41,1,218,9,118,101,114,98,111,115,105,116,121, - 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, - 0,4,0,0,0,71,0,0,0,115,58,0,0,0,116,0, - 106,1,106,2,124,1,107,5,114,27,124,0,160,3,100,1, - 161,1,115,15,100,2,124,0,23,0,125,0,116,4,124,0, - 106,5,124,2,142,0,116,0,106,6,100,3,141,2,1,0, - 100,4,83,0,100,4,83,0,41,5,122,61,80,114,105,110, - 116,32,116,104,101,32,109,101,115,115,97,103,101,32,116,111, - 32,115,116,100,101,114,114,32,105,102,32,45,118,47,80,89, - 84,72,79,78,86,69,82,66,79,83,69,32,105,115,32,116, - 117,114,110,101,100,32,111,110,46,41,2,250,1,35,122,7, - 105,109,112,111,114,116,32,122,2,35,32,41,1,90,4,102, - 105,108,101,78,41,7,114,18,0,0,0,218,5,102,108,97, - 103,115,218,7,118,101,114,98,111,115,101,218,10,115,116,97, - 114,116,115,119,105,116,104,218,5,112,114,105,110,116,114,50, - 0,0,0,218,6,115,116,100,101,114,114,41,3,218,7,109, - 101,115,115,97,103,101,114,75,0,0,0,114,62,0,0,0, + 32,97,116,32,123,125,169,3,218,6,102,111,114,109,97,116, + 114,20,0,0,0,218,2,105,100,169,1,114,33,0,0,0, 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,218, - 16,95,118,101,114,98,111,115,101,95,109,101,115,115,97,103, - 101,244,0,0,0,115,10,0,0,0,12,2,10,1,8,1, - 24,1,4,253,114,83,0,0,0,99,1,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, - 0,0,243,26,0,0,0,135,0,102,1,100,1,100,2,132, - 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, - 0,41,4,122,49,68,101,99,111,114,97,116,111,114,32,116, - 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, - 101,100,32,109,111,100,117,108,101,32,105,115,32,98,117,105, - 108,116,45,105,110,46,99,2,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, - 38,0,0,0,124,1,116,0,106,1,118,1,114,14,116,2, - 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, - 136,0,124,0,124,1,131,2,83,0,41,3,78,250,29,123, - 33,114,125,32,105,115,32,110,111,116,32,97,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,114,19,0,0, - 0,41,4,114,18,0,0,0,218,20,98,117,105,108,116,105, - 110,95,109,111,100,117,108,101,95,110,97,109,101,115,218,11, - 73,109,112,111,114,116,69,114,114,111,114,114,50,0,0,0, - 169,2,114,33,0,0,0,218,8,102,117,108,108,110,97,109, - 101,169,1,218,3,102,120,110,114,5,0,0,0,114,6,0, - 0,0,218,25,95,114,101,113,117,105,114,101,115,95,98,117, - 105,108,116,105,110,95,119,114,97,112,112,101,114,254,0,0, - 0,243,10,0,0,0,10,1,10,1,2,1,6,255,10,2, - 122,52,95,114,101,113,117,105,114,101,115,95,98,117,105,108, - 116,105,110,46,60,108,111,99,97,108,115,62,46,95,114,101, - 113,117,105,114,101,115,95,98,117,105,108,116,105,110,95,119, - 114,97,112,112,101,114,78,169,1,114,17,0,0,0,41,2, - 114,91,0,0,0,114,92,0,0,0,114,5,0,0,0,114, - 90,0,0,0,114,6,0,0,0,218,17,95,114,101,113,117, - 105,114,101,115,95,98,117,105,108,116,105,110,252,0,0,0, - 243,6,0,0,0,12,2,10,5,4,1,114,95,0,0,0, - 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,3,0,0,0,3,0,0,0,114,84,0,0,0,41,4, - 122,47,68,101,99,111,114,97,116,111,114,32,116,111,32,118, - 101,114,105,102,121,32,116,104,101,32,110,97,109,101,100,32, - 109,111,100,117,108,101,32,105,115,32,102,114,111,122,101,110, - 46,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,4,0,0,0,19,0,0,0,115,38,0,0,0,116, - 0,160,1,124,1,161,1,115,14,116,2,100,1,160,3,124, - 1,161,1,124,1,100,2,141,2,130,1,136,0,124,0,124, - 1,131,2,83,0,169,3,78,122,27,123,33,114,125,32,105, - 115,32,110,111,116,32,97,32,102,114,111,122,101,110,32,109, - 111,100,117,108,101,114,19,0,0,0,41,4,114,64,0,0, - 0,218,9,105,115,95,102,114,111,122,101,110,114,87,0,0, - 0,114,50,0,0,0,114,88,0,0,0,114,90,0,0,0, - 114,5,0,0,0,114,6,0,0,0,218,24,95,114,101,113, - 117,105,114,101,115,95,102,114,111,122,101,110,95,119,114,97, - 112,112,101,114,9,1,0,0,114,93,0,0,0,122,50,95, - 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,46, - 60,108,111,99,97,108,115,62,46,95,114,101,113,117,105,114, - 101,115,95,102,114,111,122,101,110,95,119,114,97,112,112,101, - 114,78,114,94,0,0,0,41,2,114,91,0,0,0,114,99, - 0,0,0,114,5,0,0,0,114,90,0,0,0,114,6,0, - 0,0,218,16,95,114,101,113,117,105,114,101,115,95,102,114, - 111,122,101,110,7,1,0,0,114,96,0,0,0,114,100,0, - 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,5, - 0,0,0,4,0,0,0,67,0,0,0,115,74,0,0,0, - 100,1,125,2,116,0,160,1,124,2,116,2,161,2,1,0, - 116,3,124,1,124,0,131,2,125,3,124,1,116,4,106,5, - 118,0,114,33,116,4,106,5,124,1,25,0,125,4,116,6, - 124,3,124,4,131,2,1,0,116,4,106,5,124,1,25,0, - 83,0,116,7,124,3,131,1,83,0,41,3,122,130,76,111, - 97,100,32,116,104,101,32,115,112,101,99,105,102,105,101,100, - 32,109,111,100,117,108,101,32,105,110,116,111,32,115,121,115, - 46,109,111,100,117,108,101,115,32,97,110,100,32,114,101,116, - 117,114,110,32,105,116,46,10,10,32,32,32,32,84,104,105, - 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,46,32,32,85,115,101,32,108,111,97, - 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 122,103,116,104,101,32,108,111,97,100,95,109,111,100,117,108, - 101,40,41,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,32,97,110,100,32,115,108,97, - 116,101,100,32,102,111,114,32,114,101,109,111,118,97,108,32, - 105,110,32,80,121,116,104,111,110,32,51,46,49,50,59,32, - 117,115,101,32,101,120,101,99,95,109,111,100,117,108,101,40, - 41,32,105,110,115,116,101,97,100,78,41,8,218,9,95,119, - 97,114,110,105,110,103,115,218,4,119,97,114,110,218,18,68, - 101,112,114,101,99,97,116,105,111,110,87,97,114,110,105,110, - 103,218,16,115,112,101,99,95,102,114,111,109,95,108,111,97, - 100,101,114,114,18,0,0,0,218,7,109,111,100,117,108,101, - 115,218,5,95,101,120,101,99,218,5,95,108,111,97,100,41, - 5,114,33,0,0,0,114,89,0,0,0,218,3,109,115,103, - 218,4,115,112,101,99,218,6,109,111,100,117,108,101,114,5, - 0,0,0,114,5,0,0,0,114,6,0,0,0,218,17,95, - 108,111,97,100,95,109,111,100,117,108,101,95,115,104,105,109, - 19,1,0,0,115,16,0,0,0,4,6,12,2,10,1,10, - 1,10,1,10,1,10,1,8,2,114,111,0,0,0,99,1, - 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,8, - 0,0,0,67,0,0,0,115,184,0,0,0,116,0,124,0, - 100,1,100,2,131,3,125,1,116,0,124,0,100,3,100,2, - 131,3,4,0,125,2,114,18,116,1,124,2,131,1,83,0, - 116,2,124,1,100,4,131,2,114,37,122,6,124,1,160,3, - 124,0,161,1,87,0,83,0,4,0,116,4,121,91,1,0, - 1,0,1,0,89,0,122,5,124,0,106,5,125,3,87,0, - 110,9,4,0,116,6,121,90,1,0,1,0,1,0,100,5, - 125,3,89,0,122,5,124,0,106,7,125,4,87,0,110,25, - 4,0,116,6,121,89,1,0,1,0,1,0,124,1,100,2, - 117,0,114,75,100,6,160,8,124,3,161,1,6,0,89,0, - 83,0,100,7,160,8,124,3,124,1,161,2,6,0,89,0, - 83,0,100,8,160,8,124,3,124,4,161,2,83,0,119,0, - 119,0,119,0,41,9,122,44,84,104,101,32,105,109,112,108, - 101,109,101,110,116,97,116,105,111,110,32,111,102,32,77,111, - 100,117,108,101,84,121,112,101,46,95,95,114,101,112,114,95, - 95,40,41,46,218,10,95,95,108,111,97,100,101,114,95,95, - 78,218,8,95,95,115,112,101,99,95,95,218,11,109,111,100, - 117,108,101,95,114,101,112,114,250,1,63,250,13,60,109,111, - 100,117,108,101,32,123,33,114,125,62,250,20,60,109,111,100, - 117,108,101,32,123,33,114,125,32,40,123,33,114,125,41,62, - 250,23,60,109,111,100,117,108,101,32,123,33,114,125,32,102, - 114,111,109,32,123,33,114,125,62,41,9,114,13,0,0,0, - 218,22,95,109,111,100,117,108,101,95,114,101,112,114,95,102, - 114,111,109,95,115,112,101,99,114,11,0,0,0,114,114,0, - 0,0,218,9,69,120,99,101,112,116,105,111,110,114,9,0, - 0,0,114,2,0,0,0,218,8,95,95,102,105,108,101,95, - 95,114,50,0,0,0,41,5,114,110,0,0,0,218,6,108, - 111,97,100,101,114,114,109,0,0,0,114,20,0,0,0,218, - 8,102,105,108,101,110,97,109,101,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,218,12,95,109,111,100,117,108, - 101,95,114,101,112,114,38,1,0,0,115,44,0,0,0,12, - 2,16,1,8,1,10,1,2,1,12,1,12,1,2,1,2, - 2,10,1,12,1,6,1,2,1,10,1,12,1,8,1,14, - 1,16,2,12,2,2,250,2,252,2,251,114,124,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,4,0,0,0,64,0,0,0,115,114,0,0,0,101,0, - 90,1,100,0,90,2,100,1,90,3,100,2,100,2,100,2, - 100,3,156,3,100,4,100,5,132,2,90,4,100,6,100,7, - 132,0,90,5,100,8,100,9,132,0,90,6,101,7,100,10, - 100,11,132,0,131,1,90,8,101,8,106,9,100,12,100,11, - 132,0,131,1,90,8,101,7,100,13,100,14,132,0,131,1, - 90,10,101,7,100,15,100,16,132,0,131,1,90,11,101,11, - 106,9,100,17,100,16,132,0,131,1,90,11,100,2,83,0, - 41,18,218,10,77,111,100,117,108,101,83,112,101,99,97,208, - 5,0,0,84,104,101,32,115,112,101,99,105,102,105,99,97, - 116,105,111,110,32,102,111,114,32,97,32,109,111,100,117,108, - 101,44,32,117,115,101,100,32,102,111,114,32,108,111,97,100, - 105,110,103,46,10,10,32,32,32,32,65,32,109,111,100,117, - 108,101,39,115,32,115,112,101,99,32,105,115,32,116,104,101, - 32,115,111,117,114,99,101,32,102,111,114,32,105,110,102,111, - 114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104, - 101,32,109,111,100,117,108,101,46,32,32,70,111,114,10,32, - 32,32,32,100,97,116,97,32,97,115,115,111,99,105,97,116, - 101,100,32,119,105,116,104,32,116,104,101,32,109,111,100,117, - 108,101,44,32,105,110,99,108,117,100,105,110,103,32,115,111, - 117,114,99,101,44,32,117,115,101,32,116,104,101,32,115,112, - 101,99,39,115,10,32,32,32,32,108,111,97,100,101,114,46, - 10,10,32,32,32,32,96,110,97,109,101,96,32,105,115,32, - 116,104,101,32,97,98,115,111,108,117,116,101,32,110,97,109, - 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,46, - 32,32,96,108,111,97,100,101,114,96,32,105,115,32,116,104, - 101,32,108,111,97,100,101,114,10,32,32,32,32,116,111,32, - 117,115,101,32,119,104,101,110,32,108,111,97,100,105,110,103, - 32,116,104,101,32,109,111,100,117,108,101,46,32,32,96,112, - 97,114,101,110,116,96,32,105,115,32,116,104,101,32,110,97, - 109,101,32,111,102,32,116,104,101,10,32,32,32,32,112,97, - 99,107,97,103,101,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,105,110,46,32,32,84,104,101,32,112,97,114, - 101,110,116,32,105,115,32,100,101,114,105,118,101,100,32,102, - 114,111,109,32,116,104,101,32,110,97,109,101,46,10,10,32, - 32,32,32,96,105,115,95,112,97,99,107,97,103,101,96,32, - 100,101,116,101,114,109,105,110,101,115,32,105,102,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,99,111,110,115, - 105,100,101,114,101,100,32,97,32,112,97,99,107,97,103,101, - 32,111,114,10,32,32,32,32,110,111,116,46,32,32,79,110, - 32,109,111,100,117,108,101,115,32,116,104,105,115,32,105,115, - 32,114,101,102,108,101,99,116,101,100,32,98,121,32,116,104, - 101,32,96,95,95,112,97,116,104,95,95,96,32,97,116,116, - 114,105,98,117,116,101,46,10,10,32,32,32,32,96,111,114, - 105,103,105,110,96,32,105,115,32,116,104,101,32,115,112,101, - 99,105,102,105,99,32,108,111,99,97,116,105,111,110,32,117, - 115,101,100,32,98,121,32,116,104,101,32,108,111,97,100,101, - 114,32,102,114,111,109,32,119,104,105,99,104,32,116,111,10, - 32,32,32,32,108,111,97,100,32,116,104,101,32,109,111,100, - 117,108,101,44,32,105,102,32,116,104,97,116,32,105,110,102, - 111,114,109,97,116,105,111,110,32,105,115,32,97,118,97,105, - 108,97,98,108,101,46,32,32,87,104,101,110,32,102,105,108, - 101,110,97,109,101,32,105,115,10,32,32,32,32,115,101,116, - 44,32,111,114,105,103,105,110,32,119,105,108,108,32,109,97, - 116,99,104,46,10,10,32,32,32,32,96,104,97,115,95,108, - 111,99,97,116,105,111,110,96,32,105,110,100,105,99,97,116, - 101,115,32,116,104,97,116,32,97,32,115,112,101,99,39,115, - 32,34,111,114,105,103,105,110,34,32,114,101,102,108,101,99, - 116,115,32,97,32,108,111,99,97,116,105,111,110,46,10,32, - 32,32,32,87,104,101,110,32,116,104,105,115,32,105,115,32, - 84,114,117,101,44,32,96,95,95,102,105,108,101,95,95,96, - 32,97,116,116,114,105,98,117,116,101,32,111,102,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,115,101,116,46, - 10,10,32,32,32,32,96,99,97,99,104,101,100,96,32,105, - 115,32,116,104,101,32,108,111,99,97,116,105,111,110,32,111, - 102,32,116,104,101,32,99,97,99,104,101,100,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,44,32,105,102,32,97, - 110,121,46,32,32,73,116,10,32,32,32,32,99,111,114,114, - 101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,96, - 95,95,99,97,99,104,101,100,95,95,96,32,97,116,116,114, - 105,98,117,116,101,46,10,10,32,32,32,32,96,115,117,98, - 109,111,100,117,108,101,95,115,101,97,114,99,104,95,108,111, - 99,97,116,105,111,110,115,96,32,105,115,32,116,104,101,32, - 115,101,113,117,101,110,99,101,32,111,102,32,112,97,116,104, - 32,101,110,116,114,105,101,115,32,116,111,10,32,32,32,32, - 115,101,97,114,99,104,32,119,104,101,110,32,105,109,112,111, - 114,116,105,110,103,32,115,117,98,109,111,100,117,108,101,115, - 46,32,32,73,102,32,115,101,116,44,32,105,115,95,112,97, - 99,107,97,103,101,32,115,104,111,117,108,100,32,98,101,10, - 32,32,32,32,84,114,117,101,45,45,97,110,100,32,70,97, - 108,115,101,32,111,116,104,101,114,119,105,115,101,46,10,10, - 32,32,32,32,80,97,99,107,97,103,101,115,32,97,114,101, - 32,115,105,109,112,108,121,32,109,111,100,117,108,101,115,32, - 116,104,97,116,32,40,109,97,121,41,32,104,97,118,101,32, - 115,117,98,109,111,100,117,108,101,115,46,32,32,73,102,32, - 97,32,115,112,101,99,10,32,32,32,32,104,97,115,32,97, - 32,110,111,110,45,78,111,110,101,32,118,97,108,117,101,32, - 105,110,32,96,115,117,98,109,111,100,117,108,101,95,115,101, - 97,114,99,104,95,108,111,99,97,116,105,111,110,115,96,44, - 32,116,104,101,32,105,109,112,111,114,116,10,32,32,32,32, - 115,121,115,116,101,109,32,119,105,108,108,32,99,111,110,115, - 105,100,101,114,32,109,111,100,117,108,101,115,32,108,111,97, - 100,101,100,32,102,114,111,109,32,116,104,101,32,115,112,101, - 99,32,97,115,32,112,97,99,107,97,103,101,115,46,10,10, - 32,32,32,32,79,110,108,121,32,102,105,110,100,101,114,115, - 32,40,115,101,101,32,105,109,112,111,114,116,108,105,98,46, - 97,98,99,46,77,101,116,97,80,97,116,104,70,105,110,100, - 101,114,32,97,110,100,10,32,32,32,32,105,109,112,111,114, - 116,108,105,98,46,97,98,99,46,80,97,116,104,69,110,116, - 114,121,70,105,110,100,101,114,41,32,115,104,111,117,108,100, - 32,109,111,100,105,102,121,32,77,111,100,117,108,101,83,112, - 101,99,32,105,110,115,116,97,110,99,101,115,46,10,10,32, - 32,32,32,78,41,3,218,6,111,114,105,103,105,110,218,12, - 108,111,97,100,101,114,95,115,116,97,116,101,218,10,105,115, - 95,112,97,99,107,97,103,101,99,3,0,0,0,0,0,0, - 0,3,0,0,0,6,0,0,0,2,0,0,0,67,0,0, - 0,115,54,0,0,0,124,1,124,0,95,0,124,2,124,0, - 95,1,124,3,124,0,95,2,124,4,124,0,95,3,124,5, - 114,16,103,0,110,1,100,0,124,0,95,4,100,1,124,0, - 95,5,100,0,124,0,95,6,100,0,83,0,41,2,78,70, - 41,7,114,20,0,0,0,114,122,0,0,0,114,126,0,0, - 0,114,127,0,0,0,218,26,115,117,98,109,111,100,117,108, - 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, - 110,115,218,13,95,115,101,116,95,102,105,108,101,97,116,116, - 114,218,7,95,99,97,99,104,101,100,41,6,114,33,0,0, - 0,114,20,0,0,0,114,122,0,0,0,114,126,0,0,0, - 114,127,0,0,0,114,128,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,114,34,0,0,0,101,1, - 0,0,115,14,0,0,0,6,2,6,1,6,1,6,1,14, - 1,6,3,10,1,122,19,77,111,100,117,108,101,83,112,101, - 99,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, - 0,0,0,115,102,0,0,0,100,1,160,0,124,0,106,1, - 161,1,100,2,160,0,124,0,106,2,161,1,103,2,125,1, - 124,0,106,3,100,0,117,1,114,26,124,1,160,4,100,3, - 160,0,124,0,106,3,161,1,161,1,1,0,124,0,106,5, - 100,0,117,1,114,40,124,1,160,4,100,4,160,0,124,0, - 106,5,161,1,161,1,1,0,100,5,160,0,124,0,106,6, - 106,7,100,6,160,8,124,1,161,1,161,2,83,0,41,7, - 78,122,9,110,97,109,101,61,123,33,114,125,122,11,108,111, - 97,100,101,114,61,123,33,114,125,122,11,111,114,105,103,105, - 110,61,123,33,114,125,122,29,115,117,98,109,111,100,117,108, - 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, - 110,115,61,123,125,122,6,123,125,40,123,125,41,122,2,44, - 32,41,9,114,50,0,0,0,114,20,0,0,0,114,122,0, - 0,0,114,126,0,0,0,218,6,97,112,112,101,110,100,114, - 129,0,0,0,218,9,95,95,99,108,97,115,115,95,95,114, - 9,0,0,0,218,4,106,111,105,110,41,2,114,33,0,0, - 0,114,62,0,0,0,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,114,53,0,0,0,113,1,0,0,115,20, - 0,0,0,10,1,10,1,4,255,10,2,18,1,10,1,6, - 1,8,1,4,255,22,2,122,19,77,111,100,117,108,101,83, - 112,101,99,46,95,95,114,101,112,114,95,95,99,2,0,0, - 0,0,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,67,0,0,0,115,102,0,0,0,124,0,106,0,125,2, - 122,36,124,0,106,1,124,1,106,1,107,2,111,38,124,0, - 106,2,124,1,106,2,107,2,111,38,124,0,106,3,124,1, - 106,3,107,2,111,38,124,2,124,1,106,0,107,2,111,38, - 124,0,106,4,124,1,106,4,107,2,111,38,124,0,106,5, - 124,1,106,5,107,2,87,0,83,0,4,0,116,6,121,50, - 1,0,1,0,1,0,116,7,6,0,89,0,83,0,119,0, - 114,0,0,0,0,41,8,114,129,0,0,0,114,20,0,0, - 0,114,122,0,0,0,114,126,0,0,0,218,6,99,97,99, - 104,101,100,218,12,104,97,115,95,108,111,99,97,116,105,111, - 110,114,2,0,0,0,218,14,78,111,116,73,109,112,108,101, - 109,101,110,116,101,100,41,3,114,33,0,0,0,90,5,111, - 116,104,101,114,90,4,115,109,115,108,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,218,6,95,95,101,113,95, - 95,123,1,0,0,115,32,0,0,0,6,1,2,1,12,1, - 10,1,2,255,10,2,2,254,8,3,2,253,10,4,2,252, - 10,5,4,251,12,6,8,1,2,255,122,17,77,111,100,117, - 108,101,83,112,101,99,46,95,95,101,113,95,95,99,1,0, - 0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,58,0,0,0,124,0,106,0,100, - 0,117,0,114,26,124,0,106,1,100,0,117,1,114,26,124, - 0,106,2,114,26,116,3,100,0,117,0,114,19,116,4,130, - 1,116,3,160,5,124,0,106,1,161,1,124,0,95,0,124, - 0,106,0,83,0,114,0,0,0,0,41,6,114,131,0,0, - 0,114,126,0,0,0,114,130,0,0,0,218,19,95,98,111, - 111,116,115,116,114,97,112,95,101,120,116,101,114,110,97,108, - 218,19,78,111,116,73,109,112,108,101,109,101,110,116,101,100, - 69,114,114,111,114,90,11,95,103,101,116,95,99,97,99,104, - 101,100,114,52,0,0,0,114,5,0,0,0,114,5,0,0, - 0,114,6,0,0,0,114,135,0,0,0,135,1,0,0,115, - 12,0,0,0,10,2,16,1,8,1,4,1,14,1,6,1, - 122,17,77,111,100,117,108,101,83,112,101,99,46,99,97,99, - 104,101,100,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,2,0,0,0,67,0,0,0,115,10,0,0, - 0,124,1,124,0,95,0,100,0,83,0,114,0,0,0,0, - 41,1,114,131,0,0,0,41,2,114,33,0,0,0,114,135, - 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,114,135,0,0,0,144,1,0,0,115,2,0,0,0, - 10,2,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,115,32,0,0,0, - 124,0,106,0,100,1,117,0,114,13,124,0,106,1,160,2, - 100,2,161,1,100,3,25,0,83,0,124,0,106,1,83,0, - 41,4,122,32,84,104,101,32,110,97,109,101,32,111,102,32, - 116,104,101,32,109,111,100,117,108,101,39,115,32,112,97,114, - 101,110,116,46,78,218,1,46,114,25,0,0,0,41,3,114, - 129,0,0,0,114,20,0,0,0,218,10,114,112,97,114,116, - 105,116,105,111,110,114,52,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,218,6,112,97,114,101,110, - 116,148,1,0,0,115,6,0,0,0,10,3,16,1,6,2, - 122,17,77,111,100,117,108,101,83,112,101,99,46,112,97,114, - 101,110,116,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,1,0,0,0,67,0,0,0,115,6,0,0, - 0,124,0,106,0,83,0,114,0,0,0,0,41,1,114,130, - 0,0,0,114,52,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,114,136,0,0,0,156,1,0,0, - 115,2,0,0,0,6,2,122,23,77,111,100,117,108,101,83, - 112,101,99,46,104,97,115,95,108,111,99,97,116,105,111,110, - 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,2,0,0,0,67,0,0,0,115,14,0,0,0,116,0, - 124,1,131,1,124,0,95,1,100,0,83,0,114,0,0,0, - 0,41,2,218,4,98,111,111,108,114,130,0,0,0,41,2, - 114,33,0,0,0,218,5,118,97,108,117,101,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,114,136,0,0,0, - 160,1,0,0,115,2,0,0,0,14,2,41,12,114,9,0, + 8,95,95,114,101,112,114,95,95,138,0,0,0,243,2,0, + 0,0,18,1,122,20,95,77,111,100,117,108,101,76,111,99, + 107,46,95,95,114,101,112,114,95,95,78,41,9,114,9,0, 0,0,114,8,0,0,0,114,1,0,0,0,114,10,0,0, - 0,114,34,0,0,0,114,53,0,0,0,114,138,0,0,0, - 218,8,112,114,111,112,101,114,116,121,114,135,0,0,0,218, - 6,115,101,116,116,101,114,114,143,0,0,0,114,136,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,114,125,0,0,0,64,1,0,0,115,34, - 0,0,0,8,0,4,1,4,36,2,1,12,255,8,12,8, - 10,2,12,10,1,4,8,10,1,2,3,10,1,2,7,10, - 1,4,3,14,1,114,125,0,0,0,169,2,114,126,0,0, - 0,114,128,0,0,0,99,2,0,0,0,0,0,0,0,2, - 0,0,0,6,0,0,0,8,0,0,0,67,0,0,0,115, - 150,0,0,0,116,0,124,1,100,1,131,2,114,37,116,1, - 100,2,117,0,114,11,116,2,130,1,116,1,106,3,125,4, - 124,3,100,2,117,0,114,24,124,4,124,0,124,1,100,3, - 141,2,83,0,124,3,114,28,103,0,110,1,100,2,125,5, - 124,4,124,0,124,1,124,5,100,4,141,3,83,0,124,3, - 100,2,117,0,114,66,116,0,124,1,100,5,131,2,114,64, - 122,7,124,1,160,4,124,0,161,1,125,3,87,0,110,12, - 4,0,116,5,121,74,1,0,1,0,1,0,100,2,125,3, - 89,0,110,2,100,6,125,3,116,6,124,0,124,1,124,2, - 124,3,100,7,141,4,83,0,119,0,41,8,122,53,82,101, - 116,117,114,110,32,97,32,109,111,100,117,108,101,32,115,112, - 101,99,32,98,97,115,101,100,32,111,110,32,118,97,114,105, - 111,117,115,32,108,111,97,100,101,114,32,109,101,116,104,111, - 100,115,46,90,12,103,101,116,95,102,105,108,101,110,97,109, - 101,78,41,1,114,122,0,0,0,41,2,114,122,0,0,0, - 114,129,0,0,0,114,128,0,0,0,70,114,148,0,0,0, - 41,7,114,11,0,0,0,114,139,0,0,0,114,140,0,0, - 0,218,23,115,112,101,99,95,102,114,111,109,95,102,105,108, - 101,95,108,111,99,97,116,105,111,110,114,128,0,0,0,114, - 87,0,0,0,114,125,0,0,0,41,6,114,20,0,0,0, - 114,122,0,0,0,114,126,0,0,0,114,128,0,0,0,114, - 149,0,0,0,90,6,115,101,97,114,99,104,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,114,104,0,0,0, - 165,1,0,0,115,38,0,0,0,10,2,8,1,4,1,6, - 1,8,2,12,1,12,1,6,1,2,1,6,255,8,3,10, - 1,2,1,14,1,12,1,8,1,4,3,16,2,2,250,114, - 104,0,0,0,99,3,0,0,0,0,0,0,0,0,0,0, - 0,8,0,0,0,8,0,0,0,67,0,0,0,115,30,1, - 0,0,122,5,124,0,106,0,125,3,87,0,110,8,4,0, - 116,1,121,142,1,0,1,0,1,0,89,0,110,6,124,3, - 100,0,117,1,114,20,124,3,83,0,124,0,106,2,125,4, - 124,1,100,0,117,0,114,40,122,5,124,0,106,3,125,1, - 87,0,110,7,4,0,116,1,121,141,1,0,1,0,1,0, - 89,0,122,5,124,0,106,4,125,5,87,0,110,9,4,0, - 116,1,121,140,1,0,1,0,1,0,100,0,125,5,89,0, - 124,2,100,0,117,0,114,81,124,5,100,0,117,0,114,79, - 122,5,124,1,106,5,125,2,87,0,110,12,4,0,116,1, - 121,139,1,0,1,0,1,0,100,0,125,2,89,0,110,2, - 124,5,125,2,122,5,124,0,106,6,125,6,87,0,110,9, - 4,0,116,1,121,138,1,0,1,0,1,0,100,0,125,6, - 89,0,122,7,116,7,124,0,106,8,131,1,125,7,87,0, - 110,9,4,0,116,1,121,137,1,0,1,0,1,0,100,0, - 125,7,89,0,116,9,124,4,124,1,124,2,100,1,141,3, - 125,3,124,5,100,0,117,0,114,126,100,2,110,1,100,3, - 124,3,95,10,124,6,124,3,95,11,124,7,124,3,95,12, - 124,3,83,0,119,0,119,0,119,0,119,0,119,0,119,0, + 0,114,34,0,0,0,114,41,0,0,0,114,43,0,0,0, + 114,44,0,0,0,114,53,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,23, + 0,0,0,65,0,0,0,115,14,0,0,0,8,0,4,1, + 8,5,8,8,8,21,8,25,12,13,114,23,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,64,0,0,0,115,48,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, + 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, + 6,100,8,100,9,132,0,90,7,100,10,83,0,41,11,218, + 16,95,68,117,109,109,121,77,111,100,117,108,101,76,111,99, + 107,122,86,65,32,115,105,109,112,108,101,32,95,77,111,100, + 117,108,101,76,111,99,107,32,101,113,117,105,118,97,108,101, + 110,116,32,102,111,114,32,80,121,116,104,111,110,32,98,117, + 105,108,100,115,32,119,105,116,104,111,117,116,10,32,32,32, + 32,109,117,108,116,105,45,116,104,114,101,97,100,105,110,103, + 32,115,117,112,112,111,114,116,46,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0, + 0,0,115,16,0,0,0,124,1,124,0,95,0,100,1,124, + 0,95,1,100,0,83,0,114,24,0,0,0,41,2,114,20, + 0,0,0,114,30,0,0,0,114,32,0,0,0,114,5,0, + 0,0,114,5,0,0,0,114,6,0,0,0,114,34,0,0, + 0,146,0,0,0,243,4,0,0,0,6,1,10,1,122,25, + 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, + 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,18,0,0,0,124,0,4,0,106,0,100,1,55, + 0,2,0,95,0,100,2,83,0,41,3,78,114,42,0,0, + 0,84,41,1,114,30,0,0,0,114,52,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,43,0, + 0,0,150,0,0,0,115,4,0,0,0,14,1,4,1,122, + 24,95,68,117,109,109,121,77,111,100,117,108,101,76,111,99, + 107,46,97,99,113,117,105,114,101,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,36,0,0,0,124,0,106,0,100,1,107,2,114, + 9,116,1,100,2,131,1,130,1,124,0,4,0,106,0,100, + 3,56,0,2,0,95,0,100,0,83,0,41,4,78,114,25, + 0,0,0,114,46,0,0,0,114,42,0,0,0,41,2,114, + 30,0,0,0,114,47,0,0,0,114,52,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,44,0, + 0,0,154,0,0,0,115,6,0,0,0,10,1,8,1,18, + 1,122,24,95,68,117,109,109,121,77,111,100,117,108,101,76, + 111,99,107,46,114,101,108,101,97,115,101,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0, + 67,0,0,0,114,48,0,0,0,41,2,78,122,28,95,68, + 117,109,109,121,77,111,100,117,108,101,76,111,99,107,40,123, + 33,114,125,41,32,97,116,32,123,125,114,49,0,0,0,114, + 52,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,114,53,0,0,0,159,0,0,0,114,54,0,0, + 0,122,25,95,68,117,109,109,121,77,111,100,117,108,101,76, + 111,99,107,46,95,95,114,101,112,114,95,95,78,41,8,114, + 9,0,0,0,114,8,0,0,0,114,1,0,0,0,114,10, + 0,0,0,114,34,0,0,0,114,43,0,0,0,114,44,0, + 0,0,114,53,0,0,0,114,5,0,0,0,114,5,0,0, + 0,114,5,0,0,0,114,6,0,0,0,114,55,0,0,0, + 142,0,0,0,115,12,0,0,0,8,0,4,1,8,3,8, + 4,8,4,12,5,114,55,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, + 0,0,0,115,36,0,0,0,101,0,90,1,100,0,90,2, + 100,1,100,2,132,0,90,3,100,3,100,4,132,0,90,4, + 100,5,100,6,132,0,90,5,100,7,83,0,41,8,218,18, + 95,77,111,100,117,108,101,76,111,99,107,77,97,110,97,103, + 101,114,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, + 124,1,124,0,95,0,100,0,124,0,95,1,100,0,83,0, + 114,0,0,0,0,41,2,218,5,95,110,97,109,101,218,5, + 95,108,111,99,107,114,32,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,6,0,0,0,114,34,0,0,0,165,0, + 0,0,114,56,0,0,0,122,27,95,77,111,100,117,108,101, + 76,111,99,107,77,97,110,97,103,101,114,46,95,95,105,110, + 105,116,95,95,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,2,0,0,0,67,0,0,0,115,26,0, + 0,0,116,0,124,0,106,1,131,1,124,0,95,2,124,0, + 106,2,160,3,161,0,1,0,100,0,83,0,114,0,0,0, + 0,41,4,218,16,95,103,101,116,95,109,111,100,117,108,101, + 95,108,111,99,107,114,58,0,0,0,114,59,0,0,0,114, + 43,0,0,0,114,52,0,0,0,114,5,0,0,0,114,5, + 0,0,0,114,6,0,0,0,218,9,95,95,101,110,116,101, + 114,95,95,169,0,0,0,115,4,0,0,0,12,1,14,1, + 122,28,95,77,111,100,117,108,101,76,111,99,107,77,97,110, + 97,103,101,114,46,95,95,101,110,116,101,114,95,95,99,1, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, + 0,0,0,79,0,0,0,115,14,0,0,0,124,0,106,0, + 160,1,161,0,1,0,100,0,83,0,114,0,0,0,0,41, + 2,114,59,0,0,0,114,44,0,0,0,41,3,114,33,0, + 0,0,218,4,97,114,103,115,90,6,107,119,97,114,103,115, + 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,218, + 8,95,95,101,120,105,116,95,95,173,0,0,0,115,2,0, + 0,0,14,1,122,27,95,77,111,100,117,108,101,76,111,99, + 107,77,97,110,97,103,101,114,46,95,95,101,120,105,116,95, + 95,78,41,6,114,9,0,0,0,114,8,0,0,0,114,1, + 0,0,0,114,34,0,0,0,114,61,0,0,0,114,63,0, + 0,0,114,5,0,0,0,114,5,0,0,0,114,5,0,0, + 0,114,6,0,0,0,114,57,0,0,0,163,0,0,0,115, + 8,0,0,0,8,0,8,2,8,4,12,4,114,57,0,0, + 0,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,8,0,0,0,67,0,0,0,115,148,0,0,0,116, + 0,160,1,161,0,1,0,122,64,122,7,116,2,124,0,25, + 0,131,0,125,1,87,0,110,11,4,0,116,3,121,23,1, + 0,1,0,1,0,100,1,125,1,89,0,110,1,119,0,124, + 1,100,1,117,0,114,62,116,4,100,1,117,0,114,37,116, + 5,124,0,131,1,125,1,110,4,116,6,124,0,131,1,125, + 1,124,0,102,1,100,2,100,3,132,1,125,2,116,7,160, + 8,124,1,124,2,161,2,116,2,124,0,60,0,87,0,116, + 0,160,9,161,0,1,0,124,1,83,0,87,0,116,0,160, + 9,161,0,1,0,124,1,83,0,116,0,160,9,161,0,1, + 0,119,0,41,4,122,139,71,101,116,32,111,114,32,99,114, + 101,97,116,101,32,116,104,101,32,109,111,100,117,108,101,32, + 108,111,99,107,32,102,111,114,32,97,32,103,105,118,101,110, + 32,109,111,100,117,108,101,32,110,97,109,101,46,10,10,32, + 32,32,32,65,99,113,117,105,114,101,47,114,101,108,101,97, + 115,101,32,105,110,116,101,114,110,97,108,108,121,32,116,104, + 101,32,103,108,111,98,97,108,32,105,109,112,111,114,116,32, + 108,111,99,107,32,116,111,32,112,114,111,116,101,99,116,10, + 32,32,32,32,95,109,111,100,117,108,101,95,108,111,99,107, + 115,46,78,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,8,0,0,0,83,0,0,0,115,68,0,0, + 0,116,0,160,1,161,0,1,0,122,24,116,2,160,3,124, + 1,161,1,124,0,117,0,114,22,116,2,124,1,61,0,87, + 0,116,0,160,4,161,0,1,0,100,0,83,0,87,0,116, + 0,160,4,161,0,1,0,100,0,83,0,116,0,160,4,161, + 0,1,0,119,0,114,0,0,0,0,41,5,218,4,95,105, + 109,112,218,12,97,99,113,117,105,114,101,95,108,111,99,107, + 218,13,95,109,111,100,117,108,101,95,108,111,99,107,115,114, + 38,0,0,0,218,12,114,101,108,101,97,115,101,95,108,111, + 99,107,41,2,218,3,114,101,102,114,20,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,218,2,99, + 98,198,0,0,0,115,14,0,0,0,8,1,2,1,14,4, + 8,1,12,2,2,253,22,3,122,28,95,103,101,116,95,109, + 111,100,117,108,101,95,108,111,99,107,46,60,108,111,99,97, + 108,115,62,46,99,98,41,10,114,64,0,0,0,114,65,0, + 0,0,114,66,0,0,0,218,8,75,101,121,69,114,114,111, + 114,114,26,0,0,0,114,55,0,0,0,114,23,0,0,0, + 218,8,95,119,101,97,107,114,101,102,114,68,0,0,0,114, + 67,0,0,0,41,3,114,20,0,0,0,114,27,0,0,0, + 114,69,0,0,0,114,5,0,0,0,114,5,0,0,0,114, + 6,0,0,0,114,60,0,0,0,179,0,0,0,115,38,0, + 0,0,8,6,2,1,2,1,14,1,12,1,8,1,2,255, + 8,3,8,1,10,1,8,2,12,2,18,11,8,2,4,2, + 2,235,8,19,4,2,10,254,114,60,0,0,0,99,1,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,8,0, + 0,0,67,0,0,0,115,54,0,0,0,116,0,124,0,131, + 1,125,1,122,6,124,1,160,1,161,0,1,0,87,0,110, + 10,4,0,116,2,121,20,1,0,1,0,1,0,89,0,100, + 1,83,0,119,0,124,1,160,3,161,0,1,0,100,1,83, + 0,41,2,122,189,65,99,113,117,105,114,101,115,32,116,104, + 101,110,32,114,101,108,101,97,115,101,115,32,116,104,101,32, + 109,111,100,117,108,101,32,108,111,99,107,32,102,111,114,32, + 97,32,103,105,118,101,110,32,109,111,100,117,108,101,32,110, + 97,109,101,46,10,10,32,32,32,32,84,104,105,115,32,105, + 115,32,117,115,101,100,32,116,111,32,101,110,115,117,114,101, + 32,97,32,109,111,100,117,108,101,32,105,115,32,99,111,109, + 112,108,101,116,101,108,121,32,105,110,105,116,105,97,108,105, + 122,101,100,44,32,105,110,32,116,104,101,10,32,32,32,32, + 101,118,101,110,116,32,105,116,32,105,115,32,98,101,105,110, + 103,32,105,109,112,111,114,116,101,100,32,98,121,32,97,110, + 111,116,104,101,114,32,116,104,114,101,97,100,46,10,32,32, + 32,32,78,41,4,114,60,0,0,0,114,43,0,0,0,114, + 22,0,0,0,114,44,0,0,0,41,2,114,20,0,0,0, + 114,27,0,0,0,114,5,0,0,0,114,5,0,0,0,114, + 6,0,0,0,218,19,95,108,111,99,107,95,117,110,108,111, + 99,107,95,109,111,100,117,108,101,216,0,0,0,115,14,0, + 0,0,8,6,2,1,12,1,12,1,6,3,2,253,12,5, + 114,72,0,0,0,99,1,0,0,0,0,0,0,0,0,0, + 0,0,3,0,0,0,4,0,0,0,79,0,0,0,115,14, + 0,0,0,124,0,124,1,105,0,124,2,164,1,142,1,83, + 0,41,1,97,46,1,0,0,114,101,109,111,118,101,95,105, + 109,112,111,114,116,108,105,98,95,102,114,97,109,101,115,32, + 105,110,32,105,109,112,111,114,116,46,99,32,119,105,108,108, + 32,97,108,119,97,121,115,32,114,101,109,111,118,101,32,115, + 101,113,117,101,110,99,101,115,10,32,32,32,32,111,102,32, + 105,109,112,111,114,116,108,105,98,32,102,114,97,109,101,115, + 32,116,104,97,116,32,101,110,100,32,119,105,116,104,32,97, + 32,99,97,108,108,32,116,111,32,116,104,105,115,32,102,117, + 110,99,116,105,111,110,10,10,32,32,32,32,85,115,101,32, + 105,116,32,105,110,115,116,101,97,100,32,111,102,32,97,32, + 110,111,114,109,97,108,32,99,97,108,108,32,105,110,32,112, + 108,97,99,101,115,32,119,104,101,114,101,32,105,110,99,108, + 117,100,105,110,103,32,116,104,101,32,105,109,112,111,114,116, + 108,105,98,10,32,32,32,32,102,114,97,109,101,115,32,105, + 110,116,114,111,100,117,99,101,115,32,117,110,119,97,110,116, + 101,100,32,110,111,105,115,101,32,105,110,116,111,32,116,104, + 101,32,116,114,97,99,101,98,97,99,107,32,40,101,46,103, + 46,32,119,104,101,110,32,101,120,101,99,117,116,105,110,103, + 10,32,32,32,32,109,111,100,117,108,101,32,99,111,100,101, + 41,10,32,32,32,32,114,5,0,0,0,41,3,218,1,102, + 114,62,0,0,0,90,4,107,119,100,115,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,25,95,99,97,108, + 108,95,119,105,116,104,95,102,114,97,109,101,115,95,114,101, + 109,111,118,101,100,233,0,0,0,115,2,0,0,0,14,8, + 114,74,0,0,0,114,42,0,0,0,41,1,218,9,118,101, + 114,98,111,115,105,116,121,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,4,0,0,0,71,0,0,0, + 115,58,0,0,0,116,0,106,1,106,2,124,1,107,5,114, + 27,124,0,160,3,100,1,161,1,115,15,100,2,124,0,23, + 0,125,0,116,4,124,0,106,5,124,2,142,0,116,0,106, + 6,100,3,141,2,1,0,100,4,83,0,100,4,83,0,41, + 5,122,61,80,114,105,110,116,32,116,104,101,32,109,101,115, + 115,97,103,101,32,116,111,32,115,116,100,101,114,114,32,105, + 102,32,45,118,47,80,89,84,72,79,78,86,69,82,66,79, + 83,69,32,105,115,32,116,117,114,110,101,100,32,111,110,46, + 41,2,250,1,35,122,7,105,109,112,111,114,116,32,122,2, + 35,32,41,1,90,4,102,105,108,101,78,41,7,114,18,0, + 0,0,218,5,102,108,97,103,115,218,7,118,101,114,98,111, + 115,101,218,10,115,116,97,114,116,115,119,105,116,104,218,5, + 112,114,105,110,116,114,50,0,0,0,218,6,115,116,100,101, + 114,114,41,3,218,7,109,101,115,115,97,103,101,114,75,0, + 0,0,114,62,0,0,0,114,5,0,0,0,114,5,0,0, + 0,114,6,0,0,0,218,16,95,118,101,114,98,111,115,101, + 95,109,101,115,115,97,103,101,244,0,0,0,115,10,0,0, + 0,12,2,10,1,8,1,24,1,4,253,114,83,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,3,0,0,0,3,0,0,0,243,26,0,0,0,135,0, + 102,1,100,1,100,2,132,8,125,1,116,0,124,1,136,0, + 131,2,1,0,124,1,83,0,41,3,122,49,68,101,99,111, + 114,97,116,111,114,32,116,111,32,118,101,114,105,102,121,32, + 116,104,101,32,110,97,109,101,100,32,109,111,100,117,108,101, + 32,105,115,32,98,117,105,108,116,45,105,110,46,99,2,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,19,0,0,0,115,38,0,0,0,124,1,116,0,106, + 1,118,1,114,14,116,2,100,1,160,3,124,1,161,1,124, + 1,100,2,141,2,130,1,136,0,124,0,124,1,131,2,83, + 0,41,3,78,250,29,123,33,114,125,32,105,115,32,110,111, + 116,32,97,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,114,19,0,0,0,41,4,114,18,0,0,0,218, + 20,98,117,105,108,116,105,110,95,109,111,100,117,108,101,95, + 110,97,109,101,115,218,11,73,109,112,111,114,116,69,114,114, + 111,114,114,50,0,0,0,169,2,114,33,0,0,0,218,8, + 102,117,108,108,110,97,109,101,169,1,218,3,102,120,110,114, + 5,0,0,0,114,6,0,0,0,218,25,95,114,101,113,117, + 105,114,101,115,95,98,117,105,108,116,105,110,95,119,114,97, + 112,112,101,114,254,0,0,0,243,10,0,0,0,10,1,10, + 1,2,1,6,255,10,2,122,52,95,114,101,113,117,105,114, + 101,115,95,98,117,105,108,116,105,110,46,60,108,111,99,97, + 108,115,62,46,95,114,101,113,117,105,114,101,115,95,98,117, + 105,108,116,105,110,95,119,114,97,112,112,101,114,169,1,114, + 17,0,0,0,41,2,114,91,0,0,0,114,92,0,0,0, + 114,5,0,0,0,114,90,0,0,0,114,6,0,0,0,218, + 17,95,114,101,113,117,105,114,101,115,95,98,117,105,108,116, + 105,110,252,0,0,0,243,6,0,0,0,12,2,10,5,4, + 1,114,95,0,0,0,99,1,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,114, + 84,0,0,0,41,3,122,47,68,101,99,111,114,97,116,111, + 114,32,116,111,32,118,101,114,105,102,121,32,116,104,101,32, + 110,97,109,101,100,32,109,111,100,117,108,101,32,105,115,32, + 102,114,111,122,101,110,46,99,2,0,0,0,0,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,19,0,0,0, + 115,38,0,0,0,116,0,160,1,124,1,161,1,115,14,116, + 2,100,1,160,3,124,1,161,1,124,1,100,2,141,2,130, + 1,136,0,124,0,124,1,131,2,83,0,169,3,78,122,27, + 123,33,114,125,32,105,115,32,110,111,116,32,97,32,102,114, + 111,122,101,110,32,109,111,100,117,108,101,114,19,0,0,0, + 41,4,114,64,0,0,0,218,9,105,115,95,102,114,111,122, + 101,110,114,87,0,0,0,114,50,0,0,0,114,88,0,0, + 0,114,90,0,0,0,114,5,0,0,0,114,6,0,0,0, + 218,24,95,114,101,113,117,105,114,101,115,95,102,114,111,122, + 101,110,95,119,114,97,112,112,101,114,9,1,0,0,114,93, + 0,0,0,122,50,95,114,101,113,117,105,114,101,115,95,102, + 114,111,122,101,110,46,60,108,111,99,97,108,115,62,46,95, + 114,101,113,117,105,114,101,115,95,102,114,111,122,101,110,95, + 119,114,97,112,112,101,114,114,94,0,0,0,41,2,114,91, + 0,0,0,114,99,0,0,0,114,5,0,0,0,114,90,0, + 0,0,114,6,0,0,0,218,16,95,114,101,113,117,105,114, + 101,115,95,102,114,111,122,101,110,7,1,0,0,114,96,0, + 0,0,114,100,0,0,0,99,2,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,4,0,0,0,67,0,0,0, + 115,74,0,0,0,100,1,125,2,116,0,160,1,124,2,116, + 2,161,2,1,0,116,3,124,1,124,0,131,2,125,3,124, + 1,116,4,106,5,118,0,114,33,116,4,106,5,124,1,25, + 0,125,4,116,6,124,3,124,4,131,2,1,0,116,4,106, + 5,124,1,25,0,83,0,116,7,124,3,131,1,83,0,41, + 2,122,130,76,111,97,100,32,116,104,101,32,115,112,101,99, + 105,102,105,101,100,32,109,111,100,117,108,101,32,105,110,116, + 111,32,115,121,115,46,109,111,100,117,108,101,115,32,97,110, + 100,32,114,101,116,117,114,110,32,105,116,46,10,10,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,108,111,97,100,101,114,46,101,120,101,99,95,109,111, + 100,117,108,101,40,41,32,105,110,115,116,101,97,100,46,10, + 10,32,32,32,32,122,103,116,104,101,32,108,111,97,100,95, + 109,111,100,117,108,101,40,41,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,110, + 100,32,115,108,97,116,101,100,32,102,111,114,32,114,101,109, + 111,118,97,108,32,105,110,32,80,121,116,104,111,110,32,51, + 46,49,50,59,32,117,115,101,32,101,120,101,99,95,109,111, + 100,117,108,101,40,41,32,105,110,115,116,101,97,100,41,8, + 218,9,95,119,97,114,110,105,110,103,115,218,4,119,97,114, + 110,218,18,68,101,112,114,101,99,97,116,105,111,110,87,97, + 114,110,105,110,103,218,16,115,112,101,99,95,102,114,111,109, + 95,108,111,97,100,101,114,114,18,0,0,0,218,7,109,111, + 100,117,108,101,115,218,5,95,101,120,101,99,218,5,95,108, + 111,97,100,41,5,114,33,0,0,0,114,89,0,0,0,218, + 3,109,115,103,218,4,115,112,101,99,218,6,109,111,100,117, + 108,101,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,218,17,95,108,111,97,100,95,109,111,100,117,108,101,95, + 115,104,105,109,19,1,0,0,115,16,0,0,0,4,6,12, + 2,10,1,10,1,10,1,10,1,10,1,8,2,114,111,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,8,0,0,0,67,0,0,0,115,188,0,0,0, + 116,0,124,0,100,1,100,2,131,3,125,1,116,0,124,0, + 100,3,100,2,131,3,4,0,125,2,114,18,116,1,124,2, + 131,1,83,0,116,2,124,1,100,4,131,2,114,39,122,6, + 124,1,160,3,124,0,161,1,87,0,83,0,4,0,116,4, + 121,38,1,0,1,0,1,0,89,0,110,1,119,0,122,5, + 124,0,106,5,125,3,87,0,110,11,4,0,116,6,121,55, + 1,0,1,0,1,0,100,5,125,3,89,0,110,1,119,0, + 122,5,124,0,106,7,125,4,87,0,110,26,4,0,116,6, + 121,87,1,0,1,0,1,0,124,1,100,2,117,0,114,79, + 100,6,160,8,124,3,161,1,6,0,89,0,83,0,100,7, + 160,8,124,3,124,1,161,2,6,0,89,0,83,0,119,0, + 100,8,160,8,124,3,124,4,161,2,83,0,41,9,122,44, + 84,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105, + 111,110,32,111,102,32,77,111,100,117,108,101,84,121,112,101, + 46,95,95,114,101,112,114,95,95,40,41,46,218,10,95,95, + 108,111,97,100,101,114,95,95,78,218,8,95,95,115,112,101, + 99,95,95,218,11,109,111,100,117,108,101,95,114,101,112,114, + 250,1,63,250,13,60,109,111,100,117,108,101,32,123,33,114, + 125,62,250,20,60,109,111,100,117,108,101,32,123,33,114,125, + 32,40,123,33,114,125,41,62,250,23,60,109,111,100,117,108, + 101,32,123,33,114,125,32,102,114,111,109,32,123,33,114,125, + 62,41,9,114,13,0,0,0,218,22,95,109,111,100,117,108, + 101,95,114,101,112,114,95,102,114,111,109,95,115,112,101,99, + 114,11,0,0,0,114,114,0,0,0,218,9,69,120,99,101, + 112,116,105,111,110,114,9,0,0,0,114,2,0,0,0,218, + 8,95,95,102,105,108,101,95,95,114,50,0,0,0,41,5, + 114,110,0,0,0,218,6,108,111,97,100,101,114,114,109,0, + 0,0,114,20,0,0,0,218,8,102,105,108,101,110,97,109, + 101,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, + 218,12,95,109,111,100,117,108,101,95,114,101,112,114,38,1, + 0,0,115,44,0,0,0,12,2,16,1,8,1,10,1,2, + 1,12,1,12,1,4,1,2,255,2,3,10,1,12,1,8, + 1,2,255,2,2,10,1,12,1,8,1,14,1,16,2,2, + 252,12,6,114,124,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, + 0,115,114,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,2,100,2,100,3,156,3,100,4,100,5, + 132,2,90,4,100,6,100,7,132,0,90,5,100,8,100,9, + 132,0,90,6,101,7,100,10,100,11,132,0,131,1,90,8, + 101,8,106,9,100,12,100,11,132,0,131,1,90,8,101,7, + 100,13,100,14,132,0,131,1,90,10,101,7,100,15,100,16, + 132,0,131,1,90,11,101,11,106,9,100,17,100,16,132,0, + 131,1,90,11,100,2,83,0,41,18,218,10,77,111,100,117, + 108,101,83,112,101,99,97,208,5,0,0,84,104,101,32,115, + 112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114, + 32,97,32,109,111,100,117,108,101,44,32,117,115,101,100,32, + 102,111,114,32,108,111,97,100,105,110,103,46,10,10,32,32, + 32,32,65,32,109,111,100,117,108,101,39,115,32,115,112,101, + 99,32,105,115,32,116,104,101,32,115,111,117,114,99,101,32, + 102,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32, + 97,98,111,117,116,32,116,104,101,32,109,111,100,117,108,101, + 46,32,32,70,111,114,10,32,32,32,32,100,97,116,97,32, + 97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32, + 116,104,101,32,109,111,100,117,108,101,44,32,105,110,99,108, + 117,100,105,110,103,32,115,111,117,114,99,101,44,32,117,115, + 101,32,116,104,101,32,115,112,101,99,39,115,10,32,32,32, + 32,108,111,97,100,101,114,46,10,10,32,32,32,32,96,110, + 97,109,101,96,32,105,115,32,116,104,101,32,97,98,115,111, + 108,117,116,101,32,110,97,109,101,32,111,102,32,116,104,101, + 32,109,111,100,117,108,101,46,32,32,96,108,111,97,100,101, + 114,96,32,105,115,32,116,104,101,32,108,111,97,100,101,114, + 10,32,32,32,32,116,111,32,117,115,101,32,119,104,101,110, + 32,108,111,97,100,105,110,103,32,116,104,101,32,109,111,100, + 117,108,101,46,32,32,96,112,97,114,101,110,116,96,32,105, + 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, + 101,10,32,32,32,32,112,97,99,107,97,103,101,32,116,104, + 101,32,109,111,100,117,108,101,32,105,115,32,105,110,46,32, + 32,84,104,101,32,112,97,114,101,110,116,32,105,115,32,100, + 101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32, + 110,97,109,101,46,10,10,32,32,32,32,96,105,115,95,112, + 97,99,107,97,103,101,96,32,100,101,116,101,114,109,105,110, + 101,115,32,105,102,32,116,104,101,32,109,111,100,117,108,101, + 32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97, + 32,112,97,99,107,97,103,101,32,111,114,10,32,32,32,32, + 110,111,116,46,32,32,79,110,32,109,111,100,117,108,101,115, + 32,116,104,105,115,32,105,115,32,114,101,102,108,101,99,116, + 101,100,32,98,121,32,116,104,101,32,96,95,95,112,97,116, + 104,95,95,96,32,97,116,116,114,105,98,117,116,101,46,10, + 10,32,32,32,32,96,111,114,105,103,105,110,96,32,105,115, + 32,116,104,101,32,115,112,101,99,105,102,105,99,32,108,111, + 99,97,116,105,111,110,32,117,115,101,100,32,98,121,32,116, + 104,101,32,108,111,97,100,101,114,32,102,114,111,109,32,119, + 104,105,99,104,32,116,111,10,32,32,32,32,108,111,97,100, + 32,116,104,101,32,109,111,100,117,108,101,44,32,105,102,32, + 116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110, + 32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,32, + 87,104,101,110,32,102,105,108,101,110,97,109,101,32,105,115, + 10,32,32,32,32,115,101,116,44,32,111,114,105,103,105,110, + 32,119,105,108,108,32,109,97,116,99,104,46,10,10,32,32, + 32,32,96,104,97,115,95,108,111,99,97,116,105,111,110,96, + 32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32, + 97,32,115,112,101,99,39,115,32,34,111,114,105,103,105,110, + 34,32,114,101,102,108,101,99,116,115,32,97,32,108,111,99, + 97,116,105,111,110,46,10,32,32,32,32,87,104,101,110,32, + 116,104,105,115,32,105,115,32,84,114,117,101,44,32,96,95, + 95,102,105,108,101,95,95,96,32,97,116,116,114,105,98,117, + 116,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101, + 32,105,115,32,115,101,116,46,10,10,32,32,32,32,96,99, + 97,99,104,101,100,96,32,105,115,32,116,104,101,32,108,111, + 99,97,116,105,111,110,32,111,102,32,116,104,101,32,99,97, + 99,104,101,100,32,98,121,116,101,99,111,100,101,32,102,105, + 108,101,44,32,105,102,32,97,110,121,46,32,32,73,116,10, + 32,32,32,32,99,111,114,114,101,115,112,111,110,100,115,32, + 116,111,32,116,104,101,32,96,95,95,99,97,99,104,101,100, + 95,95,96,32,97,116,116,114,105,98,117,116,101,46,10,10, + 32,32,32,32,96,115,117,98,109,111,100,117,108,101,95,115, + 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,96, + 32,105,115,32,116,104,101,32,115,101,113,117,101,110,99,101, + 32,111,102,32,112,97,116,104,32,101,110,116,114,105,101,115, + 32,116,111,10,32,32,32,32,115,101,97,114,99,104,32,119, + 104,101,110,32,105,109,112,111,114,116,105,110,103,32,115,117, + 98,109,111,100,117,108,101,115,46,32,32,73,102,32,115,101, + 116,44,32,105,115,95,112,97,99,107,97,103,101,32,115,104, + 111,117,108,100,32,98,101,10,32,32,32,32,84,114,117,101, + 45,45,97,110,100,32,70,97,108,115,101,32,111,116,104,101, + 114,119,105,115,101,46,10,10,32,32,32,32,80,97,99,107, + 97,103,101,115,32,97,114,101,32,115,105,109,112,108,121,32, + 109,111,100,117,108,101,115,32,116,104,97,116,32,40,109,97, + 121,41,32,104,97,118,101,32,115,117,98,109,111,100,117,108, + 101,115,46,32,32,73,102,32,97,32,115,112,101,99,10,32, + 32,32,32,104,97,115,32,97,32,110,111,110,45,78,111,110, + 101,32,118,97,108,117,101,32,105,110,32,96,115,117,98,109, + 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, + 97,116,105,111,110,115,96,44,32,116,104,101,32,105,109,112, + 111,114,116,10,32,32,32,32,115,121,115,116,101,109,32,119, + 105,108,108,32,99,111,110,115,105,100,101,114,32,109,111,100, + 117,108,101,115,32,108,111,97,100,101,100,32,102,114,111,109, + 32,116,104,101,32,115,112,101,99,32,97,115,32,112,97,99, + 107,97,103,101,115,46,10,10,32,32,32,32,79,110,108,121, + 32,102,105,110,100,101,114,115,32,40,115,101,101,32,105,109, + 112,111,114,116,108,105,98,46,97,98,99,46,77,101,116,97, + 80,97,116,104,70,105,110,100,101,114,32,97,110,100,10,32, + 32,32,32,105,109,112,111,114,116,108,105,98,46,97,98,99, + 46,80,97,116,104,69,110,116,114,121,70,105,110,100,101,114, + 41,32,115,104,111,117,108,100,32,109,111,100,105,102,121,32, + 77,111,100,117,108,101,83,112,101,99,32,105,110,115,116,97, + 110,99,101,115,46,10,10,32,32,32,32,78,41,3,218,6, + 111,114,105,103,105,110,218,12,108,111,97,100,101,114,95,115, + 116,97,116,101,218,10,105,115,95,112,97,99,107,97,103,101, + 99,3,0,0,0,0,0,0,0,3,0,0,0,6,0,0, + 0,2,0,0,0,67,0,0,0,115,54,0,0,0,124,1, + 124,0,95,0,124,2,124,0,95,1,124,3,124,0,95,2, + 124,4,124,0,95,3,124,5,114,16,103,0,110,1,100,0, + 124,0,95,4,100,1,124,0,95,5,100,0,124,0,95,6, + 100,0,83,0,41,2,78,70,41,7,114,20,0,0,0,114, + 122,0,0,0,114,126,0,0,0,114,127,0,0,0,218,26, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,218,13,95,115,101,116, + 95,102,105,108,101,97,116,116,114,218,7,95,99,97,99,104, + 101,100,41,6,114,33,0,0,0,114,20,0,0,0,114,122, + 0,0,0,114,126,0,0,0,114,127,0,0,0,114,128,0, + 0,0,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,114,34,0,0,0,101,1,0,0,115,14,0,0,0,6, + 2,6,1,6,1,6,1,14,1,6,3,10,1,122,19,77, + 111,100,117,108,101,83,112,101,99,46,95,95,105,110,105,116, + 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,6,0,0,0,67,0,0,0,115,102,0,0,0, + 100,1,160,0,124,0,106,1,161,1,100,2,160,0,124,0, + 106,2,161,1,103,2,125,1,124,0,106,3,100,0,117,1, + 114,26,124,1,160,4,100,3,160,0,124,0,106,3,161,1, + 161,1,1,0,124,0,106,5,100,0,117,1,114,40,124,1, + 160,4,100,4,160,0,124,0,106,5,161,1,161,1,1,0, + 100,5,160,0,124,0,106,6,106,7,100,6,160,8,124,1, + 161,1,161,2,83,0,41,7,78,122,9,110,97,109,101,61, + 123,33,114,125,122,11,108,111,97,100,101,114,61,123,33,114, + 125,122,11,111,114,105,103,105,110,61,123,33,114,125,122,29, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,61,123,125,122,6,123, + 125,40,123,125,41,122,2,44,32,41,9,114,50,0,0,0, + 114,20,0,0,0,114,122,0,0,0,114,126,0,0,0,218, + 6,97,112,112,101,110,100,114,129,0,0,0,218,9,95,95, + 99,108,97,115,115,95,95,114,9,0,0,0,218,4,106,111, + 105,110,41,2,114,33,0,0,0,114,62,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,53,0, + 0,0,113,1,0,0,115,20,0,0,0,10,1,10,1,4, + 255,10,2,18,1,10,1,6,1,8,1,4,255,22,2,122, + 19,77,111,100,117,108,101,83,112,101,99,46,95,95,114,101, + 112,114,95,95,99,2,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,8,0,0,0,67,0,0,0,115,102,0, + 0,0,124,0,106,0,125,2,122,36,124,0,106,1,124,1, + 106,1,107,2,111,38,124,0,106,2,124,1,106,2,107,2, + 111,38,124,0,106,3,124,1,106,3,107,2,111,38,124,2, + 124,1,106,0,107,2,111,38,124,0,106,4,124,1,106,4, + 107,2,111,38,124,0,106,5,124,1,106,5,107,2,87,0, + 83,0,4,0,116,6,121,50,1,0,1,0,1,0,116,7, + 6,0,89,0,83,0,119,0,114,0,0,0,0,41,8,114, + 129,0,0,0,114,20,0,0,0,114,122,0,0,0,114,126, + 0,0,0,218,6,99,97,99,104,101,100,218,12,104,97,115, + 95,108,111,99,97,116,105,111,110,114,2,0,0,0,218,14, + 78,111,116,73,109,112,108,101,109,101,110,116,101,100,41,3, + 114,33,0,0,0,90,5,111,116,104,101,114,90,4,115,109, + 115,108,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,218,6,95,95,101,113,95,95,123,1,0,0,115,32,0, + 0,0,6,1,2,1,12,1,10,1,2,255,10,2,2,254, + 8,3,2,253,10,4,2,252,10,5,4,251,12,6,8,1, + 2,255,122,17,77,111,100,117,108,101,83,112,101,99,46,95, + 95,101,113,95,95,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,58, + 0,0,0,124,0,106,0,100,0,117,0,114,26,124,0,106, + 1,100,0,117,1,114,26,124,0,106,2,114,26,116,3,100, + 0,117,0,114,19,116,4,130,1,116,3,160,5,124,0,106, + 1,161,1,124,0,95,0,124,0,106,0,83,0,114,0,0, + 0,0,41,6,114,131,0,0,0,114,126,0,0,0,114,130, + 0,0,0,218,19,95,98,111,111,116,115,116,114,97,112,95, + 101,120,116,101,114,110,97,108,218,19,78,111,116,73,109,112, + 108,101,109,101,110,116,101,100,69,114,114,111,114,90,11,95, + 103,101,116,95,99,97,99,104,101,100,114,52,0,0,0,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,135, + 0,0,0,135,1,0,0,115,12,0,0,0,10,2,16,1, + 8,1,4,1,14,1,6,1,122,17,77,111,100,117,108,101, + 83,112,101,99,46,99,97,99,104,101,100,99,2,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, + 67,0,0,0,115,10,0,0,0,124,1,124,0,95,0,100, + 0,83,0,114,0,0,0,0,41,1,114,131,0,0,0,41, + 2,114,33,0,0,0,114,135,0,0,0,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,114,135,0,0,0,144, + 1,0,0,115,2,0,0,0,10,2,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,32,0,0,0,124,0,106,0,100,1,117,0, + 114,13,124,0,106,1,160,2,100,2,161,1,100,3,25,0, + 83,0,124,0,106,1,83,0,41,4,122,32,84,104,101,32, + 110,97,109,101,32,111,102,32,116,104,101,32,109,111,100,117, + 108,101,39,115,32,112,97,114,101,110,116,46,78,218,1,46, + 114,25,0,0,0,41,3,114,129,0,0,0,114,20,0,0, + 0,218,10,114,112,97,114,116,105,116,105,111,110,114,52,0, + 0,0,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,218,6,112,97,114,101,110,116,148,1,0,0,115,6,0, + 0,0,10,3,16,1,6,2,122,17,77,111,100,117,108,101, + 83,112,101,99,46,112,97,114,101,110,116,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0, + 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,114, + 0,0,0,0,41,1,114,130,0,0,0,114,52,0,0,0, + 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,114, + 136,0,0,0,156,1,0,0,115,2,0,0,0,6,2,122, + 23,77,111,100,117,108,101,83,112,101,99,46,104,97,115,95, + 108,111,99,97,116,105,111,110,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, + 0,115,14,0,0,0,116,0,124,1,131,1,124,0,95,1, + 100,0,83,0,114,0,0,0,0,41,2,218,4,98,111,111, + 108,114,130,0,0,0,41,2,114,33,0,0,0,218,5,118, + 97,108,117,101,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,114,136,0,0,0,160,1,0,0,115,2,0,0, + 0,14,2,41,12,114,9,0,0,0,114,8,0,0,0,114, + 1,0,0,0,114,10,0,0,0,114,34,0,0,0,114,53, + 0,0,0,114,138,0,0,0,218,8,112,114,111,112,101,114, + 116,121,114,135,0,0,0,218,6,115,101,116,116,101,114,114, + 143,0,0,0,114,136,0,0,0,114,5,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,125,0, + 0,0,64,1,0,0,115,34,0,0,0,8,0,4,1,4, + 36,2,1,12,255,8,12,8,10,2,12,10,1,4,8,10, + 1,2,3,10,1,2,7,10,1,4,3,14,1,114,125,0, + 0,0,169,2,114,126,0,0,0,114,128,0,0,0,99,2, + 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,8, + 0,0,0,67,0,0,0,115,150,0,0,0,116,0,124,1, + 100,1,131,2,114,37,116,1,100,2,117,0,114,11,116,2, + 130,1,116,1,106,3,125,4,124,3,100,2,117,0,114,24, + 124,4,124,0,124,1,100,3,141,2,83,0,124,3,114,28, + 103,0,110,1,100,2,125,5,124,4,124,0,124,1,124,5, + 100,4,141,3,83,0,124,3,100,2,117,0,114,67,116,0, + 124,1,100,5,131,2,114,65,122,7,124,1,160,4,124,0, + 161,1,125,3,87,0,113,67,4,0,116,5,121,64,1,0, + 1,0,1,0,100,2,125,3,89,0,113,67,119,0,100,6, + 125,3,116,6,124,0,124,1,124,2,124,3,100,7,141,4, + 83,0,41,8,122,53,82,101,116,117,114,110,32,97,32,109, + 111,100,117,108,101,32,115,112,101,99,32,98,97,115,101,100, + 32,111,110,32,118,97,114,105,111,117,115,32,108,111,97,100, + 101,114,32,109,101,116,104,111,100,115,46,90,12,103,101,116, + 95,102,105,108,101,110,97,109,101,78,41,1,114,122,0,0, + 0,41,2,114,122,0,0,0,114,129,0,0,0,114,128,0, + 0,0,70,114,148,0,0,0,41,7,114,11,0,0,0,114, + 139,0,0,0,114,140,0,0,0,218,23,115,112,101,99,95, + 102,114,111,109,95,102,105,108,101,95,108,111,99,97,116,105, + 111,110,114,128,0,0,0,114,87,0,0,0,114,125,0,0, + 0,41,6,114,20,0,0,0,114,122,0,0,0,114,126,0, + 0,0,114,128,0,0,0,114,149,0,0,0,90,6,115,101, + 97,114,99,104,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,114,104,0,0,0,165,1,0,0,115,38,0,0, + 0,10,2,8,1,4,1,6,1,8,2,12,1,12,1,6, + 1,2,1,6,255,8,3,10,1,2,1,14,1,12,1,8, + 1,2,255,4,4,16,2,114,104,0,0,0,99,3,0,0, + 0,0,0,0,0,0,0,0,0,8,0,0,0,8,0,0, + 0,67,0,0,0,115,38,1,0,0,122,5,124,0,106,0, + 125,3,87,0,110,9,4,0,116,1,121,14,1,0,1,0, + 1,0,89,0,110,7,119,0,124,3,100,0,117,1,114,21, + 124,3,83,0,124,0,106,2,125,4,124,1,100,0,117,0, + 114,43,122,5,124,0,106,3,125,1,87,0,110,9,4,0, + 116,1,121,42,1,0,1,0,1,0,89,0,110,1,119,0, + 122,5,124,0,106,4,125,5,87,0,110,11,4,0,116,1, + 121,59,1,0,1,0,1,0,100,0,125,5,89,0,110,1, + 119,0,124,2,100,0,117,0,114,87,124,5,100,0,117,0, + 114,85,122,5,124,1,106,5,125,2,87,0,113,87,4,0, + 116,1,121,84,1,0,1,0,1,0,100,0,125,2,89,0, + 113,87,119,0,124,5,125,2,122,5,124,0,106,6,125,6, + 87,0,110,11,4,0,116,1,121,103,1,0,1,0,1,0, + 100,0,125,6,89,0,110,1,119,0,122,7,116,7,124,0, + 106,8,131,1,125,7,87,0,110,11,4,0,116,1,121,122, + 1,0,1,0,1,0,100,0,125,7,89,0,110,1,119,0, + 116,9,124,4,124,1,124,2,100,1,141,3,125,3,124,5, + 100,0,117,0,114,136,100,2,110,1,100,3,124,3,95,10, + 124,6,124,3,95,11,124,7,124,3,95,12,124,3,83,0, 41,4,78,169,1,114,126,0,0,0,70,84,41,13,114,113, 0,0,0,114,2,0,0,0,114,9,0,0,0,114,112,0, 0,0,114,121,0,0,0,218,7,95,79,82,73,71,73,78, @@ -829,239 +834,240 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 5,0,0,0,114,5,0,0,0,114,6,0,0,0,218,17, 95,115,112,101,99,95,102,114,111,109,95,109,111,100,117,108, 101,191,1,0,0,115,84,0,0,0,2,2,10,1,12,1, - 4,1,8,2,4,1,6,2,8,1,2,1,10,1,12,1, - 2,2,2,1,10,1,12,1,6,1,8,1,8,1,2,1, - 10,1,12,1,8,1,4,2,2,1,10,1,12,1,6,1, - 2,1,14,1,12,1,6,1,14,2,18,1,6,1,6,1, - 4,1,2,249,2,252,2,250,2,250,2,251,2,246,114,155, + 4,1,2,255,8,3,4,1,6,2,8,1,2,1,10,1, + 12,1,4,2,2,254,2,3,10,1,12,1,8,1,2,255, + 8,2,8,1,2,1,10,1,12,1,8,1,2,255,4,3, + 2,1,10,1,12,1,8,1,2,255,2,2,14,1,12,1, + 8,1,2,255,14,3,18,1,6,1,6,1,4,1,114,155, 0,0,0,70,169,1,218,8,111,118,101,114,114,105,100,101, 99,2,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,8,0,0,0,67,0,0,0,115,178,1,0,0,124,2, + 0,8,0,0,0,67,0,0,0,115,190,1,0,0,124,2, 115,10,116,0,124,1,100,1,100,0,131,3,100,0,117,0, - 114,24,122,6,124,0,106,1,124,1,95,2,87,0,110,7, - 4,0,116,3,121,216,1,0,1,0,1,0,89,0,124,2, - 115,34,116,0,124,1,100,2,100,0,131,3,100,0,117,0, - 114,83,124,0,106,4,125,3,124,3,100,0,117,0,114,70, - 124,0,106,5,100,0,117,1,114,70,116,6,100,0,117,0, - 114,52,116,7,130,1,116,6,106,8,125,4,124,4,160,9, - 124,4,161,1,125,3,124,0,106,5,124,3,95,10,124,3, - 124,0,95,4,100,0,124,1,95,11,122,5,124,3,124,1, - 95,12,87,0,110,7,4,0,116,3,121,215,1,0,1,0, - 1,0,89,0,124,2,115,93,116,0,124,1,100,3,100,0, - 131,3,100,0,117,0,114,107,122,6,124,0,106,13,124,1, - 95,14,87,0,110,7,4,0,116,3,121,214,1,0,1,0, - 1,0,89,0,122,5,124,0,124,1,95,15,87,0,110,7, - 4,0,116,3,121,213,1,0,1,0,1,0,89,0,124,2, - 115,130,116,0,124,1,100,4,100,0,131,3,100,0,117,0, - 114,149,124,0,106,5,100,0,117,1,114,149,122,6,124,0, - 106,5,124,1,95,16,87,0,110,7,4,0,116,3,121,212, - 1,0,1,0,1,0,89,0,124,0,106,17,114,208,124,2, - 115,162,116,0,124,1,100,5,100,0,131,3,100,0,117,0, - 114,176,122,6,124,0,106,18,124,1,95,11,87,0,110,7, - 4,0,116,3,121,211,1,0,1,0,1,0,89,0,124,2, - 115,186,116,0,124,1,100,6,100,0,131,3,100,0,117,0, - 114,208,124,0,106,19,100,0,117,1,114,208,122,7,124,0, - 106,19,124,1,95,20,87,0,124,1,83,0,4,0,116,3, - 121,210,1,0,1,0,1,0,89,0,124,1,83,0,124,1, - 83,0,119,0,119,0,119,0,119,0,119,0,119,0,119,0, - 41,7,78,114,9,0,0,0,114,112,0,0,0,218,11,95, - 95,112,97,99,107,97,103,101,95,95,114,154,0,0,0,114, - 121,0,0,0,114,152,0,0,0,41,21,114,13,0,0,0, - 114,20,0,0,0,114,9,0,0,0,114,2,0,0,0,114, - 122,0,0,0,114,129,0,0,0,114,139,0,0,0,114,140, - 0,0,0,218,16,95,78,97,109,101,115,112,97,99,101,76, - 111,97,100,101,114,218,7,95,95,110,101,119,95,95,90,5, - 95,112,97,116,104,114,121,0,0,0,114,112,0,0,0,114, - 143,0,0,0,114,158,0,0,0,114,113,0,0,0,114,154, - 0,0,0,114,136,0,0,0,114,126,0,0,0,114,135,0, - 0,0,114,152,0,0,0,41,5,114,109,0,0,0,114,110, - 0,0,0,114,157,0,0,0,114,122,0,0,0,114,159,0, + 114,26,122,6,124,0,106,1,124,1,95,2,87,0,110,9, + 4,0,116,3,121,25,1,0,1,0,1,0,89,0,110,1, + 119,0,124,2,115,36,116,0,124,1,100,2,100,0,131,3, + 100,0,117,0,114,87,124,0,106,4,125,3,124,3,100,0, + 117,0,114,72,124,0,106,5,100,0,117,1,114,72,116,6, + 100,0,117,0,114,54,116,7,130,1,116,6,106,8,125,4, + 124,4,160,9,124,4,161,1,125,3,124,0,106,5,124,3, + 95,10,124,3,124,0,95,4,100,0,124,1,95,11,122,5, + 124,3,124,1,95,12,87,0,110,9,4,0,116,3,121,86, + 1,0,1,0,1,0,89,0,110,1,119,0,124,2,115,97, + 116,0,124,1,100,3,100,0,131,3,100,0,117,0,114,113, + 122,6,124,0,106,13,124,1,95,14,87,0,110,9,4,0, + 116,3,121,112,1,0,1,0,1,0,89,0,110,1,119,0, + 122,5,124,0,124,1,95,15,87,0,110,9,4,0,116,3, + 121,127,1,0,1,0,1,0,89,0,110,1,119,0,124,2, + 115,138,116,0,124,1,100,4,100,0,131,3,100,0,117,0, + 114,159,124,0,106,5,100,0,117,1,114,159,122,6,124,0, + 106,5,124,1,95,16,87,0,110,9,4,0,116,3,121,158, + 1,0,1,0,1,0,89,0,110,1,119,0,124,0,106,17, + 114,221,124,2,115,172,116,0,124,1,100,5,100,0,131,3, + 100,0,117,0,114,188,122,6,124,0,106,18,124,1,95,11, + 87,0,110,9,4,0,116,3,121,187,1,0,1,0,1,0, + 89,0,110,1,119,0,124,2,115,198,116,0,124,1,100,6, + 100,0,131,3,100,0,117,0,114,221,124,0,106,19,100,0, + 117,1,114,221,122,7,124,0,106,19,124,1,95,20,87,0, + 124,1,83,0,4,0,116,3,121,220,1,0,1,0,1,0, + 89,0,124,1,83,0,119,0,124,1,83,0,41,7,78,114, + 9,0,0,0,114,112,0,0,0,218,11,95,95,112,97,99, + 107,97,103,101,95,95,114,154,0,0,0,114,121,0,0,0, + 114,152,0,0,0,41,21,114,13,0,0,0,114,20,0,0, + 0,114,9,0,0,0,114,2,0,0,0,114,122,0,0,0, + 114,129,0,0,0,114,139,0,0,0,114,140,0,0,0,218, + 16,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, + 114,218,7,95,95,110,101,119,95,95,90,5,95,112,97,116, + 104,114,121,0,0,0,114,112,0,0,0,114,143,0,0,0, + 114,158,0,0,0,114,113,0,0,0,114,154,0,0,0,114, + 136,0,0,0,114,126,0,0,0,114,135,0,0,0,114,152, + 0,0,0,41,5,114,109,0,0,0,114,110,0,0,0,114, + 157,0,0,0,114,122,0,0,0,114,159,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,218,18,95, + 105,110,105,116,95,109,111,100,117,108,101,95,97,116,116,114, + 115,236,1,0,0,115,114,0,0,0,20,4,2,1,12,1, + 12,1,4,1,2,255,20,3,6,1,8,1,10,2,8,1, + 4,1,6,1,10,2,8,1,6,1,6,11,2,1,10,1, + 12,1,4,1,2,255,20,3,2,1,12,1,12,1,4,1, + 2,255,2,3,10,1,12,1,4,1,2,255,20,3,10,1, + 2,1,12,1,12,1,4,1,2,255,6,3,20,1,2,1, + 12,1,12,1,4,1,2,255,20,3,10,1,2,1,10,1, + 4,3,12,254,2,1,4,1,2,254,4,2,114,161,0,0, + 0,99,1,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,67,0,0,0,115,82,0,0,0,100, + 1,125,1,116,0,124,0,106,1,100,2,131,2,114,15,124, + 0,106,1,160,2,124,0,161,1,125,1,110,10,116,0,124, + 0,106,1,100,3,131,2,114,25,116,3,100,4,131,1,130, + 1,124,1,100,1,117,0,114,34,116,4,124,0,106,5,131, + 1,125,1,116,6,124,0,124,1,131,2,1,0,124,1,83, + 0,41,5,122,43,67,114,101,97,116,101,32,97,32,109,111, + 100,117,108,101,32,98,97,115,101,100,32,111,110,32,116,104, + 101,32,112,114,111,118,105,100,101,100,32,115,112,101,99,46, + 78,218,13,99,114,101,97,116,101,95,109,111,100,117,108,101, + 218,11,101,120,101,99,95,109,111,100,117,108,101,122,66,108, + 111,97,100,101,114,115,32,116,104,97,116,32,100,101,102,105, + 110,101,32,101,120,101,99,95,109,111,100,117,108,101,40,41, + 32,109,117,115,116,32,97,108,115,111,32,100,101,102,105,110, + 101,32,99,114,101,97,116,101,95,109,111,100,117,108,101,40, + 41,41,7,114,11,0,0,0,114,122,0,0,0,114,162,0, + 0,0,114,87,0,0,0,114,21,0,0,0,114,20,0,0, + 0,114,161,0,0,0,169,2,114,109,0,0,0,114,110,0, 0,0,114,5,0,0,0,114,5,0,0,0,114,6,0,0, - 0,218,18,95,105,110,105,116,95,109,111,100,117,108,101,95, - 97,116,116,114,115,236,1,0,0,115,112,0,0,0,20,4, - 2,1,12,1,12,1,2,1,20,2,6,1,8,1,10,2, - 8,1,4,1,6,1,10,2,8,1,6,1,6,11,2,1, - 10,1,12,1,2,1,20,2,2,1,12,1,12,1,2,1, - 2,2,10,1,12,1,2,1,20,2,10,1,2,1,12,1, - 12,1,2,1,6,2,20,1,2,1,12,1,12,1,2,1, - 20,2,10,1,2,1,10,1,4,3,12,254,2,1,8,1, - 2,254,2,249,2,249,2,249,2,251,2,250,2,228,114,161, + 0,218,16,109,111,100,117,108,101,95,102,114,111,109,95,115, + 112,101,99,52,2,0,0,115,18,0,0,0,4,3,12,1, + 14,3,12,1,8,1,8,2,10,1,10,1,4,1,114,165, 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,82,0,0, - 0,100,1,125,1,116,0,124,0,106,1,100,2,131,2,114, - 15,124,0,106,1,160,2,124,0,161,1,125,1,110,10,116, - 0,124,0,106,1,100,3,131,2,114,25,116,3,100,4,131, - 1,130,1,124,1,100,1,117,0,114,34,116,4,124,0,106, - 5,131,1,125,1,116,6,124,0,124,1,131,2,1,0,124, - 1,83,0,41,5,122,43,67,114,101,97,116,101,32,97,32, - 109,111,100,117,108,101,32,98,97,115,101,100,32,111,110,32, - 116,104,101,32,112,114,111,118,105,100,101,100,32,115,112,101, - 99,46,78,218,13,99,114,101,97,116,101,95,109,111,100,117, - 108,101,218,11,101,120,101,99,95,109,111,100,117,108,101,122, - 66,108,111,97,100,101,114,115,32,116,104,97,116,32,100,101, - 102,105,110,101,32,101,120,101,99,95,109,111,100,117,108,101, - 40,41,32,109,117,115,116,32,97,108,115,111,32,100,101,102, - 105,110,101,32,99,114,101,97,116,101,95,109,111,100,117,108, - 101,40,41,41,7,114,11,0,0,0,114,122,0,0,0,114, - 162,0,0,0,114,87,0,0,0,114,21,0,0,0,114,20, - 0,0,0,114,161,0,0,0,169,2,114,109,0,0,0,114, - 110,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,16,109,111,100,117,108,101,95,102,114,111,109, - 95,115,112,101,99,52,2,0,0,115,18,0,0,0,4,3, - 12,1,14,3,12,1,8,1,8,2,10,1,10,1,4,1, - 114,165,0,0,0,99,1,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,4,0,0,0,67,0,0,0,115,100, - 0,0,0,124,0,106,0,100,1,117,0,114,7,100,2,110, - 2,124,0,106,0,125,1,124,0,106,1,100,1,117,0,114, - 32,124,0,106,2,100,1,117,0,114,25,100,3,160,3,124, - 1,161,1,83,0,100,4,160,3,124,1,124,0,106,2,161, - 2,83,0,124,0,106,4,114,42,100,5,160,3,124,1,124, - 0,106,1,161,2,83,0,100,6,160,3,124,0,106,0,124, - 0,106,1,161,2,83,0,41,7,122,38,82,101,116,117,114, - 110,32,116,104,101,32,114,101,112,114,32,116,111,32,117,115, - 101,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, - 46,78,114,115,0,0,0,114,116,0,0,0,114,117,0,0, - 0,114,118,0,0,0,250,18,60,109,111,100,117,108,101,32, - 123,33,114,125,32,40,123,125,41,62,41,5,114,20,0,0, - 0,114,126,0,0,0,114,122,0,0,0,114,50,0,0,0, - 114,136,0,0,0,41,2,114,109,0,0,0,114,20,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, - 114,119,0,0,0,69,2,0,0,115,16,0,0,0,20,3, - 10,1,10,1,10,1,14,2,6,2,14,1,16,2,114,119, - 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, - 4,0,0,0,10,0,0,0,67,0,0,0,115,24,1,0, - 0,124,0,106,0,125,2,116,1,124,2,131,1,143,123,1, - 0,116,2,106,3,160,4,124,2,161,1,124,1,117,1,114, - 27,100,1,160,5,124,2,161,1,125,3,116,6,124,3,124, - 2,100,2,141,2,130,1,122,80,124,0,106,7,100,3,117, - 0,114,53,124,0,106,8,100,3,117,0,114,45,116,6,100, - 4,124,0,106,0,100,2,141,2,130,1,116,9,124,0,124, - 1,100,5,100,6,141,3,1,0,110,40,116,9,124,0,124, - 1,100,5,100,6,141,3,1,0,116,10,124,0,106,7,100, - 7,131,2,115,87,116,11,124,0,106,7,131,1,155,0,100, - 8,157,2,125,3,116,12,160,13,124,3,116,14,161,2,1, - 0,124,0,106,7,160,15,124,2,161,1,1,0,110,6,124, - 0,106,7,160,16,124,1,161,1,1,0,87,0,116,2,106, - 3,160,17,124,0,106,0,161,1,125,1,124,1,116,2,106, - 3,124,0,106,0,60,0,110,14,116,2,106,3,160,17,124, - 0,106,0,161,1,125,1,124,1,116,2,106,3,124,0,106, - 0,60,0,119,0,87,0,100,3,4,0,4,0,131,3,1, - 0,124,1,83,0,49,0,115,133,119,1,1,0,1,0,1, - 0,89,0,1,0,124,1,83,0,41,9,122,70,69,120,101, - 99,117,116,101,32,116,104,101,32,115,112,101,99,39,115,32, - 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, - 32,105,110,32,97,110,32,101,120,105,115,116,105,110,103,32, - 109,111,100,117,108,101,39,115,32,110,97,109,101,115,112,97, - 99,101,46,122,30,109,111,100,117,108,101,32,123,33,114,125, - 32,110,111,116,32,105,110,32,115,121,115,46,109,111,100,117, - 108,101,115,114,19,0,0,0,78,250,14,109,105,115,115,105, - 110,103,32,108,111,97,100,101,114,84,114,156,0,0,0,114, - 163,0,0,0,250,55,46,101,120,101,99,95,109,111,100,117, - 108,101,40,41,32,110,111,116,32,102,111,117,110,100,59,32, - 102,97,108,108,105,110,103,32,98,97,99,107,32,116,111,32, - 108,111,97,100,95,109,111,100,117,108,101,40,41,41,18,114, - 20,0,0,0,114,57,0,0,0,114,18,0,0,0,114,105, - 0,0,0,114,38,0,0,0,114,50,0,0,0,114,87,0, - 0,0,114,122,0,0,0,114,129,0,0,0,114,161,0,0, - 0,114,11,0,0,0,114,7,0,0,0,114,101,0,0,0, - 114,102,0,0,0,218,13,73,109,112,111,114,116,87,97,114, - 110,105,110,103,218,11,108,111,97,100,95,109,111,100,117,108, - 101,114,163,0,0,0,218,3,112,111,112,41,4,114,109,0, - 0,0,114,110,0,0,0,114,20,0,0,0,114,108,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, - 114,106,0,0,0,86,2,0,0,115,50,0,0,0,6,2, - 10,1,16,1,10,1,12,1,2,1,10,1,10,1,14,1, - 16,2,14,2,12,1,16,1,12,2,14,1,12,2,2,128, - 14,4,14,1,14,255,16,1,10,233,4,24,16,232,4,24, - 114,106,0,0,0,99,1,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,8,0,0,0,67,0,0,0,115,10, - 1,0,0,122,9,124,0,106,0,160,1,124,0,106,2,161, - 1,1,0,87,0,110,23,1,0,1,0,1,0,124,0,106, - 2,116,3,106,4,118,0,114,32,116,3,106,4,160,5,124, - 0,106,2,161,1,125,1,124,1,116,3,106,4,124,0,106, - 2,60,0,130,0,116,3,106,4,160,5,124,0,106,2,161, - 1,125,1,124,1,116,3,106,4,124,0,106,2,60,0,116, - 6,124,1,100,1,100,0,131,3,100,0,117,0,114,68,122, - 6,124,0,106,0,124,1,95,7,87,0,110,7,4,0,116, - 8,121,132,1,0,1,0,1,0,89,0,116,6,124,1,100, - 2,100,0,131,3,100,0,117,0,114,104,122,20,124,1,106, - 9,124,1,95,10,116,11,124,1,100,3,131,2,115,95,124, - 0,106,2,160,12,100,4,161,1,100,5,25,0,124,1,95, - 10,87,0,110,7,4,0,116,8,121,131,1,0,1,0,1, - 0,89,0,116,6,124,1,100,6,100,0,131,3,100,0,117, - 0,114,128,122,6,124,0,124,1,95,13,87,0,124,1,83, - 0,4,0,116,8,121,130,1,0,1,0,1,0,89,0,124, - 1,83,0,124,1,83,0,119,0,119,0,119,0,41,7,78, - 114,112,0,0,0,114,158,0,0,0,114,154,0,0,0,114, - 141,0,0,0,114,25,0,0,0,114,113,0,0,0,41,14, - 114,122,0,0,0,114,170,0,0,0,114,20,0,0,0,114, - 18,0,0,0,114,105,0,0,0,114,171,0,0,0,114,13, - 0,0,0,114,112,0,0,0,114,2,0,0,0,114,9,0, - 0,0,114,158,0,0,0,114,11,0,0,0,114,142,0,0, - 0,114,113,0,0,0,114,164,0,0,0,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,218,25,95,108,111,97, - 100,95,98,97,99,107,119,97,114,100,95,99,111,109,112,97, - 116,105,98,108,101,116,2,0,0,115,64,0,0,0,2,3, - 18,1,6,1,12,1,14,1,12,1,2,1,14,3,12,1, - 16,1,2,1,12,1,12,1,2,1,16,1,2,1,8,4, - 10,1,18,1,4,128,12,1,2,1,16,1,2,1,8,1, - 4,3,12,254,2,1,8,1,2,254,2,251,2,246,114,172, + 2,0,0,0,4,0,0,0,67,0,0,0,115,100,0,0, + 0,124,0,106,0,100,1,117,0,114,7,100,2,110,2,124, + 0,106,0,125,1,124,0,106,1,100,1,117,0,114,32,124, + 0,106,2,100,1,117,0,114,25,100,3,160,3,124,1,161, + 1,83,0,100,4,160,3,124,1,124,0,106,2,161,2,83, + 0,124,0,106,4,114,42,100,5,160,3,124,1,124,0,106, + 1,161,2,83,0,100,6,160,3,124,0,106,0,124,0,106, + 1,161,2,83,0,41,7,122,38,82,101,116,117,114,110,32, + 116,104,101,32,114,101,112,114,32,116,111,32,117,115,101,32, + 102,111,114,32,116,104,101,32,109,111,100,117,108,101,46,78, + 114,115,0,0,0,114,116,0,0,0,114,117,0,0,0,114, + 118,0,0,0,250,18,60,109,111,100,117,108,101,32,123,33, + 114,125,32,40,123,125,41,62,41,5,114,20,0,0,0,114, + 126,0,0,0,114,122,0,0,0,114,50,0,0,0,114,136, + 0,0,0,41,2,114,109,0,0,0,114,20,0,0,0,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,119, + 0,0,0,69,2,0,0,115,16,0,0,0,20,3,10,1, + 10,1,10,1,14,2,6,2,14,1,16,2,114,119,0,0, + 0,99,2,0,0,0,0,0,0,0,0,0,0,0,4,0, + 0,0,10,0,0,0,67,0,0,0,115,24,1,0,0,124, + 0,106,0,125,2,116,1,124,2,131,1,143,123,1,0,116, + 2,106,3,160,4,124,2,161,1,124,1,117,1,114,27,100, + 1,160,5,124,2,161,1,125,3,116,6,124,3,124,2,100, + 2,141,2,130,1,122,80,124,0,106,7,100,3,117,0,114, + 53,124,0,106,8,100,3,117,0,114,45,116,6,100,4,124, + 0,106,0,100,2,141,2,130,1,116,9,124,0,124,1,100, + 5,100,6,141,3,1,0,110,40,116,9,124,0,124,1,100, + 5,100,6,141,3,1,0,116,10,124,0,106,7,100,7,131, + 2,115,87,116,11,124,0,106,7,131,1,155,0,100,8,157, + 2,125,3,116,12,160,13,124,3,116,14,161,2,1,0,124, + 0,106,7,160,15,124,2,161,1,1,0,110,6,124,0,106, + 7,160,16,124,1,161,1,1,0,87,0,116,2,106,3,160, + 17,124,0,106,0,161,1,125,1,124,1,116,2,106,3,124, + 0,106,0,60,0,110,14,116,2,106,3,160,17,124,0,106, + 0,161,1,125,1,124,1,116,2,106,3,124,0,106,0,60, + 0,119,0,87,0,100,3,4,0,4,0,131,3,1,0,124, + 1,83,0,49,0,115,133,119,1,1,0,1,0,1,0,89, + 0,1,0,124,1,83,0,41,9,122,70,69,120,101,99,117, + 116,101,32,116,104,101,32,115,112,101,99,39,115,32,115,112, + 101,99,105,102,105,101,100,32,109,111,100,117,108,101,32,105, + 110,32,97,110,32,101,120,105,115,116,105,110,103,32,109,111, + 100,117,108,101,39,115,32,110,97,109,101,115,112,97,99,101, + 46,122,30,109,111,100,117,108,101,32,123,33,114,125,32,110, + 111,116,32,105,110,32,115,121,115,46,109,111,100,117,108,101, + 115,114,19,0,0,0,78,250,14,109,105,115,115,105,110,103, + 32,108,111,97,100,101,114,84,114,156,0,0,0,114,163,0, + 0,0,250,55,46,101,120,101,99,95,109,111,100,117,108,101, + 40,41,32,110,111,116,32,102,111,117,110,100,59,32,102,97, + 108,108,105,110,103,32,98,97,99,107,32,116,111,32,108,111, + 97,100,95,109,111,100,117,108,101,40,41,41,18,114,20,0, + 0,0,114,57,0,0,0,114,18,0,0,0,114,105,0,0, + 0,114,38,0,0,0,114,50,0,0,0,114,87,0,0,0, + 114,122,0,0,0,114,129,0,0,0,114,161,0,0,0,114, + 11,0,0,0,114,7,0,0,0,114,101,0,0,0,114,102, + 0,0,0,218,13,73,109,112,111,114,116,87,97,114,110,105, + 110,103,218,11,108,111,97,100,95,109,111,100,117,108,101,114, + 163,0,0,0,218,3,112,111,112,41,4,114,109,0,0,0, + 114,110,0,0,0,114,20,0,0,0,114,108,0,0,0,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,106, + 0,0,0,86,2,0,0,115,50,0,0,0,6,2,10,1, + 16,1,10,1,12,1,2,1,10,1,10,1,14,1,16,2, + 14,2,12,1,16,1,12,2,14,1,12,2,2,128,14,4, + 14,1,14,255,16,1,10,233,4,24,16,232,4,24,114,106, 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,11,0,0,0,67,0,0,0,115,242,0,0, - 0,124,0,106,0,100,0,117,1,114,29,116,1,124,0,106, - 0,100,1,131,2,115,29,116,2,124,0,106,0,131,1,155, - 0,100,2,157,2,125,1,116,3,160,4,124,1,116,5,161, - 2,1,0,116,6,124,0,131,1,83,0,116,7,124,0,131, - 1,125,2,100,3,124,0,95,8,122,79,124,2,116,9,106, - 10,124,0,106,11,60,0,122,26,124,0,106,0,100,0,117, - 0,114,62,124,0,106,12,100,0,117,0,114,61,116,13,100, - 4,124,0,106,11,100,5,141,2,130,1,110,6,124,0,106, - 0,160,14,124,2,161,1,1,0,87,0,110,19,1,0,1, - 0,1,0,122,7,116,9,106,10,124,0,106,11,61,0,87, - 0,130,0,4,0,116,15,121,120,1,0,1,0,1,0,89, - 0,130,0,116,9,106,10,160,16,124,0,106,11,161,1,125, - 2,124,2,116,9,106,10,124,0,106,11,60,0,116,17,100, - 6,124,0,106,11,124,0,106,0,131,3,1,0,87,0,100, - 7,124,0,95,8,124,2,83,0,100,7,124,0,95,8,119, - 0,119,0,41,8,78,114,163,0,0,0,114,168,0,0,0, - 84,114,167,0,0,0,114,19,0,0,0,122,18,105,109,112, - 111,114,116,32,123,33,114,125,32,35,32,123,33,114,125,70, - 41,18,114,122,0,0,0,114,11,0,0,0,114,7,0,0, - 0,114,101,0,0,0,114,102,0,0,0,114,169,0,0,0, - 114,172,0,0,0,114,165,0,0,0,90,13,95,105,110,105, - 116,105,97,108,105,122,105,110,103,114,18,0,0,0,114,105, - 0,0,0,114,20,0,0,0,114,129,0,0,0,114,87,0, - 0,0,114,163,0,0,0,114,70,0,0,0,114,171,0,0, - 0,114,83,0,0,0,41,3,114,109,0,0,0,114,108,0, - 0,0,114,110,0,0,0,114,5,0,0,0,114,5,0,0, - 0,114,6,0,0,0,218,14,95,108,111,97,100,95,117,110, - 108,111,99,107,101,100,152,2,0,0,115,60,0,0,0,10, - 2,12,2,16,1,12,2,8,1,8,2,6,5,2,1,12, - 1,2,1,10,1,10,1,14,1,2,255,12,4,4,128,6, - 1,2,1,12,1,2,3,12,254,2,1,2,1,14,5,12, - 1,18,1,6,2,4,2,8,254,2,245,114,173,0,0,0, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,8,0,0,0,67,0,0,0,115,54,0,0,0,116,0, - 124,0,106,1,131,1,143,12,1,0,116,2,124,0,131,1, - 87,0,2,0,100,1,4,0,4,0,131,3,1,0,83,0, - 49,0,115,20,119,1,1,0,1,0,1,0,89,0,1,0, - 100,1,83,0,41,2,122,191,82,101,116,117,114,110,32,97, - 32,110,101,119,32,109,111,100,117,108,101,32,111,98,106,101, - 99,116,44,32,108,111,97,100,101,100,32,98,121,32,116,104, - 101,32,115,112,101,99,39,115,32,108,111,97,100,101,114,46, - 10,10,32,32,32,32,84,104,101,32,109,111,100,117,108,101, - 32,105,115,32,110,111,116,32,97,100,100,101,100,32,116,111, - 32,105,116,115,32,112,97,114,101,110,116,46,10,10,32,32, - 32,32,73,102,32,97,32,109,111,100,117,108,101,32,105,115, - 32,97,108,114,101,97,100,121,32,105,110,32,115,121,115,46, - 109,111,100,117,108,101,115,44,32,116,104,97,116,32,101,120, - 105,115,116,105,110,103,32,109,111,100,117,108,101,32,103,101, - 116,115,10,32,32,32,32,99,108,111,98,98,101,114,101,100, - 46,10,10,32,32,32,32,78,41,3,114,57,0,0,0,114, - 20,0,0,0,114,173,0,0,0,169,1,114,109,0,0,0, - 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,114, - 107,0,0,0,197,2,0,0,115,10,0,0,0,12,9,6, - 1,14,255,2,1,20,255,114,107,0,0,0,99,0,0,0, + 2,0,0,0,8,0,0,0,67,0,0,0,115,14,1,0, + 0,122,9,124,0,106,0,160,1,124,0,106,2,161,1,1, + 0,87,0,110,23,1,0,1,0,1,0,124,0,106,2,116, + 3,106,4,118,0,114,32,116,3,106,4,160,5,124,0,106, + 2,161,1,125,1,124,1,116,3,106,4,124,0,106,2,60, + 0,130,0,116,3,106,4,160,5,124,0,106,2,161,1,125, + 1,124,1,116,3,106,4,124,0,106,2,60,0,116,6,124, + 1,100,1,100,0,131,3,100,0,117,0,114,70,122,6,124, + 0,106,0,124,1,95,7,87,0,110,9,4,0,116,8,121, + 69,1,0,1,0,1,0,89,0,110,1,119,0,116,6,124, + 1,100,2,100,0,131,3,100,0,117,0,114,108,122,20,124, + 1,106,9,124,1,95,10,116,11,124,1,100,3,131,2,115, + 97,124,0,106,2,160,12,100,4,161,1,100,5,25,0,124, + 1,95,10,87,0,110,9,4,0,116,8,121,107,1,0,1, + 0,1,0,89,0,110,1,119,0,116,6,124,1,100,6,100, + 0,131,3,100,0,117,0,114,133,122,6,124,0,124,1,95, + 13,87,0,124,1,83,0,4,0,116,8,121,132,1,0,1, + 0,1,0,89,0,124,1,83,0,119,0,124,1,83,0,41, + 7,78,114,112,0,0,0,114,158,0,0,0,114,154,0,0, + 0,114,141,0,0,0,114,25,0,0,0,114,113,0,0,0, + 41,14,114,122,0,0,0,114,170,0,0,0,114,20,0,0, + 0,114,18,0,0,0,114,105,0,0,0,114,171,0,0,0, + 114,13,0,0,0,114,112,0,0,0,114,2,0,0,0,114, + 9,0,0,0,114,158,0,0,0,114,11,0,0,0,114,142, + 0,0,0,114,113,0,0,0,114,164,0,0,0,114,5,0, + 0,0,114,5,0,0,0,114,6,0,0,0,218,25,95,108, + 111,97,100,95,98,97,99,107,119,97,114,100,95,99,111,109, + 112,97,116,105,98,108,101,116,2,0,0,115,66,0,0,0, + 2,3,18,1,6,1,12,1,14,1,12,1,2,1,14,3, + 12,1,16,1,2,1,12,1,12,1,4,1,2,255,16,2, + 2,1,8,4,10,1,18,1,4,128,12,1,4,1,2,255, + 16,2,2,1,8,1,4,3,12,254,2,1,4,1,2,254, + 4,2,114,172,0,0,0,99,1,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,11,0,0,0,67,0,0,0, + 115,242,0,0,0,124,0,106,0,100,0,117,1,114,29,116, + 1,124,0,106,0,100,1,131,2,115,29,116,2,124,0,106, + 0,131,1,155,0,100,2,157,2,125,1,116,3,160,4,124, + 1,116,5,161,2,1,0,116,6,124,0,131,1,83,0,116, + 7,124,0,131,1,125,2,100,3,124,0,95,8,122,80,124, + 2,116,9,106,10,124,0,106,11,60,0,122,26,124,0,106, + 0,100,0,117,0,114,62,124,0,106,12,100,0,117,0,114, + 61,116,13,100,4,124,0,106,11,100,5,141,2,130,1,110, + 6,124,0,106,0,160,14,124,2,161,1,1,0,87,0,110, + 20,1,0,1,0,1,0,122,7,116,9,106,10,124,0,106, + 11,61,0,87,0,130,0,4,0,116,15,121,89,1,0,1, + 0,1,0,89,0,130,0,119,0,116,9,106,10,160,16,124, + 0,106,11,161,1,125,2,124,2,116,9,106,10,124,0,106, + 11,60,0,116,17,100,6,124,0,106,11,124,0,106,0,131, + 3,1,0,87,0,100,7,124,0,95,8,124,2,83,0,100, + 7,124,0,95,8,119,0,41,8,78,114,163,0,0,0,114, + 168,0,0,0,84,114,167,0,0,0,114,19,0,0,0,122, + 18,105,109,112,111,114,116,32,123,33,114,125,32,35,32,123, + 33,114,125,70,41,18,114,122,0,0,0,114,11,0,0,0, + 114,7,0,0,0,114,101,0,0,0,114,102,0,0,0,114, + 169,0,0,0,114,172,0,0,0,114,165,0,0,0,90,13, + 95,105,110,105,116,105,97,108,105,122,105,110,103,114,18,0, + 0,0,114,105,0,0,0,114,20,0,0,0,114,129,0,0, + 0,114,87,0,0,0,114,163,0,0,0,114,70,0,0,0, + 114,171,0,0,0,114,83,0,0,0,41,3,114,109,0,0, + 0,114,108,0,0,0,114,110,0,0,0,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,14,95,108,111,97, + 100,95,117,110,108,111,99,107,101,100,152,2,0,0,115,60, + 0,0,0,10,2,12,2,16,1,12,2,8,1,8,2,6, + 5,2,1,12,1,2,1,10,1,10,1,14,1,2,255,12, + 4,4,128,6,1,2,1,12,1,2,3,12,254,2,1,2, + 1,2,254,14,7,12,1,18,1,6,2,4,2,8,254,114, + 173,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,8,0,0,0,67,0,0,0,115,54,0, + 0,0,116,0,124,0,106,1,131,1,143,12,1,0,116,2, + 124,0,131,1,87,0,2,0,100,1,4,0,4,0,131,3, + 1,0,83,0,49,0,115,20,119,1,1,0,1,0,1,0, + 89,0,1,0,100,1,83,0,41,2,122,191,82,101,116,117, + 114,110,32,97,32,110,101,119,32,109,111,100,117,108,101,32, + 111,98,106,101,99,116,44,32,108,111,97,100,101,100,32,98, + 121,32,116,104,101,32,115,112,101,99,39,115,32,108,111,97, + 100,101,114,46,10,10,32,32,32,32,84,104,101,32,109,111, + 100,117,108,101,32,105,115,32,110,111,116,32,97,100,100,101, + 100,32,116,111,32,105,116,115,32,112,97,114,101,110,116,46, + 10,10,32,32,32,32,73,102,32,97,32,109,111,100,117,108, + 101,32,105,115,32,97,108,114,101,97,100,121,32,105,110,32, + 115,121,115,46,109,111,100,117,108,101,115,44,32,116,104,97, + 116,32,101,120,105,115,116,105,110,103,32,109,111,100,117,108, + 101,32,103,101,116,115,10,32,32,32,32,99,108,111,98,98, + 101,114,101,100,46,10,10,32,32,32,32,78,41,3,114,57, + 0,0,0,114,20,0,0,0,114,173,0,0,0,169,1,114, + 109,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,114,107,0,0,0,197,2,0,0,115,6,0,0, + 0,12,9,6,1,36,255,114,107,0,0,0,99,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,64,0,0,0,115,140,0,0,0,101,0,90,1,100,0, 90,2,100,1,90,3,100,2,90,4,101,5,100,3,100,4, @@ -1087,7 +1093,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,1,0,0,0,5,0,0,0,67,0,0,0,115,34, 0,0,0,116,0,160,1,100,1,116,2,161,2,1,0,100, 2,124,0,106,3,155,2,100,3,116,4,106,5,155,0,100, - 4,157,5,83,0,41,6,250,115,82,101,116,117,114,110,32, + 4,157,5,83,0,41,5,250,115,82,101,116,117,114,110,32, 114,101,112,114,32,102,111,114,32,116,104,101,32,109,111,100, 117,108,101,46,10,10,32,32,32,32,32,32,32,32,84,104, 101,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, @@ -1101,779 +1107,779 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 97,116,101,100,32,102,111,114,32,114,101,109,111,118,97,108, 32,105,110,32,80,121,116,104,111,110,32,51,46,49,50,122, 8,60,109,111,100,117,108,101,32,122,2,32,40,122,2,41, - 62,78,41,6,114,101,0,0,0,114,102,0,0,0,114,103, - 0,0,0,114,9,0,0,0,114,175,0,0,0,114,151,0, - 0,0,169,1,114,110,0,0,0,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,114,114,0,0,0,223,2,0, - 0,115,8,0,0,0,6,7,2,1,4,255,22,2,122,27, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, - 109,111,100,117,108,101,95,114,101,112,114,78,99,4,0,0, - 0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0, - 0,67,0,0,0,115,42,0,0,0,124,2,100,0,117,1, - 114,6,100,0,83,0,116,0,160,1,124,1,161,1,114,19, - 116,2,124,1,124,0,124,0,106,3,100,1,141,3,83,0, - 100,0,83,0,169,2,78,114,150,0,0,0,41,4,114,64, - 0,0,0,90,10,105,115,95,98,117,105,108,116,105,110,114, - 104,0,0,0,114,151,0,0,0,169,4,218,3,99,108,115, - 114,89,0,0,0,218,4,112,97,116,104,218,6,116,97,114, - 103,101,116,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,218,9,102,105,110,100,95,115,112,101,99,234,2,0, - 0,115,10,0,0,0,8,2,4,1,10,1,16,1,4,2, - 122,25,66,117,105,108,116,105,110,73,109,112,111,114,116,101, - 114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,0, - 0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,42,0,0,0,116,0,160,1,100,1,116, - 2,161,2,1,0,124,0,160,3,124,1,124,2,161,2,125, - 3,124,3,100,2,117,1,114,19,124,3,106,4,83,0,100, - 2,83,0,41,3,122,175,70,105,110,100,32,116,104,101,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,73,102,32,39,112,97, - 116,104,39,32,105,115,32,101,118,101,114,32,115,112,101,99, - 105,102,105,101,100,32,116,104,101,110,32,116,104,101,32,115, - 101,97,114,99,104,32,105,115,32,99,111,110,115,105,100,101, - 114,101,100,32,97,32,102,97,105,108,117,114,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,122,106,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,46,102,105,110,100,95,109,111,100, - 117,108,101,40,41,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, - 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, - 116,104,111,110,32,51,46,49,50,59,32,117,115,101,32,102, - 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, - 97,100,78,41,5,114,101,0,0,0,114,102,0,0,0,114, - 103,0,0,0,114,183,0,0,0,114,122,0,0,0,41,4, - 114,180,0,0,0,114,89,0,0,0,114,181,0,0,0,114, - 109,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,11,102,105,110,100,95,109,111,100,117,108,101, - 243,2,0,0,115,10,0,0,0,6,9,2,2,4,254,12, - 3,18,1,122,27,66,117,105,108,116,105,110,73,109,112,111, - 114,116,101,114,46,102,105,110,100,95,109,111,100,117,108,101, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,67,0,0,0,115,46,0,0,0,124,0, - 106,0,116,1,106,2,118,1,114,17,116,3,100,1,160,4, - 124,0,106,0,161,1,124,0,106,0,100,2,141,2,130,1, - 116,5,116,6,106,7,124,0,131,2,83,0,41,4,122,24, - 67,114,101,97,116,101,32,97,32,98,117,105,108,116,45,105, - 110,32,109,111,100,117,108,101,114,85,0,0,0,114,19,0, - 0,0,78,41,8,114,20,0,0,0,114,18,0,0,0,114, - 86,0,0,0,114,87,0,0,0,114,50,0,0,0,114,74, - 0,0,0,114,64,0,0,0,90,14,99,114,101,97,116,101, - 95,98,117,105,108,116,105,110,114,174,0,0,0,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,114,162,0,0, - 0,2,3,0,0,115,10,0,0,0,12,3,12,1,4,1, - 6,255,12,2,122,29,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,99,114,101,97,116,101,95,109,111,100, - 117,108,101,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,16,0,0, - 0,116,0,116,1,106,2,124,0,131,2,1,0,100,1,83, - 0,41,2,122,22,69,120,101,99,32,97,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,78,41,3,114,74, - 0,0,0,114,64,0,0,0,90,12,101,120,101,99,95,98, - 117,105,108,116,105,110,114,177,0,0,0,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,114,163,0,0,0,10, - 3,0,0,115,2,0,0,0,16,3,122,27,66,117,105,108, - 116,105,110,73,109,112,111,114,116,101,114,46,101,120,101,99, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 243,4,0,0,0,100,1,83,0,41,2,122,57,82,101,116, - 117,114,110,32,78,111,110,101,32,97,115,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,115,32,100,111,32, - 110,111,116,32,104,97,118,101,32,99,111,100,101,32,111,98, - 106,101,99,116,115,46,78,114,5,0,0,0,169,2,114,180, - 0,0,0,114,89,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,218,8,103,101,116,95,99,111,100, - 101,15,3,0,0,243,2,0,0,0,4,4,122,24,66,117, - 105,108,116,105,110,73,109,112,111,114,116,101,114,46,103,101, - 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,114, - 185,0,0,0,41,2,122,56,82,101,116,117,114,110,32,78, - 111,110,101,32,97,115,32,98,117,105,108,116,45,105,110,32, - 109,111,100,117,108,101,115,32,100,111,32,110,111,116,32,104, - 97,118,101,32,115,111,117,114,99,101,32,99,111,100,101,46, - 78,114,5,0,0,0,114,186,0,0,0,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,218,10,103,101,116,95, - 115,111,117,114,99,101,21,3,0,0,114,188,0,0,0,122, - 26,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,114,185,0,0,0,41,3,122,52,82,101,116, - 117,114,110,32,70,97,108,115,101,32,97,115,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,114, - 101,32,110,101,118,101,114,32,112,97,99,107,97,103,101,115, - 46,70,78,114,5,0,0,0,114,186,0,0,0,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,114,128,0,0, - 0,27,3,0,0,114,188,0,0,0,122,26,66,117,105,108, - 116,105,110,73,109,112,111,114,116,101,114,46,105,115,95,112, - 97,99,107,97,103,101,169,2,78,78,114,0,0,0,0,41, - 18,114,9,0,0,0,114,8,0,0,0,114,1,0,0,0, - 114,10,0,0,0,114,151,0,0,0,218,12,115,116,97,116, - 105,99,109,101,116,104,111,100,114,114,0,0,0,218,11,99, - 108,97,115,115,109,101,116,104,111,100,114,183,0,0,0,114, - 184,0,0,0,114,162,0,0,0,114,163,0,0,0,114,95, - 0,0,0,114,187,0,0,0,114,189,0,0,0,114,128,0, - 0,0,114,111,0,0,0,114,170,0,0,0,114,5,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, - 114,175,0,0,0,212,2,0,0,115,46,0,0,0,8,0, - 4,2,4,7,2,2,10,1,2,10,12,1,2,8,12,1, - 2,14,10,1,2,7,10,1,2,4,2,1,12,1,2,4, - 2,1,12,1,2,4,2,1,12,1,12,4,114,175,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,4,0,0,0,64,0,0,0,115,144,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,90,4,101, - 5,100,3,100,4,132,0,131,1,90,6,101,7,100,22,100, - 6,100,7,132,1,131,1,90,8,101,7,100,23,100,8,100, - 9,132,1,131,1,90,9,101,5,100,10,100,11,132,0,131, - 1,90,10,101,5,100,12,100,13,132,0,131,1,90,11,101, - 7,100,14,100,15,132,0,131,1,90,12,101,7,101,13,100, - 16,100,17,132,0,131,1,131,1,90,14,101,7,101,13,100, - 18,100,19,132,0,131,1,131,1,90,15,101,7,101,13,100, - 20,100,21,132,0,131,1,131,1,90,16,100,5,83,0,41, - 24,218,14,70,114,111,122,101,110,73,109,112,111,114,116,101, - 114,122,142,77,101,116,97,32,112,97,116,104,32,105,109,112, - 111,114,116,32,102,111,114,32,102,114,111,122,101,110,32,109, - 111,100,117,108,101,115,46,10,10,32,32,32,32,65,108,108, - 32,109,101,116,104,111,100,115,32,97,114,101,32,101,105,116, - 104,101,114,32,99,108,97,115,115,32,111,114,32,115,116,97, - 116,105,99,32,109,101,116,104,111,100,115,32,116,111,32,97, - 118,111,105,100,32,116,104,101,32,110,101,101,100,32,116,111, - 10,32,32,32,32,105,110,115,116,97,110,116,105,97,116,101, - 32,116,104,101,32,99,108,97,115,115,46,10,10,32,32,32, - 32,90,6,102,114,111,122,101,110,99,1,0,0,0,0,0, - 0,0,0,0,0,0,1,0,0,0,4,0,0,0,67,0, - 0,0,115,28,0,0,0,116,0,160,1,100,1,116,2,161, - 2,1,0,100,2,160,3,124,0,106,4,116,5,106,6,161, - 2,83,0,41,4,114,176,0,0,0,122,80,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,46,109,111,100,117,108, - 101,95,114,101,112,114,40,41,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,32,97,110,100,32,115,108,97,116,101, - 100,32,102,111,114,32,114,101,109,111,118,97,108,32,105,110, - 32,80,121,116,104,111,110,32,51,46,49,50,114,166,0,0, - 0,78,41,7,114,101,0,0,0,114,102,0,0,0,114,103, - 0,0,0,114,50,0,0,0,114,9,0,0,0,114,193,0, - 0,0,114,151,0,0,0,41,1,218,1,109,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,114,114,0,0,0, - 47,3,0,0,115,8,0,0,0,6,7,2,1,4,255,16, - 2,122,26,70,114,111,122,101,110,73,109,112,111,114,116,101, - 114,46,109,111,100,117,108,101,95,114,101,112,114,78,99,4, - 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5, - 0,0,0,67,0,0,0,115,30,0,0,0,116,0,160,1, - 124,1,161,1,114,13,116,2,124,1,124,0,124,0,106,3, - 100,1,141,3,83,0,100,0,83,0,114,178,0,0,0,41, - 4,114,64,0,0,0,114,98,0,0,0,114,104,0,0,0, - 114,151,0,0,0,114,179,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,114,183,0,0,0,58,3, - 0,0,115,6,0,0,0,10,2,16,1,4,2,122,24,70, - 114,111,122,101,110,73,109,112,111,114,116,101,114,46,102,105, - 110,100,95,115,112,101,99,99,3,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,4,0,0,0,67,0,0,0, - 115,30,0,0,0,116,0,160,1,100,1,116,2,161,2,1, - 0,116,3,160,4,124,1,161,1,114,13,124,0,83,0,100, - 2,83,0,41,3,122,93,70,105,110,100,32,97,32,102,114, - 111,122,101,110,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,122,105,70,114,111,122,101,110,73,109,112,111, - 114,116,101,114,46,102,105,110,100,95,109,111,100,117,108,101, - 40,41,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 32,97,110,100,32,115,108,97,116,101,100,32,102,111,114,32, - 114,101,109,111,118,97,108,32,105,110,32,80,121,116,104,111, - 110,32,51,46,49,50,59,32,117,115,101,32,102,105,110,100, - 95,115,112,101,99,40,41,32,105,110,115,116,101,97,100,78, - 41,5,114,101,0,0,0,114,102,0,0,0,114,103,0,0, - 0,114,64,0,0,0,114,98,0,0,0,41,3,114,180,0, - 0,0,114,89,0,0,0,114,181,0,0,0,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,114,184,0,0,0, - 65,3,0,0,115,8,0,0,0,6,7,2,2,4,254,18, - 3,122,26,70,114,111,122,101,110,73,109,112,111,114,116,101, - 114,46,102,105,110,100,95,109,111,100,117,108,101,99,1,0, - 0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0, - 0,0,67,0,0,0,114,185,0,0,0,41,2,122,42,85, - 115,101,32,100,101,102,97,117,108,116,32,115,101,109,97,110, - 116,105,99,115,32,102,111,114,32,109,111,100,117,108,101,32, - 99,114,101,97,116,105,111,110,46,78,114,5,0,0,0,114, - 174,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,114,162,0,0,0,77,3,0,0,115,2,0,0, - 0,4,0,122,28,70,114,111,122,101,110,73,109,112,111,114, + 62,41,6,114,101,0,0,0,114,102,0,0,0,114,103,0, + 0,0,114,9,0,0,0,114,175,0,0,0,114,151,0,0, + 0,169,1,114,110,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,114,0,0,0,223,2,0,0, + 115,8,0,0,0,6,7,2,1,4,255,22,2,122,27,66, + 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,109, + 111,100,117,108,101,95,114,101,112,114,78,99,4,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0, + 67,0,0,0,115,42,0,0,0,124,2,100,0,117,1,114, + 6,100,0,83,0,116,0,160,1,124,1,161,1,114,19,116, + 2,124,1,124,0,124,0,106,3,100,1,141,3,83,0,100, + 0,83,0,169,2,78,114,150,0,0,0,41,4,114,64,0, + 0,0,90,10,105,115,95,98,117,105,108,116,105,110,114,104, + 0,0,0,114,151,0,0,0,169,4,218,3,99,108,115,114, + 89,0,0,0,218,4,112,97,116,104,218,6,116,97,114,103, + 101,116,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,218,9,102,105,110,100,95,115,112,101,99,234,2,0,0, + 115,10,0,0,0,8,2,4,1,10,1,16,1,4,2,122, + 25,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 46,102,105,110,100,95,115,112,101,99,99,3,0,0,0,0, + 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, + 0,0,0,115,42,0,0,0,116,0,160,1,100,1,116,2, + 161,2,1,0,124,0,160,3,124,1,124,2,161,2,125,3, + 124,3,100,2,117,1,114,19,124,3,106,4,83,0,100,2, + 83,0,41,3,122,175,70,105,110,100,32,116,104,101,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,46,10, + 10,32,32,32,32,32,32,32,32,73,102,32,39,112,97,116, + 104,39,32,105,115,32,101,118,101,114,32,115,112,101,99,105, + 102,105,101,100,32,116,104,101,110,32,116,104,101,32,115,101, + 97,114,99,104,32,105,115,32,99,111,110,115,105,100,101,114, + 101,100,32,97,32,102,97,105,108,117,114,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, + 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, + 46,32,32,85,115,101,32,102,105,110,100,95,115,112,101,99, + 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, + 32,32,32,32,32,122,106,66,117,105,108,116,105,110,73,109, + 112,111,114,116,101,114,46,102,105,110,100,95,109,111,100,117, + 108,101,40,41,32,105,115,32,100,101,112,114,101,99,97,116, + 101,100,32,97,110,100,32,115,108,97,116,101,100,32,102,111, + 114,32,114,101,109,111,118,97,108,32,105,110,32,80,121,116, + 104,111,110,32,51,46,49,50,59,32,117,115,101,32,102,105, + 110,100,95,115,112,101,99,40,41,32,105,110,115,116,101,97, + 100,78,41,5,114,101,0,0,0,114,102,0,0,0,114,103, + 0,0,0,114,183,0,0,0,114,122,0,0,0,41,4,114, + 180,0,0,0,114,89,0,0,0,114,181,0,0,0,114,109, + 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,243, + 2,0,0,115,10,0,0,0,6,9,2,2,4,254,12,3, + 18,1,122,27,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 4,0,0,0,67,0,0,0,115,46,0,0,0,124,0,106, + 0,116,1,106,2,118,1,114,17,116,3,100,1,160,4,124, + 0,106,0,161,1,124,0,106,0,100,2,141,2,130,1,116, + 5,116,6,106,7,124,0,131,2,83,0,41,3,122,24,67, + 114,101,97,116,101,32,97,32,98,117,105,108,116,45,105,110, + 32,109,111,100,117,108,101,114,85,0,0,0,114,19,0,0, + 0,41,8,114,20,0,0,0,114,18,0,0,0,114,86,0, + 0,0,114,87,0,0,0,114,50,0,0,0,114,74,0,0, + 0,114,64,0,0,0,90,14,99,114,101,97,116,101,95,98, + 117,105,108,116,105,110,114,174,0,0,0,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,114,162,0,0,0,2, + 3,0,0,115,10,0,0,0,12,3,12,1,4,1,6,255, + 12,2,122,29,66,117,105,108,116,105,110,73,109,112,111,114, 116,101,114,46,99,114,101,97,116,101,95,109,111,100,117,108, - 101,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, - 0,0,4,0,0,0,67,0,0,0,115,64,0,0,0,124, - 0,106,0,106,1,125,1,116,2,160,3,124,1,161,1,115, - 18,116,4,100,1,160,5,124,1,161,1,124,1,100,2,141, - 2,130,1,116,6,116,2,106,7,124,1,131,2,125,2,116, - 8,124,2,124,0,106,9,131,2,1,0,100,0,83,0,114, - 97,0,0,0,41,10,114,113,0,0,0,114,20,0,0,0, - 114,64,0,0,0,114,98,0,0,0,114,87,0,0,0,114, - 50,0,0,0,114,74,0,0,0,218,17,103,101,116,95,102, - 114,111,122,101,110,95,111,98,106,101,99,116,218,4,101,120, - 101,99,114,14,0,0,0,41,3,114,110,0,0,0,114,20, - 0,0,0,218,4,99,111,100,101,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,114,163,0,0,0,81,3,0, - 0,115,14,0,0,0,8,2,10,1,10,1,2,1,6,255, - 12,2,16,1,122,26,70,114,111,122,101,110,73,109,112,111, - 114,116,101,114,46,101,120,101,99,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,3,0,0,0,67,0,0,0,115,10,0,0,0,116,0, - 124,0,124,1,131,2,83,0,41,2,122,95,76,111,97,100, - 32,97,32,102,114,111,122,101,110,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, - 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, - 97,116,101,100,46,32,32,85,115,101,32,101,120,101,99,95, - 109,111,100,117,108,101,40,41,32,105,110,115,116,101,97,100, - 46,10,10,32,32,32,32,32,32,32,32,78,41,1,114,111, - 0,0,0,114,186,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,114,170,0,0,0,90,3,0,0, - 115,2,0,0,0,10,8,122,26,70,114,111,122,101,110,73, - 109,112,111,114,116,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,243,10,0,0, - 0,116,0,160,1,124,1,161,1,83,0,41,2,122,45,82, - 101,116,117,114,110,32,116,104,101,32,99,111,100,101,32,111, - 98,106,101,99,116,32,102,111,114,32,116,104,101,32,102,114, - 111,122,101,110,32,109,111,100,117,108,101,46,78,41,2,114, - 64,0,0,0,114,195,0,0,0,114,186,0,0,0,114,5, - 0,0,0,114,5,0,0,0,114,6,0,0,0,114,187,0, - 0,0,100,3,0,0,243,2,0,0,0,10,4,122,23,70, - 114,111,122,101,110,73,109,112,111,114,116,101,114,46,103,101, - 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,114, - 185,0,0,0,41,2,122,54,82,101,116,117,114,110,32,78, - 111,110,101,32,97,115,32,102,114,111,122,101,110,32,109,111, + 101,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,16,0,0,0,116, + 0,116,1,106,2,124,0,131,2,1,0,100,1,83,0,41, + 2,122,22,69,120,101,99,32,97,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,78,41,3,114,74,0,0, + 0,114,64,0,0,0,90,12,101,120,101,99,95,98,117,105, + 108,116,105,110,114,177,0,0,0,114,5,0,0,0,114,5, + 0,0,0,114,6,0,0,0,114,163,0,0,0,10,3,0, + 0,115,2,0,0,0,16,3,122,27,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,101,120,101,99,95,109, + 111,100,117,108,101,99,2,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,243,4, + 0,0,0,100,1,83,0,41,2,122,57,82,101,116,117,114, + 110,32,78,111,110,101,32,97,115,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,115,32,100,111,32,110,111, + 116,32,104,97,118,101,32,99,111,100,101,32,111,98,106,101, + 99,116,115,46,78,114,5,0,0,0,169,2,114,180,0,0, + 0,114,89,0,0,0,114,5,0,0,0,114,5,0,0,0, + 114,6,0,0,0,218,8,103,101,116,95,99,111,100,101,15, + 3,0,0,243,2,0,0,0,4,4,122,24,66,117,105,108, + 116,105,110,73,109,112,111,114,116,101,114,46,103,101,116,95, + 99,111,100,101,99,2,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,114,185,0, + 0,0,41,2,122,56,82,101,116,117,114,110,32,78,111,110, + 101,32,97,115,32,98,117,105,108,116,45,105,110,32,109,111, 100,117,108,101,115,32,100,111,32,110,111,116,32,104,97,118, 101,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, 5,0,0,0,114,186,0,0,0,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,114,189,0,0,0,106,3,0, - 0,114,188,0,0,0,122,25,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,46,103,101,116,95,115,111,117,114,99, - 101,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,114,198,0,0,0,41, - 2,122,46,82,101,116,117,114,110,32,84,114,117,101,32,105, - 102,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, - 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, - 46,78,41,2,114,64,0,0,0,90,17,105,115,95,102,114, - 111,122,101,110,95,112,97,99,107,97,103,101,114,186,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,6,0,0,0, - 114,128,0,0,0,112,3,0,0,114,199,0,0,0,122,25, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,105, - 115,95,112,97,99,107,97,103,101,114,190,0,0,0,114,0, - 0,0,0,41,17,114,9,0,0,0,114,8,0,0,0,114, - 1,0,0,0,114,10,0,0,0,114,151,0,0,0,114,191, - 0,0,0,114,114,0,0,0,114,192,0,0,0,114,183,0, - 0,0,114,184,0,0,0,114,162,0,0,0,114,163,0,0, - 0,114,170,0,0,0,114,100,0,0,0,114,187,0,0,0, - 114,189,0,0,0,114,128,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,193, - 0,0,0,36,3,0,0,115,48,0,0,0,8,0,4,2, - 4,7,2,2,10,1,2,10,12,1,2,6,12,1,2,11, - 10,1,2,3,10,1,2,8,10,1,2,9,2,1,12,1, - 2,4,2,1,12,1,2,4,2,1,16,1,114,193,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,64,0,0,0,115,32,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,83,0,41, - 7,218,18,95,73,109,112,111,114,116,76,111,99,107,67,111, - 110,116,101,120,116,122,36,67,111,110,116,101,120,116,32,109, - 97,110,97,103,101,114,32,102,111,114,32,116,104,101,32,105, - 109,112,111,114,116,32,108,111,99,107,46,99,1,0,0,0, - 0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0, - 67,0,0,0,243,12,0,0,0,116,0,160,1,161,0,1, - 0,100,1,83,0,41,2,122,24,65,99,113,117,105,114,101, - 32,116,104,101,32,105,109,112,111,114,116,32,108,111,99,107, - 46,78,41,2,114,64,0,0,0,114,65,0,0,0,114,52, - 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,114,61,0,0,0,125,3,0,0,243,2,0,0,0, - 12,2,122,28,95,73,109,112,111,114,116,76,111,99,107,67, - 111,110,116,101,120,116,46,95,95,101,110,116,101,114,95,95, - 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,2,0,0,0,67,0,0,0,114,201,0,0,0,41,2, - 122,60,82,101,108,101,97,115,101,32,116,104,101,32,105,109, - 112,111,114,116,32,108,111,99,107,32,114,101,103,97,114,100, - 108,101,115,115,32,111,102,32,97,110,121,32,114,97,105,115, - 101,100,32,101,120,99,101,112,116,105,111,110,115,46,78,41, - 2,114,64,0,0,0,114,67,0,0,0,41,4,114,33,0, - 0,0,218,8,101,120,99,95,116,121,112,101,218,9,101,120, - 99,95,118,97,108,117,101,218,13,101,120,99,95,116,114,97, - 99,101,98,97,99,107,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,114,63,0,0,0,129,3,0,0,114,202, - 0,0,0,122,27,95,73,109,112,111,114,116,76,111,99,107, - 67,111,110,116,101,120,116,46,95,95,101,120,105,116,95,95, - 78,41,6,114,9,0,0,0,114,8,0,0,0,114,1,0, - 0,0,114,10,0,0,0,114,61,0,0,0,114,63,0,0, - 0,114,5,0,0,0,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,114,200,0,0,0,121,3,0,0,115,8, - 0,0,0,8,0,4,2,8,2,12,4,114,200,0,0,0, - 99,3,0,0,0,0,0,0,0,0,0,0,0,5,0,0, - 0,5,0,0,0,67,0,0,0,115,64,0,0,0,124,1, - 160,0,100,1,124,2,100,2,24,0,161,2,125,3,116,1, - 124,3,131,1,124,2,107,0,114,18,116,2,100,3,131,1, - 130,1,124,3,100,4,25,0,125,4,124,0,114,30,100,5, - 160,3,124,4,124,0,161,2,83,0,124,4,83,0,41,7, - 122,50,82,101,115,111,108,118,101,32,97,32,114,101,108,97, - 116,105,118,101,32,109,111,100,117,108,101,32,110,97,109,101, - 32,116,111,32,97,110,32,97,98,115,111,108,117,116,101,32, - 111,110,101,46,114,141,0,0,0,114,42,0,0,0,122,50, - 97,116,116,101,109,112,116,101,100,32,114,101,108,97,116,105, - 118,101,32,105,109,112,111,114,116,32,98,101,121,111,110,100, - 32,116,111,112,45,108,101,118,101,108,32,112,97,99,107,97, - 103,101,114,25,0,0,0,250,5,123,125,46,123,125,78,41, - 4,218,6,114,115,112,108,105,116,218,3,108,101,110,114,87, - 0,0,0,114,50,0,0,0,41,5,114,20,0,0,0,218, - 7,112,97,99,107,97,103,101,218,5,108,101,118,101,108,90, - 4,98,105,116,115,90,4,98,97,115,101,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,218,13,95,114,101,115, - 111,108,118,101,95,110,97,109,101,134,3,0,0,115,10,0, - 0,0,16,2,12,1,8,1,8,1,20,1,114,211,0,0, - 0,99,3,0,0,0,0,0,0,0,0,0,0,0,5,0, - 0,0,4,0,0,0,67,0,0,0,115,60,0,0,0,116, - 0,124,0,131,1,155,0,100,1,157,2,125,3,116,1,160, - 2,124,3,116,3,161,2,1,0,124,0,160,4,124,1,124, - 2,161,2,125,4,124,4,100,0,117,0,114,25,100,0,83, - 0,116,5,124,1,124,4,131,2,83,0,41,2,78,122,53, - 46,102,105,110,100,95,115,112,101,99,40,41,32,110,111,116, - 32,102,111,117,110,100,59,32,102,97,108,108,105,110,103,32, - 98,97,99,107,32,116,111,32,102,105,110,100,95,109,111,100, - 117,108,101,40,41,41,6,114,7,0,0,0,114,101,0,0, - 0,114,102,0,0,0,114,169,0,0,0,114,184,0,0,0, - 114,104,0,0,0,41,5,218,6,102,105,110,100,101,114,114, - 20,0,0,0,114,181,0,0,0,114,108,0,0,0,114,122, + 0,0,0,114,6,0,0,0,218,10,103,101,116,95,115,111, + 117,114,99,101,21,3,0,0,114,188,0,0,0,122,26,66, + 117,105,108,116,105,110,73,109,112,111,114,116,101,114,46,103, + 101,116,95,115,111,117,114,99,101,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,114,185,0,0,0,41,2,122,52,82,101,116,117,114, + 110,32,70,97,108,115,101,32,97,115,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,32,97,114,101,32, + 110,101,118,101,114,32,112,97,99,107,97,103,101,115,46,70, + 114,5,0,0,0,114,186,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,6,0,0,0,114,128,0,0,0,27,3, + 0,0,114,188,0,0,0,122,26,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,46,105,115,95,112,97,99,107, + 97,103,101,169,2,78,78,114,0,0,0,0,41,18,114,9, + 0,0,0,114,8,0,0,0,114,1,0,0,0,114,10,0, + 0,0,114,151,0,0,0,218,12,115,116,97,116,105,99,109, + 101,116,104,111,100,114,114,0,0,0,218,11,99,108,97,115, + 115,109,101,116,104,111,100,114,183,0,0,0,114,184,0,0, + 0,114,162,0,0,0,114,163,0,0,0,114,95,0,0,0, + 114,187,0,0,0,114,189,0,0,0,114,128,0,0,0,114, + 111,0,0,0,114,170,0,0,0,114,5,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,175,0, + 0,0,212,2,0,0,115,46,0,0,0,8,0,4,2,4, + 7,2,2,10,1,2,10,12,1,2,8,12,1,2,14,10, + 1,2,7,10,1,2,4,2,1,12,1,2,4,2,1,12, + 1,2,4,2,1,12,1,12,4,114,175,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, + 0,0,0,64,0,0,0,115,144,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,90,4,101,5,100,3, + 100,4,132,0,131,1,90,6,101,7,100,22,100,6,100,7, + 132,1,131,1,90,8,101,7,100,23,100,8,100,9,132,1, + 131,1,90,9,101,5,100,10,100,11,132,0,131,1,90,10, + 101,5,100,12,100,13,132,0,131,1,90,11,101,7,100,14, + 100,15,132,0,131,1,90,12,101,7,101,13,100,16,100,17, + 132,0,131,1,131,1,90,14,101,7,101,13,100,18,100,19, + 132,0,131,1,131,1,90,15,101,7,101,13,100,20,100,21, + 132,0,131,1,131,1,90,16,100,5,83,0,41,24,218,14, + 70,114,111,122,101,110,73,109,112,111,114,116,101,114,122,142, + 77,101,116,97,32,112,97,116,104,32,105,109,112,111,114,116, + 32,102,111,114,32,102,114,111,122,101,110,32,109,111,100,117, + 108,101,115,46,10,10,32,32,32,32,65,108,108,32,109,101, + 116,104,111,100,115,32,97,114,101,32,101,105,116,104,101,114, + 32,99,108,97,115,115,32,111,114,32,115,116,97,116,105,99, + 32,109,101,116,104,111,100,115,32,116,111,32,97,118,111,105, + 100,32,116,104,101,32,110,101,101,100,32,116,111,10,32,32, + 32,32,105,110,115,116,97,110,116,105,97,116,101,32,116,104, + 101,32,99,108,97,115,115,46,10,10,32,32,32,32,90,6, + 102,114,111,122,101,110,99,1,0,0,0,0,0,0,0,0, + 0,0,0,1,0,0,0,4,0,0,0,67,0,0,0,115, + 28,0,0,0,116,0,160,1,100,1,116,2,161,2,1,0, + 100,2,160,3,124,0,106,4,116,5,106,6,161,2,83,0, + 41,3,114,176,0,0,0,122,80,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,109,111,100,117,108,101,95,114, + 101,112,114,40,41,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, + 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, + 116,104,111,110,32,51,46,49,50,114,166,0,0,0,41,7, + 114,101,0,0,0,114,102,0,0,0,114,103,0,0,0,114, + 50,0,0,0,114,9,0,0,0,114,193,0,0,0,114,151, + 0,0,0,41,1,218,1,109,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,114,0,0,0,47,3,0,0, + 115,8,0,0,0,6,7,2,1,4,255,16,2,122,26,70, + 114,111,122,101,110,73,109,112,111,114,116,101,114,46,109,111, + 100,117,108,101,95,114,101,112,114,78,99,4,0,0,0,0, + 0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,67, + 0,0,0,115,30,0,0,0,116,0,160,1,124,1,161,1, + 114,13,116,2,124,1,124,0,124,0,106,3,100,1,141,3, + 83,0,100,0,83,0,114,178,0,0,0,41,4,114,64,0, + 0,0,114,98,0,0,0,114,104,0,0,0,114,151,0,0, + 0,114,179,0,0,0,114,5,0,0,0,114,5,0,0,0, + 114,6,0,0,0,114,183,0,0,0,58,3,0,0,115,6, + 0,0,0,10,2,16,1,4,2,122,24,70,114,111,122,101, + 110,73,109,112,111,114,116,101,114,46,102,105,110,100,95,115, + 112,101,99,99,3,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,4,0,0,0,67,0,0,0,115,30,0,0, + 0,116,0,160,1,100,1,116,2,161,2,1,0,116,3,160, + 4,124,1,161,1,114,13,124,0,83,0,100,2,83,0,41, + 3,122,93,70,105,110,100,32,97,32,102,114,111,122,101,110, + 32,109,111,100,117,108,101,46,10,10,32,32,32,32,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, + 122,105,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,102,105,110,100,95,109,111,100,117,108,101,40,41,32,105, + 115,32,100,101,112,114,101,99,97,116,101,100,32,97,110,100, + 32,115,108,97,116,101,100,32,102,111,114,32,114,101,109,111, + 118,97,108,32,105,110,32,80,121,116,104,111,110,32,51,46, + 49,50,59,32,117,115,101,32,102,105,110,100,95,115,112,101, + 99,40,41,32,105,110,115,116,101,97,100,78,41,5,114,101, + 0,0,0,114,102,0,0,0,114,103,0,0,0,114,64,0, + 0,0,114,98,0,0,0,41,3,114,180,0,0,0,114,89, + 0,0,0,114,181,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,184,0,0,0,65,3,0,0, + 115,8,0,0,0,6,7,2,2,4,254,18,3,122,26,70, + 114,111,122,101,110,73,109,112,111,114,116,101,114,46,102,105, + 110,100,95,109,111,100,117,108,101,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,1,0,0,0,67,0, + 0,0,114,185,0,0,0,41,2,122,42,85,115,101,32,100, + 101,102,97,117,108,116,32,115,101,109,97,110,116,105,99,115, + 32,102,111,114,32,109,111,100,117,108,101,32,99,114,101,97, + 116,105,111,110,46,78,114,5,0,0,0,114,174,0,0,0, + 114,5,0,0,0,114,5,0,0,0,114,6,0,0,0,114, + 162,0,0,0,77,3,0,0,115,2,0,0,0,4,0,122, + 28,70,114,111,122,101,110,73,109,112,111,114,116,101,114,46, + 99,114,101,97,116,101,95,109,111,100,117,108,101,99,1,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, + 0,0,67,0,0,0,115,64,0,0,0,124,0,106,0,106, + 1,125,1,116,2,160,3,124,1,161,1,115,18,116,4,100, + 1,160,5,124,1,161,1,124,1,100,2,141,2,130,1,116, + 6,116,2,106,7,124,1,131,2,125,2,116,8,124,2,124, + 0,106,9,131,2,1,0,100,0,83,0,114,97,0,0,0, + 41,10,114,113,0,0,0,114,20,0,0,0,114,64,0,0, + 0,114,98,0,0,0,114,87,0,0,0,114,50,0,0,0, + 114,74,0,0,0,218,17,103,101,116,95,102,114,111,122,101, + 110,95,111,98,106,101,99,116,218,4,101,120,101,99,114,14, + 0,0,0,41,3,114,110,0,0,0,114,20,0,0,0,218, + 4,99,111,100,101,114,5,0,0,0,114,5,0,0,0,114, + 6,0,0,0,114,163,0,0,0,81,3,0,0,115,14,0, + 0,0,8,2,10,1,10,1,2,1,6,255,12,2,16,1, + 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,67,0,0,0,115,10,0,0,0,116,0,124,0,124,1, + 131,2,83,0,41,1,122,95,76,111,97,100,32,97,32,102, + 114,111,122,101,110,32,109,111,100,117,108,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, + 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, + 46,32,32,85,115,101,32,101,120,101,99,95,109,111,100,117, + 108,101,40,41,32,105,110,115,116,101,97,100,46,10,10,32, + 32,32,32,32,32,32,32,41,1,114,111,0,0,0,114,186, 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,218,17,95,102,105,110,100,95,115,112,101,99,95,108, - 101,103,97,99,121,143,3,0,0,115,12,0,0,0,14,1, - 12,2,12,1,8,1,4,1,10,1,114,213,0,0,0,99, - 3,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0, - 10,0,0,0,67,0,0,0,115,24,1,0,0,116,0,106, - 1,125,3,124,3,100,1,117,0,114,11,116,2,100,2,131, - 1,130,1,124,3,115,19,116,3,160,4,100,3,116,5,161, - 2,1,0,124,0,116,0,106,6,118,0,125,4,124,3,68, - 0,93,109,125,5,116,7,131,0,143,46,1,0,122,5,124, - 5,106,8,125,6,87,0,110,26,4,0,116,9,121,139,1, - 0,1,0,1,0,116,10,124,5,124,0,124,1,131,3,125, - 7,124,7,100,1,117,0,114,62,89,0,87,0,100,1,4, - 0,4,0,131,3,1,0,113,26,89,0,110,6,124,6,124, - 0,124,1,124,2,131,3,125,7,87,0,100,1,4,0,4, - 0,131,3,1,0,110,8,49,0,115,80,119,1,1,0,1, - 0,1,0,89,0,1,0,124,7,100,1,117,1,114,135,124, - 4,115,131,124,0,116,0,106,6,118,0,114,131,116,0,106, - 6,124,0,25,0,125,8,122,5,124,8,106,11,125,9,87, - 0,110,12,4,0,116,9,121,138,1,0,1,0,1,0,124, - 7,6,0,89,0,2,0,1,0,83,0,124,9,100,1,117, - 0,114,127,124,7,2,0,1,0,83,0,124,9,2,0,1, - 0,83,0,124,7,2,0,1,0,83,0,113,26,100,1,83, - 0,119,0,119,0,41,4,122,21,70,105,110,100,32,97,32, - 109,111,100,117,108,101,39,115,32,115,112,101,99,46,78,122, - 53,115,121,115,46,109,101,116,97,95,112,97,116,104,32,105, - 115,32,78,111,110,101,44,32,80,121,116,104,111,110,32,105, - 115,32,108,105,107,101,108,121,32,115,104,117,116,116,105,110, - 103,32,100,111,119,110,122,22,115,121,115,46,109,101,116,97, - 95,112,97,116,104,32,105,115,32,101,109,112,116,121,41,12, - 114,18,0,0,0,218,9,109,101,116,97,95,112,97,116,104, - 114,87,0,0,0,114,101,0,0,0,114,102,0,0,0,114, - 169,0,0,0,114,105,0,0,0,114,200,0,0,0,114,183, - 0,0,0,114,2,0,0,0,114,213,0,0,0,114,113,0, - 0,0,41,10,114,20,0,0,0,114,181,0,0,0,114,182, - 0,0,0,114,214,0,0,0,90,9,105,115,95,114,101,108, - 111,97,100,114,212,0,0,0,114,183,0,0,0,114,109,0, - 0,0,114,110,0,0,0,114,113,0,0,0,114,5,0,0, - 0,114,5,0,0,0,114,6,0,0,0,218,10,95,102,105, - 110,100,95,115,112,101,99,153,3,0,0,115,70,0,0,0, - 6,2,8,1,8,2,4,3,12,1,10,5,8,1,8,1, - 2,1,10,1,12,1,12,1,8,1,2,1,12,250,2,6, - 4,255,12,3,2,128,28,248,8,9,14,2,10,1,2,1, - 10,1,12,1,12,4,8,2,8,1,8,2,8,2,2,239, - 4,19,2,243,2,244,114,215,0,0,0,99,3,0,0,0, - 0,0,0,0,0,0,0,0,3,0,0,0,5,0,0,0, - 67,0,0,0,115,110,0,0,0,116,0,124,0,116,1,131, - 2,115,14,116,2,100,1,160,3,116,4,124,0,131,1,161, - 1,131,1,130,1,124,2,100,2,107,0,114,22,116,5,100, - 3,131,1,130,1,124,2,100,2,107,4,114,41,116,0,124, - 1,116,1,131,2,115,35,116,2,100,4,131,1,130,1,124, - 1,115,41,116,6,100,5,131,1,130,1,124,0,115,53,124, - 2,100,2,107,2,114,51,116,5,100,6,131,1,130,1,100, - 7,83,0,100,7,83,0,41,8,122,28,86,101,114,105,102, - 121,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32, - 34,115,97,110,101,34,46,122,31,109,111,100,117,108,101,32, - 110,97,109,101,32,109,117,115,116,32,98,101,32,115,116,114, - 44,32,110,111,116,32,123,125,114,25,0,0,0,122,18,108, - 101,118,101,108,32,109,117,115,116,32,98,101,32,62,61,32, - 48,122,31,95,95,112,97,99,107,97,103,101,95,95,32,110, - 111,116,32,115,101,116,32,116,111,32,97,32,115,116,114,105, - 110,103,122,54,97,116,116,101,109,112,116,101,100,32,114,101, - 108,97,116,105,118,101,32,105,109,112,111,114,116,32,119,105, - 116,104,32,110,111,32,107,110,111,119,110,32,112,97,114,101, - 110,116,32,112,97,99,107,97,103,101,122,17,69,109,112,116, - 121,32,109,111,100,117,108,101,32,110,97,109,101,78,41,7, - 218,10,105,115,105,110,115,116,97,110,99,101,218,3,115,116, - 114,218,9,84,121,112,101,69,114,114,111,114,114,50,0,0, - 0,114,3,0,0,0,218,10,86,97,108,117,101,69,114,114, - 111,114,114,87,0,0,0,169,3,114,20,0,0,0,114,209, - 0,0,0,114,210,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,218,13,95,115,97,110,105,116,121, - 95,99,104,101,99,107,200,3,0,0,115,24,0,0,0,10, - 2,18,1,8,1,8,1,8,1,10,1,8,1,4,1,8, - 1,12,2,8,1,8,255,114,221,0,0,0,122,16,78,111, - 32,109,111,100,117,108,101,32,110,97,109,101,100,32,122,4, - 123,33,114,125,99,2,0,0,0,0,0,0,0,0,0,0, - 0,9,0,0,0,8,0,0,0,67,0,0,0,115,16,1, - 0,0,100,0,125,2,124,0,160,0,100,1,161,1,100,2, - 25,0,125,3,124,3,114,63,124,3,116,1,106,2,118,1, - 114,21,116,3,124,1,124,3,131,2,1,0,124,0,116,1, - 106,2,118,0,114,31,116,1,106,2,124,0,25,0,83,0, - 116,1,106,2,124,3,25,0,125,4,122,5,124,4,106,4, - 125,2,87,0,110,21,4,0,116,5,121,135,1,0,1,0, - 1,0,116,6,100,3,23,0,160,7,124,0,124,3,161,2, - 125,5,116,8,124,5,124,0,100,4,141,2,100,0,130,2, - 116,9,124,0,124,2,131,2,125,6,124,6,100,0,117,0, - 114,81,116,8,116,6,160,7,124,0,161,1,124,0,100,4, - 141,2,130,1,116,10,124,6,131,1,125,7,124,3,114,132, - 116,1,106,2,124,3,25,0,125,4,124,0,160,0,100,1, - 161,1,100,5,25,0,125,8,122,9,116,11,124,4,124,8, - 124,7,131,3,1,0,87,0,124,7,83,0,4,0,116,5, - 121,134,1,0,1,0,1,0,100,6,124,3,155,2,100,7, - 124,8,155,2,157,4,125,5,116,12,160,13,124,5,116,14, - 161,2,1,0,89,0,124,7,83,0,124,7,83,0,119,0, - 119,0,41,8,78,114,141,0,0,0,114,25,0,0,0,122, - 23,59,32,123,33,114,125,32,105,115,32,110,111,116,32,97, - 32,112,97,99,107,97,103,101,114,19,0,0,0,233,2,0, - 0,0,122,27,67,97,110,110,111,116,32,115,101,116,32,97, - 110,32,97,116,116,114,105,98,117,116,101,32,111,110,32,122, - 18,32,102,111,114,32,99,104,105,108,100,32,109,111,100,117, - 108,101,32,41,15,114,142,0,0,0,114,18,0,0,0,114, - 105,0,0,0,114,74,0,0,0,114,154,0,0,0,114,2, - 0,0,0,218,8,95,69,82,82,95,77,83,71,114,50,0, - 0,0,218,19,77,111,100,117,108,101,78,111,116,70,111,117, - 110,100,69,114,114,111,114,114,215,0,0,0,114,173,0,0, - 0,114,12,0,0,0,114,101,0,0,0,114,102,0,0,0, - 114,169,0,0,0,41,9,114,20,0,0,0,218,7,105,109, - 112,111,114,116,95,114,181,0,0,0,114,143,0,0,0,90, - 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,108, - 0,0,0,114,109,0,0,0,114,110,0,0,0,90,5,99, - 104,105,108,100,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,23,95,102,105,110,100,95,97,110,100,95,108, - 111,97,100,95,117,110,108,111,99,107,101,100,219,3,0,0, - 115,58,0,0,0,4,1,14,1,4,1,10,1,10,1,10, - 2,10,1,10,1,2,1,10,1,12,1,16,1,14,1,10, - 1,8,1,18,1,8,2,4,1,10,2,14,1,2,1,14, - 1,4,4,12,253,16,1,14,1,8,1,2,253,2,242,114, - 226,0,0,0,99,2,0,0,0,0,0,0,0,0,0,0, - 0,4,0,0,0,8,0,0,0,67,0,0,0,115,128,0, - 0,0,116,0,124,0,131,1,143,31,1,0,116,1,106,2, - 160,3,124,0,116,4,161,2,125,2,124,2,116,4,117,0, - 114,28,116,5,124,0,124,1,131,2,87,0,2,0,100,1, - 4,0,4,0,131,3,1,0,83,0,87,0,100,1,4,0, - 4,0,131,3,1,0,110,8,49,0,115,38,119,1,1,0, - 1,0,1,0,89,0,1,0,124,2,100,1,117,0,114,58, - 100,2,160,6,124,0,161,1,125,3,116,7,124,3,124,0, - 100,3,141,2,130,1,116,8,124,0,131,1,1,0,124,2, - 83,0,41,4,122,25,70,105,110,100,32,97,110,100,32,108, - 111,97,100,32,116,104,101,32,109,111,100,117,108,101,46,78, - 122,40,105,109,112,111,114,116,32,111,102,32,123,125,32,104, - 97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,115, - 121,115,46,109,111,100,117,108,101,115,114,19,0,0,0,41, - 9,114,57,0,0,0,114,18,0,0,0,114,105,0,0,0, - 114,38,0,0,0,218,14,95,78,69,69,68,83,95,76,79, - 65,68,73,78,71,114,226,0,0,0,114,50,0,0,0,114, - 224,0,0,0,114,72,0,0,0,41,4,114,20,0,0,0, - 114,225,0,0,0,114,110,0,0,0,114,82,0,0,0,114, - 5,0,0,0,114,5,0,0,0,114,6,0,0,0,218,14, - 95,102,105,110,100,95,97,110,100,95,108,111,97,100,254,3, - 0,0,115,30,0,0,0,10,2,14,1,8,1,8,1,14, - 253,2,3,2,255,28,254,8,5,2,1,6,1,2,255,12, - 2,8,2,4,1,114,228,0,0,0,114,25,0,0,0,99, - 3,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 4,0,0,0,67,0,0,0,115,42,0,0,0,116,0,124, - 0,124,1,124,2,131,3,1,0,124,2,100,1,107,4,114, - 16,116,1,124,0,124,1,124,2,131,3,125,0,116,2,124, - 0,116,3,131,2,83,0,41,3,97,50,1,0,0,73,109, - 112,111,114,116,32,97,110,100,32,114,101,116,117,114,110,32, - 116,104,101,32,109,111,100,117,108,101,32,98,97,115,101,100, - 32,111,110,32,105,116,115,32,110,97,109,101,44,32,116,104, - 101,32,112,97,99,107,97,103,101,32,116,104,101,32,99,97, - 108,108,32,105,115,10,32,32,32,32,98,101,105,110,103,32, - 109,97,100,101,32,102,114,111,109,44,32,97,110,100,32,116, - 104,101,32,108,101,118,101,108,32,97,100,106,117,115,116,109, - 101,110,116,46,10,10,32,32,32,32,84,104,105,115,32,102, - 117,110,99,116,105,111,110,32,114,101,112,114,101,115,101,110, - 116,115,32,116,104,101,32,103,114,101,97,116,101,115,116,32, - 99,111,109,109,111,110,32,100,101,110,111,109,105,110,97,116, - 111,114,32,111,102,32,102,117,110,99,116,105,111,110,97,108, - 105,116,121,10,32,32,32,32,98,101,116,119,101,101,110,32, - 105,109,112,111,114,116,95,109,111,100,117,108,101,32,97,110, - 100,32,95,95,105,109,112,111,114,116,95,95,46,32,84,104, - 105,115,32,105,110,99,108,117,100,101,115,32,115,101,116,116, - 105,110,103,32,95,95,112,97,99,107,97,103,101,95,95,32, - 105,102,10,32,32,32,32,116,104,101,32,108,111,97,100,101, - 114,32,100,105,100,32,110,111,116,46,10,10,32,32,32,32, - 114,25,0,0,0,78,41,4,114,221,0,0,0,114,211,0, - 0,0,114,228,0,0,0,218,11,95,103,99,100,95,105,109, - 112,111,114,116,114,220,0,0,0,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,114,229,0,0,0,14,4,0, - 0,115,8,0,0,0,12,9,8,1,12,1,10,1,114,229, - 0,0,0,169,1,218,9,114,101,99,117,114,115,105,118,101, - 99,3,0,0,0,0,0,0,0,1,0,0,0,8,0,0, - 0,11,0,0,0,67,0,0,0,115,218,0,0,0,124,1, - 68,0,93,103,125,4,116,0,124,4,116,1,131,2,115,32, - 124,3,114,17,124,0,106,2,100,1,23,0,125,5,110,2, - 100,2,125,5,116,3,100,3,124,5,155,0,100,4,116,4, - 124,4,131,1,106,2,155,0,157,4,131,1,130,1,124,4, - 100,5,107,2,114,53,124,3,115,52,116,5,124,0,100,6, - 131,2,114,52,116,6,124,0,124,0,106,7,124,2,100,7, - 100,8,141,4,1,0,113,2,116,5,124,0,124,4,131,2, - 115,105,100,9,160,8,124,0,106,2,124,4,161,2,125,6, - 122,7,116,9,124,2,124,6,131,2,1,0,87,0,113,2, - 4,0,116,10,121,108,1,0,125,7,1,0,122,21,124,7, - 106,11,124,6,107,2,114,100,116,12,106,13,160,14,124,6, - 116,15,161,2,100,10,117,1,114,100,87,0,89,0,100,10, - 125,7,126,7,113,2,130,0,100,10,125,7,126,7,119,1, - 113,2,124,0,83,0,119,0,41,11,122,238,70,105,103,117, - 114,101,32,111,117,116,32,119,104,97,116,32,95,95,105,109, - 112,111,114,116,95,95,32,115,104,111,117,108,100,32,114,101, - 116,117,114,110,46,10,10,32,32,32,32,84,104,101,32,105, - 109,112,111,114,116,95,32,112,97,114,97,109,101,116,101,114, - 32,105,115,32,97,32,99,97,108,108,97,98,108,101,32,119, - 104,105,99,104,32,116,97,107,101,115,32,116,104,101,32,110, - 97,109,101,32,111,102,32,109,111,100,117,108,101,32,116,111, - 10,32,32,32,32,105,109,112,111,114,116,46,32,73,116,32, - 105,115,32,114,101,113,117,105,114,101,100,32,116,111,32,100, - 101,99,111,117,112,108,101,32,116,104,101,32,102,117,110,99, - 116,105,111,110,32,102,114,111,109,32,97,115,115,117,109,105, - 110,103,32,105,109,112,111,114,116,108,105,98,39,115,10,32, - 32,32,32,105,109,112,111,114,116,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,105,115,32,100,101,115,105, - 114,101,100,46,10,10,32,32,32,32,122,8,46,95,95,97, - 108,108,95,95,122,13,96,96,102,114,111,109,32,108,105,115, - 116,39,39,122,8,73,116,101,109,32,105,110,32,122,18,32, - 109,117,115,116,32,98,101,32,115,116,114,44,32,110,111,116, - 32,250,1,42,218,7,95,95,97,108,108,95,95,84,114,230, - 0,0,0,114,206,0,0,0,78,41,16,114,216,0,0,0, - 114,217,0,0,0,114,9,0,0,0,114,218,0,0,0,114, - 3,0,0,0,114,11,0,0,0,218,16,95,104,97,110,100, - 108,101,95,102,114,111,109,108,105,115,116,114,233,0,0,0, - 114,50,0,0,0,114,74,0,0,0,114,224,0,0,0,114, - 20,0,0,0,114,18,0,0,0,114,105,0,0,0,114,38, - 0,0,0,114,227,0,0,0,41,8,114,110,0,0,0,218, - 8,102,114,111,109,108,105,115,116,114,225,0,0,0,114,231, - 0,0,0,218,1,120,90,5,119,104,101,114,101,90,9,102, - 114,111,109,95,110,97,109,101,90,3,101,120,99,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,114,234,0,0, - 0,29,4,0,0,115,56,0,0,0,8,10,10,1,4,1, - 12,1,4,2,10,1,8,1,8,255,8,2,14,1,10,1, - 2,1,6,255,2,128,10,2,14,1,2,1,14,1,14,1, - 10,4,16,1,2,255,12,2,2,1,8,128,2,245,4,12, - 2,248,114,234,0,0,0,99,1,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,6,0,0,0,67,0,0,0, - 115,146,0,0,0,124,0,160,0,100,1,161,1,125,1,124, - 0,160,0,100,2,161,1,125,2,124,1,100,3,117,1,114, - 41,124,2,100,3,117,1,114,39,124,1,124,2,106,1,107, - 3,114,39,116,2,106,3,100,4,124,1,155,2,100,5,124, - 2,106,1,155,2,100,6,157,5,116,4,100,7,100,8,141, - 3,1,0,124,1,83,0,124,2,100,3,117,1,114,48,124, - 2,106,1,83,0,116,2,106,3,100,9,116,4,100,7,100, - 8,141,3,1,0,124,0,100,10,25,0,125,1,100,11,124, - 0,118,1,114,71,124,1,160,5,100,12,161,1,100,13,25, - 0,125,1,124,1,83,0,41,14,122,167,67,97,108,99,117, - 108,97,116,101,32,119,104,97,116,32,95,95,112,97,99,107, - 97,103,101,95,95,32,115,104,111,117,108,100,32,98,101,46, - 10,10,32,32,32,32,95,95,112,97,99,107,97,103,101,95, - 95,32,105,115,32,110,111,116,32,103,117,97,114,97,110,116, - 101,101,100,32,116,111,32,98,101,32,100,101,102,105,110,101, - 100,32,111,114,32,99,111,117,108,100,32,98,101,32,115,101, - 116,32,116,111,32,78,111,110,101,10,32,32,32,32,116,111, - 32,114,101,112,114,101,115,101,110,116,32,116,104,97,116,32, - 105,116,115,32,112,114,111,112,101,114,32,118,97,108,117,101, - 32,105,115,32,117,110,107,110,111,119,110,46,10,10,32,32, - 32,32,114,158,0,0,0,114,113,0,0,0,78,122,32,95, - 95,112,97,99,107,97,103,101,95,95,32,33,61,32,95,95, - 115,112,101,99,95,95,46,112,97,114,101,110,116,32,40,122, - 4,32,33,61,32,250,1,41,233,3,0,0,0,41,1,90, - 10,115,116,97,99,107,108,101,118,101,108,122,89,99,97,110, - 39,116,32,114,101,115,111,108,118,101,32,112,97,99,107,97, - 103,101,32,102,114,111,109,32,95,95,115,112,101,99,95,95, - 32,111,114,32,95,95,112,97,99,107,97,103,101,95,95,44, - 32,102,97,108,108,105,110,103,32,98,97,99,107,32,111,110, - 32,95,95,110,97,109,101,95,95,32,97,110,100,32,95,95, - 112,97,116,104,95,95,114,9,0,0,0,114,154,0,0,0, - 114,141,0,0,0,114,25,0,0,0,41,6,114,38,0,0, - 0,114,143,0,0,0,114,101,0,0,0,114,102,0,0,0, - 114,169,0,0,0,114,142,0,0,0,41,3,218,7,103,108, - 111,98,97,108,115,114,209,0,0,0,114,109,0,0,0,114, - 5,0,0,0,114,5,0,0,0,114,6,0,0,0,218,17, - 95,99,97,108,99,95,95,95,112,97,99,107,97,103,101,95, - 95,66,4,0,0,115,42,0,0,0,10,7,10,1,8,1, - 18,1,6,1,2,1,4,255,4,1,6,255,4,2,6,254, - 4,3,8,1,6,1,6,2,4,2,6,254,8,3,8,1, - 14,1,4,1,114,240,0,0,0,114,5,0,0,0,99,5, - 0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,5, - 0,0,0,67,0,0,0,115,174,0,0,0,124,4,100,1, - 107,2,114,9,116,0,124,0,131,1,125,5,110,18,124,1, - 100,2,117,1,114,15,124,1,110,1,105,0,125,6,116,1, - 124,6,131,1,125,7,116,0,124,0,124,7,124,4,131,3, - 125,5,124,3,115,74,124,4,100,1,107,2,114,42,116,0, - 124,0,160,2,100,3,161,1,100,1,25,0,131,1,83,0, - 124,0,115,46,124,5,83,0,116,3,124,0,131,1,116,3, - 124,0,160,2,100,3,161,1,100,1,25,0,131,1,24,0, - 125,8,116,4,106,5,124,5,106,6,100,2,116,3,124,5, - 106,6,131,1,124,8,24,0,133,2,25,0,25,0,83,0, - 116,7,124,5,100,4,131,2,114,85,116,8,124,5,124,3, - 116,0,131,3,83,0,124,5,83,0,41,5,97,215,1,0, - 0,73,109,112,111,114,116,32,97,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,84,104,101,32,39,103,108,111,98, - 97,108,115,39,32,97,114,103,117,109,101,110,116,32,105,115, - 32,117,115,101,100,32,116,111,32,105,110,102,101,114,32,119, - 104,101,114,101,32,116,104,101,32,105,109,112,111,114,116,32, - 105,115,32,111,99,99,117,114,114,105,110,103,32,102,114,111, - 109,10,32,32,32,32,116,111,32,104,97,110,100,108,101,32, - 114,101,108,97,116,105,118,101,32,105,109,112,111,114,116,115, - 46,32,84,104,101,32,39,108,111,99,97,108,115,39,32,97, - 114,103,117,109,101,110,116,32,105,115,32,105,103,110,111,114, - 101,100,46,32,84,104,101,10,32,32,32,32,39,102,114,111, - 109,108,105,115,116,39,32,97,114,103,117,109,101,110,116,32, - 115,112,101,99,105,102,105,101,115,32,119,104,97,116,32,115, - 104,111,117,108,100,32,101,120,105,115,116,32,97,115,32,97, - 116,116,114,105,98,117,116,101,115,32,111,110,32,116,104,101, - 32,109,111,100,117,108,101,10,32,32,32,32,98,101,105,110, - 103,32,105,109,112,111,114,116,101,100,32,40,101,46,103,46, - 32,96,96,102,114,111,109,32,109,111,100,117,108,101,32,105, - 109,112,111,114,116,32,60,102,114,111,109,108,105,115,116,62, - 96,96,41,46,32,32,84,104,101,32,39,108,101,118,101,108, - 39,10,32,32,32,32,97,114,103,117,109,101,110,116,32,114, - 101,112,114,101,115,101,110,116,115,32,116,104,101,32,112,97, - 99,107,97,103,101,32,108,111,99,97,116,105,111,110,32,116, - 111,32,105,109,112,111,114,116,32,102,114,111,109,32,105,110, - 32,97,32,114,101,108,97,116,105,118,101,10,32,32,32,32, - 105,109,112,111,114,116,32,40,101,46,103,46,32,96,96,102, - 114,111,109,32,46,46,112,107,103,32,105,109,112,111,114,116, - 32,109,111,100,96,96,32,119,111,117,108,100,32,104,97,118, - 101,32,97,32,39,108,101,118,101,108,39,32,111,102,32,50, - 41,46,10,10,32,32,32,32,114,25,0,0,0,78,114,141, - 0,0,0,114,154,0,0,0,41,9,114,229,0,0,0,114, - 240,0,0,0,218,9,112,97,114,116,105,116,105,111,110,114, - 208,0,0,0,114,18,0,0,0,114,105,0,0,0,114,9, - 0,0,0,114,11,0,0,0,114,234,0,0,0,41,9,114, - 20,0,0,0,114,239,0,0,0,218,6,108,111,99,97,108, - 115,114,235,0,0,0,114,210,0,0,0,114,110,0,0,0, - 90,8,103,108,111,98,97,108,115,95,114,209,0,0,0,90, - 7,99,117,116,95,111,102,102,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,218,10,95,95,105,109,112,111,114, - 116,95,95,93,4,0,0,115,30,0,0,0,8,11,10,1, - 16,2,8,1,12,1,4,1,8,3,18,1,4,1,4,1, - 26,4,30,3,10,1,12,1,4,2,114,243,0,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,67,0,0,0,115,38,0,0,0,116,0,160, - 1,124,0,161,1,125,1,124,1,100,0,117,0,114,15,116, - 2,100,1,124,0,23,0,131,1,130,1,116,3,124,1,131, - 1,83,0,41,2,78,122,25,110,111,32,98,117,105,108,116, - 45,105,110,32,109,111,100,117,108,101,32,110,97,109,101,100, - 32,41,4,114,175,0,0,0,114,183,0,0,0,114,87,0, - 0,0,114,173,0,0,0,41,2,114,20,0,0,0,114,109, + 0,0,114,170,0,0,0,90,3,0,0,115,2,0,0,0, + 10,8,122,26,70,114,111,122,101,110,73,109,112,111,114,116, + 101,114,46,108,111,97,100,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,67,0,0,0,243,10,0,0,0,116,0,160,1, + 124,1,161,1,83,0,41,1,122,45,82,101,116,117,114,110, + 32,116,104,101,32,99,111,100,101,32,111,98,106,101,99,116, + 32,102,111,114,32,116,104,101,32,102,114,111,122,101,110,32, + 109,111,100,117,108,101,46,41,2,114,64,0,0,0,114,195, + 0,0,0,114,186,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,187,0,0,0,100,3,0,0, + 243,2,0,0,0,10,4,122,23,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,103,101,116,95,99,111,100,101, + 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,114,185,0,0,0,41,2, + 122,54,82,101,116,117,114,110,32,78,111,110,101,32,97,115, + 32,102,114,111,122,101,110,32,109,111,100,117,108,101,115,32, + 100,111,32,110,111,116,32,104,97,118,101,32,115,111,117,114, + 99,101,32,99,111,100,101,46,78,114,5,0,0,0,114,186, 0,0,0,114,5,0,0,0,114,5,0,0,0,114,6,0, - 0,0,218,18,95,98,117,105,108,116,105,110,95,102,114,111, - 109,95,110,97,109,101,130,4,0,0,115,8,0,0,0,10, - 1,8,1,12,1,8,1,114,244,0,0,0,99,2,0,0, - 0,0,0,0,0,0,0,0,0,10,0,0,0,5,0,0, - 0,67,0,0,0,115,166,0,0,0,124,1,97,0,124,0, - 97,1,116,2,116,1,131,1,125,2,116,1,106,3,160,4, - 161,0,68,0,93,36,92,2,125,3,125,4,116,5,124,4, - 124,2,131,2,114,49,124,3,116,1,106,6,118,0,114,30, - 116,7,125,5,110,9,116,0,160,8,124,3,161,1,114,38, - 116,9,125,5,110,1,113,13,116,10,124,4,124,5,131,2, - 125,6,116,11,124,6,124,4,131,2,1,0,113,13,116,1, - 106,3,116,12,25,0,125,7,100,1,68,0,93,23,125,8, - 124,8,116,1,106,3,118,1,114,69,116,13,124,8,131,1, - 125,9,110,5,116,1,106,3,124,8,25,0,125,9,116,14, - 124,7,124,8,124,9,131,3,1,0,113,57,100,2,83,0, - 41,3,122,250,83,101,116,117,112,32,105,109,112,111,114,116, - 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103, - 32,110,101,101,100,101,100,32,98,117,105,108,116,45,105,110, - 32,109,111,100,117,108,101,115,32,97,110,100,32,105,110,106, - 101,99,116,105,110,103,32,116,104,101,109,10,32,32,32,32, - 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32, - 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32, - 65,115,32,115,121,115,32,105,115,32,110,101,101,100,101,100, - 32,102,111,114,32,115,121,115,46,109,111,100,117,108,101,115, - 32,97,99,99,101,115,115,32,97,110,100,32,95,105,109,112, - 32,105,115,32,110,101,101,100,101,100,32,116,111,32,108,111, - 97,100,32,98,117,105,108,116,45,105,110,10,32,32,32,32, - 109,111,100,117,108,101,115,44,32,116,104,111,115,101,32,116, - 119,111,32,109,111,100,117,108,101,115,32,109,117,115,116,32, - 98,101,32,101,120,112,108,105,99,105,116,108,121,32,112,97, - 115,115,101,100,32,105,110,46,10,10,32,32,32,32,41,3, - 114,26,0,0,0,114,101,0,0,0,114,71,0,0,0,78, - 41,15,114,64,0,0,0,114,18,0,0,0,114,3,0,0, - 0,114,105,0,0,0,218,5,105,116,101,109,115,114,216,0, - 0,0,114,86,0,0,0,114,175,0,0,0,114,98,0,0, - 0,114,193,0,0,0,114,155,0,0,0,114,161,0,0,0, - 114,9,0,0,0,114,244,0,0,0,114,12,0,0,0,41, - 10,218,10,115,121,115,95,109,111,100,117,108,101,218,11,95, - 105,109,112,95,109,111,100,117,108,101,90,11,109,111,100,117, - 108,101,95,116,121,112,101,114,20,0,0,0,114,110,0,0, - 0,114,122,0,0,0,114,109,0,0,0,90,11,115,101,108, - 102,95,109,111,100,117,108,101,90,12,98,117,105,108,116,105, - 110,95,110,97,109,101,90,14,98,117,105,108,116,105,110,95, - 109,111,100,117,108,101,114,5,0,0,0,114,5,0,0,0, - 114,6,0,0,0,218,6,95,115,101,116,117,112,137,4,0, - 0,115,40,0,0,0,4,9,4,1,8,3,18,1,10,1, - 10,1,6,1,10,1,6,1,2,2,10,1,10,1,2,128, - 10,3,8,1,10,1,10,1,10,2,14,1,4,251,114,248, - 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,38,0,0, - 0,116,0,124,0,124,1,131,2,1,0,116,1,106,2,160, - 3,116,4,161,1,1,0,116,1,106,2,160,3,116,5,161, - 1,1,0,100,1,83,0,41,2,122,48,73,110,115,116,97, - 108,108,32,105,109,112,111,114,116,101,114,115,32,102,111,114, - 32,98,117,105,108,116,105,110,32,97,110,100,32,102,114,111, - 122,101,110,32,109,111,100,117,108,101,115,78,41,6,114,248, - 0,0,0,114,18,0,0,0,114,214,0,0,0,114,132,0, - 0,0,114,175,0,0,0,114,193,0,0,0,41,2,114,246, - 0,0,0,114,247,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,218,8,95,105,110,115,116,97,108, - 108,172,4,0,0,115,6,0,0,0,10,2,12,2,16,1, - 114,249,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,1,0,0,0,4,0,0,0,67,0,0,0,115,32, - 0,0,0,100,1,100,2,108,0,125,0,124,0,97,1,124, - 0,160,2,116,3,106,4,116,5,25,0,161,1,1,0,100, - 2,83,0,41,3,122,57,73,110,115,116,97,108,108,32,105, - 109,112,111,114,116,101,114,115,32,116,104,97,116,32,114,101, - 113,117,105,114,101,32,101,120,116,101,114,110,97,108,32,102, - 105,108,101,115,121,115,116,101,109,32,97,99,99,101,115,115, - 114,25,0,0,0,78,41,6,218,26,95,102,114,111,122,101, - 110,95,105,109,112,111,114,116,108,105,98,95,101,120,116,101, - 114,110,97,108,114,139,0,0,0,114,249,0,0,0,114,18, - 0,0,0,114,105,0,0,0,114,9,0,0,0,41,1,114, - 250,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,27,95,105,110,115,116,97,108,108,95,101,120, - 116,101,114,110,97,108,95,105,109,112,111,114,116,101,114,115, - 180,4,0,0,115,6,0,0,0,8,3,4,1,20,1,114, - 251,0,0,0,114,190,0,0,0,114,0,0,0,0,114,24, - 0,0,0,41,4,78,78,114,5,0,0,0,114,25,0,0, - 0,41,54,114,10,0,0,0,114,7,0,0,0,114,26,0, - 0,0,114,101,0,0,0,114,71,0,0,0,114,139,0,0, - 0,114,17,0,0,0,114,21,0,0,0,114,66,0,0,0, - 114,37,0,0,0,114,47,0,0,0,114,22,0,0,0,114, - 23,0,0,0,114,55,0,0,0,114,57,0,0,0,114,60, - 0,0,0,114,72,0,0,0,114,74,0,0,0,114,83,0, - 0,0,114,95,0,0,0,114,100,0,0,0,114,111,0,0, - 0,114,124,0,0,0,114,125,0,0,0,114,104,0,0,0, - 114,155,0,0,0,114,161,0,0,0,114,165,0,0,0,114, - 119,0,0,0,114,106,0,0,0,114,172,0,0,0,114,173, - 0,0,0,114,107,0,0,0,114,175,0,0,0,114,193,0, - 0,0,114,200,0,0,0,114,211,0,0,0,114,213,0,0, - 0,114,215,0,0,0,114,221,0,0,0,90,15,95,69,82, - 82,95,77,83,71,95,80,82,69,70,73,88,114,223,0,0, - 0,114,226,0,0,0,218,6,111,98,106,101,99,116,114,227, - 0,0,0,114,228,0,0,0,114,229,0,0,0,114,234,0, - 0,0,114,240,0,0,0,114,243,0,0,0,114,244,0,0, - 0,114,248,0,0,0,114,249,0,0,0,114,251,0,0,0, - 114,5,0,0,0,114,5,0,0,0,114,5,0,0,0,114, - 6,0,0,0,218,8,60,109,111,100,117,108,101,62,1,0, - 0,0,115,104,0,0,0,4,0,8,22,4,9,4,1,4, - 1,4,3,8,3,8,8,4,8,4,2,16,3,14,4,14, - 77,14,21,8,16,8,37,8,17,14,11,8,8,8,11,8, - 12,8,19,14,26,16,101,10,26,14,45,8,72,8,17,8, - 17,8,30,8,36,8,45,14,15,14,80,14,85,8,13,8, - 9,10,10,8,47,4,16,8,1,8,2,6,32,8,3,10, - 16,14,15,8,37,10,27,8,37,8,7,8,35,12,8, + 0,0,114,189,0,0,0,106,3,0,0,114,188,0,0,0, + 122,25,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,114,198,0,0,0,41,1,122,46,82,101,116, + 117,114,110,32,84,114,117,101,32,105,102,32,116,104,101,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,32,105,115, + 32,97,32,112,97,99,107,97,103,101,46,41,2,114,64,0, + 0,0,90,17,105,115,95,102,114,111,122,101,110,95,112,97, + 99,107,97,103,101,114,186,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,6,0,0,0,114,128,0,0,0,112,3, + 0,0,114,199,0,0,0,122,25,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,105,115,95,112,97,99,107,97, + 103,101,114,190,0,0,0,114,0,0,0,0,41,17,114,9, + 0,0,0,114,8,0,0,0,114,1,0,0,0,114,10,0, + 0,0,114,151,0,0,0,114,191,0,0,0,114,114,0,0, + 0,114,192,0,0,0,114,183,0,0,0,114,184,0,0,0, + 114,162,0,0,0,114,163,0,0,0,114,170,0,0,0,114, + 100,0,0,0,114,187,0,0,0,114,189,0,0,0,114,128, + 0,0,0,114,5,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,114,193,0,0,0,36,3,0,0, + 115,48,0,0,0,8,0,4,2,4,7,2,2,10,1,2, + 10,12,1,2,6,12,1,2,11,10,1,2,3,10,1,2, + 8,10,1,2,9,2,1,12,1,2,4,2,1,12,1,2, + 4,2,1,16,1,114,193,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, + 0,0,0,115,32,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,100,6,83,0,41,7,218,18,95,73,109,112, + 111,114,116,76,111,99,107,67,111,110,116,101,120,116,122,36, + 67,111,110,116,101,120,116,32,109,97,110,97,103,101,114,32, + 102,111,114,32,116,104,101,32,105,109,112,111,114,116,32,108, + 111,99,107,46,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,2,0,0,0,67,0,0,0,243,12,0, + 0,0,116,0,160,1,161,0,1,0,100,1,83,0,41,2, + 122,24,65,99,113,117,105,114,101,32,116,104,101,32,105,109, + 112,111,114,116,32,108,111,99,107,46,78,41,2,114,64,0, + 0,0,114,65,0,0,0,114,52,0,0,0,114,5,0,0, + 0,114,5,0,0,0,114,6,0,0,0,114,61,0,0,0, + 125,3,0,0,243,2,0,0,0,12,2,122,28,95,73,109, + 112,111,114,116,76,111,99,107,67,111,110,116,101,120,116,46, + 95,95,101,110,116,101,114,95,95,99,4,0,0,0,0,0, + 0,0,0,0,0,0,4,0,0,0,2,0,0,0,67,0, + 0,0,114,201,0,0,0,41,2,122,60,82,101,108,101,97, + 115,101,32,116,104,101,32,105,109,112,111,114,116,32,108,111, + 99,107,32,114,101,103,97,114,100,108,101,115,115,32,111,102, + 32,97,110,121,32,114,97,105,115,101,100,32,101,120,99,101, + 112,116,105,111,110,115,46,78,41,2,114,64,0,0,0,114, + 67,0,0,0,41,4,114,33,0,0,0,218,8,101,120,99, + 95,116,121,112,101,218,9,101,120,99,95,118,97,108,117,101, + 218,13,101,120,99,95,116,114,97,99,101,98,97,99,107,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,63, + 0,0,0,129,3,0,0,114,202,0,0,0,122,27,95,73, + 109,112,111,114,116,76,111,99,107,67,111,110,116,101,120,116, + 46,95,95,101,120,105,116,95,95,78,41,6,114,9,0,0, + 0,114,8,0,0,0,114,1,0,0,0,114,10,0,0,0, + 114,61,0,0,0,114,63,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,5,0,0,0,114,6,0,0,0,114,200, + 0,0,0,121,3,0,0,115,8,0,0,0,8,0,4,2, + 8,2,12,4,114,200,0,0,0,99,3,0,0,0,0,0, + 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, + 0,0,115,64,0,0,0,124,1,160,0,100,1,124,2,100, + 2,24,0,161,2,125,3,116,1,124,3,131,1,124,2,107, + 0,114,18,116,2,100,3,131,1,130,1,124,3,100,4,25, + 0,125,4,124,0,114,30,100,5,160,3,124,4,124,0,161, + 2,83,0,124,4,83,0,41,6,122,50,82,101,115,111,108, + 118,101,32,97,32,114,101,108,97,116,105,118,101,32,109,111, + 100,117,108,101,32,110,97,109,101,32,116,111,32,97,110,32, + 97,98,115,111,108,117,116,101,32,111,110,101,46,114,141,0, + 0,0,114,42,0,0,0,122,50,97,116,116,101,109,112,116, + 101,100,32,114,101,108,97,116,105,118,101,32,105,109,112,111, + 114,116,32,98,101,121,111,110,100,32,116,111,112,45,108,101, + 118,101,108,32,112,97,99,107,97,103,101,114,25,0,0,0, + 250,5,123,125,46,123,125,41,4,218,6,114,115,112,108,105, + 116,218,3,108,101,110,114,87,0,0,0,114,50,0,0,0, + 41,5,114,20,0,0,0,218,7,112,97,99,107,97,103,101, + 218,5,108,101,118,101,108,90,4,98,105,116,115,90,4,98, + 97,115,101,114,5,0,0,0,114,5,0,0,0,114,6,0, + 0,0,218,13,95,114,101,115,111,108,118,101,95,110,97,109, + 101,134,3,0,0,115,10,0,0,0,16,2,12,1,8,1, + 8,1,20,1,114,211,0,0,0,99,3,0,0,0,0,0, + 0,0,0,0,0,0,5,0,0,0,4,0,0,0,67,0, + 0,0,115,60,0,0,0,116,0,124,0,131,1,155,0,100, + 1,157,2,125,3,116,1,160,2,124,3,116,3,161,2,1, + 0,124,0,160,4,124,1,124,2,161,2,125,4,124,4,100, + 0,117,0,114,25,100,0,83,0,116,5,124,1,124,4,131, + 2,83,0,41,2,78,122,53,46,102,105,110,100,95,115,112, + 101,99,40,41,32,110,111,116,32,102,111,117,110,100,59,32, + 102,97,108,108,105,110,103,32,98,97,99,107,32,116,111,32, + 102,105,110,100,95,109,111,100,117,108,101,40,41,41,6,114, + 7,0,0,0,114,101,0,0,0,114,102,0,0,0,114,169, + 0,0,0,114,184,0,0,0,114,104,0,0,0,41,5,218, + 6,102,105,110,100,101,114,114,20,0,0,0,114,181,0,0, + 0,114,108,0,0,0,114,122,0,0,0,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,17,95,102,105,110, + 100,95,115,112,101,99,95,108,101,103,97,99,121,143,3,0, + 0,115,12,0,0,0,14,1,12,2,12,1,8,1,4,1, + 10,1,114,213,0,0,0,99,3,0,0,0,0,0,0,0, + 0,0,0,0,10,0,0,0,10,0,0,0,67,0,0,0, + 115,24,1,0,0,116,0,106,1,125,3,124,3,100,1,117, + 0,114,11,116,2,100,2,131,1,130,1,124,3,115,19,116, + 3,160,4,100,3,116,5,161,2,1,0,124,0,116,0,106, + 6,118,0,125,4,124,3,68,0,93,111,125,5,116,7,131, + 0,143,47,1,0,122,5,124,5,106,8,125,6,87,0,110, + 27,4,0,116,9,121,64,1,0,1,0,1,0,116,10,124, + 5,124,0,124,1,131,3,125,7,124,7,100,1,117,0,114, + 62,89,0,87,0,100,1,4,0,4,0,131,3,1,0,113, + 26,89,0,110,7,119,0,124,6,124,0,124,1,124,2,131, + 3,125,7,87,0,100,1,4,0,4,0,131,3,1,0,110, + 8,49,0,115,81,119,1,1,0,1,0,1,0,89,0,1, + 0,124,7,100,1,117,1,114,137,124,4,115,133,124,0,116, + 0,106,6,118,0,114,133,116,0,106,6,124,0,25,0,125, + 8,122,5,124,8,106,11,125,9,87,0,110,13,4,0,116, + 9,121,120,1,0,1,0,1,0,124,7,6,0,89,0,2, + 0,1,0,83,0,119,0,124,9,100,1,117,0,114,129,124, + 7,2,0,1,0,83,0,124,9,2,0,1,0,83,0,124, + 7,2,0,1,0,83,0,113,26,100,1,83,0,41,4,122, + 21,70,105,110,100,32,97,32,109,111,100,117,108,101,39,115, + 32,115,112,101,99,46,78,122,53,115,121,115,46,109,101,116, + 97,95,112,97,116,104,32,105,115,32,78,111,110,101,44,32, + 80,121,116,104,111,110,32,105,115,32,108,105,107,101,108,121, + 32,115,104,117,116,116,105,110,103,32,100,111,119,110,122,22, + 115,121,115,46,109,101,116,97,95,112,97,116,104,32,105,115, + 32,101,109,112,116,121,41,12,114,18,0,0,0,218,9,109, + 101,116,97,95,112,97,116,104,114,87,0,0,0,114,101,0, + 0,0,114,102,0,0,0,114,169,0,0,0,114,105,0,0, + 0,114,200,0,0,0,114,183,0,0,0,114,2,0,0,0, + 114,213,0,0,0,114,113,0,0,0,41,10,114,20,0,0, + 0,114,181,0,0,0,114,182,0,0,0,114,214,0,0,0, + 90,9,105,115,95,114,101,108,111,97,100,114,212,0,0,0, + 114,183,0,0,0,114,109,0,0,0,114,110,0,0,0,114, + 113,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,218,10,95,102,105,110,100,95,115,112,101,99,153, + 3,0,0,115,68,0,0,0,6,2,8,1,8,2,4,3, + 12,1,10,5,8,1,8,1,2,1,10,1,12,1,12,1, + 8,1,2,1,14,250,4,5,2,254,12,5,2,128,28,248, + 8,9,14,2,10,1,2,1,10,1,12,1,12,4,2,252, + 8,6,8,1,8,2,8,2,2,239,4,19,114,215,0,0, + 0,99,3,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,5,0,0,0,67,0,0,0,115,110,0,0,0,116, + 0,124,0,116,1,131,2,115,14,116,2,100,1,160,3,116, + 4,124,0,131,1,161,1,131,1,130,1,124,2,100,2,107, + 0,114,22,116,5,100,3,131,1,130,1,124,2,100,2,107, + 4,114,41,116,0,124,1,116,1,131,2,115,35,116,2,100, + 4,131,1,130,1,124,1,115,41,116,6,100,5,131,1,130, + 1,124,0,115,51,124,2,100,2,107,2,114,53,116,5,100, + 6,131,1,130,1,100,7,83,0,100,7,83,0,41,8,122, + 28,86,101,114,105,102,121,32,97,114,103,117,109,101,110,116, + 115,32,97,114,101,32,34,115,97,110,101,34,46,122,31,109, + 111,100,117,108,101,32,110,97,109,101,32,109,117,115,116,32, + 98,101,32,115,116,114,44,32,110,111,116,32,123,125,114,25, + 0,0,0,122,18,108,101,118,101,108,32,109,117,115,116,32, + 98,101,32,62,61,32,48,122,31,95,95,112,97,99,107,97, + 103,101,95,95,32,110,111,116,32,115,101,116,32,116,111,32, + 97,32,115,116,114,105,110,103,122,54,97,116,116,101,109,112, + 116,101,100,32,114,101,108,97,116,105,118,101,32,105,109,112, + 111,114,116,32,119,105,116,104,32,110,111,32,107,110,111,119, + 110,32,112,97,114,101,110,116,32,112,97,99,107,97,103,101, + 122,17,69,109,112,116,121,32,109,111,100,117,108,101,32,110, + 97,109,101,78,41,7,218,10,105,115,105,110,115,116,97,110, + 99,101,218,3,115,116,114,218,9,84,121,112,101,69,114,114, + 111,114,114,50,0,0,0,114,3,0,0,0,218,10,86,97, + 108,117,101,69,114,114,111,114,114,87,0,0,0,169,3,114, + 20,0,0,0,114,209,0,0,0,114,210,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,218,13,95, + 115,97,110,105,116,121,95,99,104,101,99,107,200,3,0,0, + 115,24,0,0,0,10,2,18,1,8,1,8,1,8,1,10, + 1,8,1,4,1,8,1,12,2,8,1,8,255,114,221,0, + 0,0,122,16,78,111,32,109,111,100,117,108,101,32,110,97, + 109,101,100,32,122,4,123,33,114,125,99,2,0,0,0,0, + 0,0,0,0,0,0,0,9,0,0,0,8,0,0,0,67, + 0,0,0,115,16,1,0,0,100,0,125,2,124,0,160,0, + 100,1,161,1,100,2,25,0,125,3,124,3,114,64,124,3, + 116,1,106,2,118,1,114,21,116,3,124,1,124,3,131,2, + 1,0,124,0,116,1,106,2,118,0,114,31,116,1,106,2, + 124,0,25,0,83,0,116,1,106,2,124,3,25,0,125,4, + 122,5,124,4,106,4,125,2,87,0,110,22,4,0,116,5, + 121,63,1,0,1,0,1,0,116,6,100,3,23,0,160,7, + 124,0,124,3,161,2,125,5,116,8,124,5,124,0,100,4, + 141,2,100,0,130,2,119,0,116,9,124,0,124,2,131,2, + 125,6,124,6,100,0,117,0,114,82,116,8,116,6,160,7, + 124,0,161,1,124,0,100,4,141,2,130,1,116,10,124,6, + 131,1,125,7,124,3,114,134,116,1,106,2,124,3,25,0, + 125,4,124,0,160,0,100,1,161,1,100,5,25,0,125,8, + 122,9,116,11,124,4,124,8,124,7,131,3,1,0,87,0, + 124,7,83,0,4,0,116,5,121,133,1,0,1,0,1,0, + 100,6,124,3,155,2,100,7,124,8,155,2,157,4,125,5, + 116,12,160,13,124,5,116,14,161,2,1,0,89,0,124,7, + 83,0,119,0,124,7,83,0,41,8,78,114,141,0,0,0, + 114,25,0,0,0,122,23,59,32,123,33,114,125,32,105,115, + 32,110,111,116,32,97,32,112,97,99,107,97,103,101,114,19, + 0,0,0,233,2,0,0,0,122,27,67,97,110,110,111,116, + 32,115,101,116,32,97,110,32,97,116,116,114,105,98,117,116, + 101,32,111,110,32,122,18,32,102,111,114,32,99,104,105,108, + 100,32,109,111,100,117,108,101,32,41,15,114,142,0,0,0, + 114,18,0,0,0,114,105,0,0,0,114,74,0,0,0,114, + 154,0,0,0,114,2,0,0,0,218,8,95,69,82,82,95, + 77,83,71,114,50,0,0,0,218,19,77,111,100,117,108,101, + 78,111,116,70,111,117,110,100,69,114,114,111,114,114,215,0, + 0,0,114,173,0,0,0,114,12,0,0,0,114,101,0,0, + 0,114,102,0,0,0,114,169,0,0,0,41,9,114,20,0, + 0,0,218,7,105,109,112,111,114,116,95,114,181,0,0,0, + 114,143,0,0,0,90,13,112,97,114,101,110,116,95,109,111, + 100,117,108,101,114,108,0,0,0,114,109,0,0,0,114,110, + 0,0,0,90,5,99,104,105,108,100,114,5,0,0,0,114, + 5,0,0,0,114,6,0,0,0,218,23,95,102,105,110,100, + 95,97,110,100,95,108,111,97,100,95,117,110,108,111,99,107, + 101,100,219,3,0,0,115,60,0,0,0,4,1,14,1,4, + 1,10,1,10,1,10,2,10,1,10,1,2,1,10,1,12, + 1,16,1,14,1,2,254,10,3,8,1,18,1,8,2,4, + 1,10,2,14,1,2,1,14,1,4,4,12,253,16,1,14, + 1,4,1,2,253,4,3,114,226,0,0,0,99,2,0,0, + 0,0,0,0,0,0,0,0,0,4,0,0,0,8,0,0, + 0,67,0,0,0,115,128,0,0,0,116,0,124,0,131,1, + 143,31,1,0,116,1,106,2,160,3,124,0,116,4,161,2, + 125,2,124,2,116,4,117,0,114,28,116,5,124,0,124,1, + 131,2,87,0,2,0,100,1,4,0,4,0,131,3,1,0, + 83,0,87,0,100,1,4,0,4,0,131,3,1,0,110,8, + 49,0,115,38,119,1,1,0,1,0,1,0,89,0,1,0, + 124,2,100,1,117,0,114,58,100,2,160,6,124,0,161,1, + 125,3,116,7,124,3,124,0,100,3,141,2,130,1,116,8, + 124,0,131,1,1,0,124,2,83,0,41,4,122,25,70,105, + 110,100,32,97,110,100,32,108,111,97,100,32,116,104,101,32, + 109,111,100,117,108,101,46,78,122,40,105,109,112,111,114,116, + 32,111,102,32,123,125,32,104,97,108,116,101,100,59,32,78, + 111,110,101,32,105,110,32,115,121,115,46,109,111,100,117,108, + 101,115,114,19,0,0,0,41,9,114,57,0,0,0,114,18, + 0,0,0,114,105,0,0,0,114,38,0,0,0,218,14,95, + 78,69,69,68,83,95,76,79,65,68,73,78,71,114,226,0, + 0,0,114,50,0,0,0,114,224,0,0,0,114,72,0,0, + 0,41,4,114,20,0,0,0,114,225,0,0,0,114,110,0, + 0,0,114,82,0,0,0,114,5,0,0,0,114,5,0,0, + 0,114,6,0,0,0,218,14,95,102,105,110,100,95,97,110, + 100,95,108,111,97,100,254,3,0,0,115,28,0,0,0,10, + 2,14,1,8,1,8,1,16,253,2,2,28,254,8,5,2, + 1,6,1,2,255,12,2,8,2,4,1,114,228,0,0,0, + 114,25,0,0,0,99,3,0,0,0,0,0,0,0,0,0, + 0,0,3,0,0,0,4,0,0,0,67,0,0,0,115,42, + 0,0,0,116,0,124,0,124,1,124,2,131,3,1,0,124, + 2,100,1,107,4,114,16,116,1,124,0,124,1,124,2,131, + 3,125,0,116,2,124,0,116,3,131,2,83,0,41,2,97, + 50,1,0,0,73,109,112,111,114,116,32,97,110,100,32,114, + 101,116,117,114,110,32,116,104,101,32,109,111,100,117,108,101, + 32,98,97,115,101,100,32,111,110,32,105,116,115,32,110,97, + 109,101,44,32,116,104,101,32,112,97,99,107,97,103,101,32, + 116,104,101,32,99,97,108,108,32,105,115,10,32,32,32,32, + 98,101,105,110,103,32,109,97,100,101,32,102,114,111,109,44, + 32,97,110,100,32,116,104,101,32,108,101,118,101,108,32,97, + 100,106,117,115,116,109,101,110,116,46,10,10,32,32,32,32, + 84,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101, + 112,114,101,115,101,110,116,115,32,116,104,101,32,103,114,101, + 97,116,101,115,116,32,99,111,109,109,111,110,32,100,101,110, + 111,109,105,110,97,116,111,114,32,111,102,32,102,117,110,99, + 116,105,111,110,97,108,105,116,121,10,32,32,32,32,98,101, + 116,119,101,101,110,32,105,109,112,111,114,116,95,109,111,100, + 117,108,101,32,97,110,100,32,95,95,105,109,112,111,114,116, + 95,95,46,32,84,104,105,115,32,105,110,99,108,117,100,101, + 115,32,115,101,116,116,105,110,103,32,95,95,112,97,99,107, + 97,103,101,95,95,32,105,102,10,32,32,32,32,116,104,101, + 32,108,111,97,100,101,114,32,100,105,100,32,110,111,116,46, + 10,10,32,32,32,32,114,25,0,0,0,41,4,114,221,0, + 0,0,114,211,0,0,0,114,228,0,0,0,218,11,95,103, + 99,100,95,105,109,112,111,114,116,114,220,0,0,0,114,5, + 0,0,0,114,5,0,0,0,114,6,0,0,0,114,229,0, + 0,0,14,4,0,0,115,8,0,0,0,12,9,8,1,12, + 1,10,1,114,229,0,0,0,169,1,218,9,114,101,99,117, + 114,115,105,118,101,99,3,0,0,0,0,0,0,0,1,0, + 0,0,8,0,0,0,11,0,0,0,67,0,0,0,115,218, + 0,0,0,124,1,68,0,93,104,125,4,116,0,124,4,116, + 1,131,2,115,32,124,3,114,17,124,0,106,2,100,1,23, + 0,125,5,110,2,100,2,125,5,116,3,100,3,124,5,155, + 0,100,4,116,4,124,4,131,1,106,2,155,0,157,4,131, + 1,130,1,124,4,100,5,107,2,114,53,124,3,115,52,116, + 5,124,0,100,6,131,2,114,52,116,6,124,0,124,0,106, + 7,124,2,100,7,100,8,141,4,1,0,113,2,116,5,124, + 0,124,4,131,2,115,106,100,9,160,8,124,0,106,2,124, + 4,161,2,125,6,122,7,116,9,124,2,124,6,131,2,1, + 0,87,0,113,2,4,0,116,10,121,105,1,0,125,7,1, + 0,122,21,124,7,106,11,124,6,107,2,114,100,116,12,106, + 13,160,14,124,6,116,15,161,2,100,10,117,1,114,100,87, + 0,89,0,100,10,125,7,126,7,113,2,130,0,100,10,125, + 7,126,7,119,1,119,0,113,2,124,0,83,0,41,11,122, + 238,70,105,103,117,114,101,32,111,117,116,32,119,104,97,116, + 32,95,95,105,109,112,111,114,116,95,95,32,115,104,111,117, + 108,100,32,114,101,116,117,114,110,46,10,10,32,32,32,32, + 84,104,101,32,105,109,112,111,114,116,95,32,112,97,114,97, + 109,101,116,101,114,32,105,115,32,97,32,99,97,108,108,97, + 98,108,101,32,119,104,105,99,104,32,116,97,107,101,115,32, + 116,104,101,32,110,97,109,101,32,111,102,32,109,111,100,117, + 108,101,32,116,111,10,32,32,32,32,105,109,112,111,114,116, + 46,32,73,116,32,105,115,32,114,101,113,117,105,114,101,100, + 32,116,111,32,100,101,99,111,117,112,108,101,32,116,104,101, + 32,102,117,110,99,116,105,111,110,32,102,114,111,109,32,97, + 115,115,117,109,105,110,103,32,105,109,112,111,114,116,108,105, + 98,39,115,10,32,32,32,32,105,109,112,111,114,116,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,115, + 32,100,101,115,105,114,101,100,46,10,10,32,32,32,32,122, + 8,46,95,95,97,108,108,95,95,122,13,96,96,102,114,111, + 109,32,108,105,115,116,39,39,122,8,73,116,101,109,32,105, + 110,32,122,18,32,109,117,115,116,32,98,101,32,115,116,114, + 44,32,110,111,116,32,250,1,42,218,7,95,95,97,108,108, + 95,95,84,114,230,0,0,0,114,206,0,0,0,78,41,16, + 114,216,0,0,0,114,217,0,0,0,114,9,0,0,0,114, + 218,0,0,0,114,3,0,0,0,114,11,0,0,0,218,16, + 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, + 114,233,0,0,0,114,50,0,0,0,114,74,0,0,0,114, + 224,0,0,0,114,20,0,0,0,114,18,0,0,0,114,105, + 0,0,0,114,38,0,0,0,114,227,0,0,0,41,8,114, + 110,0,0,0,218,8,102,114,111,109,108,105,115,116,114,225, + 0,0,0,114,231,0,0,0,218,1,120,90,5,119,104,101, + 114,101,90,9,102,114,111,109,95,110,97,109,101,90,3,101, + 120,99,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,114,234,0,0,0,29,4,0,0,115,56,0,0,0,8, + 10,10,1,4,1,12,1,4,2,10,1,8,1,8,255,8, + 2,14,1,10,1,2,1,6,255,2,128,10,2,14,1,2, + 1,14,1,14,1,10,4,16,1,2,255,12,2,2,1,8, + 128,2,249,2,252,4,12,114,234,0,0,0,99,1,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,6,0,0, + 0,67,0,0,0,115,146,0,0,0,124,0,160,0,100,1, + 161,1,125,1,124,0,160,0,100,2,161,1,125,2,124,1, + 100,3,117,1,114,41,124,2,100,3,117,1,114,39,124,1, + 124,2,106,1,107,3,114,39,116,2,106,3,100,4,124,1, + 155,2,100,5,124,2,106,1,155,2,100,6,157,5,116,4, + 100,7,100,8,141,3,1,0,124,1,83,0,124,2,100,3, + 117,1,114,48,124,2,106,1,83,0,116,2,106,3,100,9, + 116,4,100,7,100,8,141,3,1,0,124,0,100,10,25,0, + 125,1,100,11,124,0,118,1,114,71,124,1,160,5,100,12, + 161,1,100,13,25,0,125,1,124,1,83,0,41,14,122,167, + 67,97,108,99,117,108,97,116,101,32,119,104,97,116,32,95, + 95,112,97,99,107,97,103,101,95,95,32,115,104,111,117,108, + 100,32,98,101,46,10,10,32,32,32,32,95,95,112,97,99, + 107,97,103,101,95,95,32,105,115,32,110,111,116,32,103,117, + 97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100, + 101,102,105,110,101,100,32,111,114,32,99,111,117,108,100,32, + 98,101,32,115,101,116,32,116,111,32,78,111,110,101,10,32, + 32,32,32,116,111,32,114,101,112,114,101,115,101,110,116,32, + 116,104,97,116,32,105,116,115,32,112,114,111,112,101,114,32, + 118,97,108,117,101,32,105,115,32,117,110,107,110,111,119,110, + 46,10,10,32,32,32,32,114,158,0,0,0,114,113,0,0, + 0,78,122,32,95,95,112,97,99,107,97,103,101,95,95,32, + 33,61,32,95,95,115,112,101,99,95,95,46,112,97,114,101, + 110,116,32,40,122,4,32,33,61,32,250,1,41,233,3,0, + 0,0,41,1,90,10,115,116,97,99,107,108,101,118,101,108, + 122,89,99,97,110,39,116,32,114,101,115,111,108,118,101,32, + 112,97,99,107,97,103,101,32,102,114,111,109,32,95,95,115, + 112,101,99,95,95,32,111,114,32,95,95,112,97,99,107,97, + 103,101,95,95,44,32,102,97,108,108,105,110,103,32,98,97, + 99,107,32,111,110,32,95,95,110,97,109,101,95,95,32,97, + 110,100,32,95,95,112,97,116,104,95,95,114,9,0,0,0, + 114,154,0,0,0,114,141,0,0,0,114,25,0,0,0,41, + 6,114,38,0,0,0,114,143,0,0,0,114,101,0,0,0, + 114,102,0,0,0,114,169,0,0,0,114,142,0,0,0,41, + 3,218,7,103,108,111,98,97,108,115,114,209,0,0,0,114, + 109,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, + 0,0,0,218,17,95,99,97,108,99,95,95,95,112,97,99, + 107,97,103,101,95,95,66,4,0,0,115,42,0,0,0,10, + 7,10,1,8,1,18,1,6,1,2,1,4,255,4,1,6, + 255,4,2,6,254,4,3,8,1,6,1,6,2,4,2,6, + 254,8,3,8,1,14,1,4,1,114,240,0,0,0,114,5, + 0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0, + 9,0,0,0,5,0,0,0,67,0,0,0,115,174,0,0, + 0,124,4,100,1,107,2,114,9,116,0,124,0,131,1,125, + 5,110,18,124,1,100,2,117,1,114,15,124,1,110,1,105, + 0,125,6,116,1,124,6,131,1,125,7,116,0,124,0,124, + 7,124,4,131,3,125,5,124,3,115,74,124,4,100,1,107, + 2,114,42,116,0,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,83,0,124,0,115,46,124,5,83,0,116,3,124, + 0,131,1,116,3,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,24,0,125,8,116,4,106,5,124,5,106,6,100, + 2,116,3,124,5,106,6,131,1,124,8,24,0,133,2,25, + 0,25,0,83,0,116,7,124,5,100,4,131,2,114,85,116, + 8,124,5,124,3,116,0,131,3,83,0,124,5,83,0,41, + 5,97,215,1,0,0,73,109,112,111,114,116,32,97,32,109, + 111,100,117,108,101,46,10,10,32,32,32,32,84,104,101,32, + 39,103,108,111,98,97,108,115,39,32,97,114,103,117,109,101, + 110,116,32,105,115,32,117,115,101,100,32,116,111,32,105,110, + 102,101,114,32,119,104,101,114,101,32,116,104,101,32,105,109, + 112,111,114,116,32,105,115,32,111,99,99,117,114,114,105,110, + 103,32,102,114,111,109,10,32,32,32,32,116,111,32,104,97, + 110,100,108,101,32,114,101,108,97,116,105,118,101,32,105,109, + 112,111,114,116,115,46,32,84,104,101,32,39,108,111,99,97, + 108,115,39,32,97,114,103,117,109,101,110,116,32,105,115,32, + 105,103,110,111,114,101,100,46,32,84,104,101,10,32,32,32, + 32,39,102,114,111,109,108,105,115,116,39,32,97,114,103,117, + 109,101,110,116,32,115,112,101,99,105,102,105,101,115,32,119, + 104,97,116,32,115,104,111,117,108,100,32,101,120,105,115,116, + 32,97,115,32,97,116,116,114,105,98,117,116,101,115,32,111, + 110,32,116,104,101,32,109,111,100,117,108,101,10,32,32,32, + 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, + 40,101,46,103,46,32,96,96,102,114,111,109,32,109,111,100, + 117,108,101,32,105,109,112,111,114,116,32,60,102,114,111,109, + 108,105,115,116,62,96,96,41,46,32,32,84,104,101,32,39, + 108,101,118,101,108,39,10,32,32,32,32,97,114,103,117,109, + 101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116, + 104,101,32,112,97,99,107,97,103,101,32,108,111,99,97,116, + 105,111,110,32,116,111,32,105,109,112,111,114,116,32,102,114, + 111,109,32,105,110,32,97,32,114,101,108,97,116,105,118,101, + 10,32,32,32,32,105,109,112,111,114,116,32,40,101,46,103, + 46,32,96,96,102,114,111,109,32,46,46,112,107,103,32,105, + 109,112,111,114,116,32,109,111,100,96,96,32,119,111,117,108, + 100,32,104,97,118,101,32,97,32,39,108,101,118,101,108,39, + 32,111,102,32,50,41,46,10,10,32,32,32,32,114,25,0, + 0,0,78,114,141,0,0,0,114,154,0,0,0,41,9,114, + 229,0,0,0,114,240,0,0,0,218,9,112,97,114,116,105, + 116,105,111,110,114,208,0,0,0,114,18,0,0,0,114,105, + 0,0,0,114,9,0,0,0,114,11,0,0,0,114,234,0, + 0,0,41,9,114,20,0,0,0,114,239,0,0,0,218,6, + 108,111,99,97,108,115,114,235,0,0,0,114,210,0,0,0, + 114,110,0,0,0,90,8,103,108,111,98,97,108,115,95,114, + 209,0,0,0,90,7,99,117,116,95,111,102,102,114,5,0, + 0,0,114,5,0,0,0,114,6,0,0,0,218,10,95,95, + 105,109,112,111,114,116,95,95,93,4,0,0,115,30,0,0, + 0,8,11,10,1,16,2,8,1,12,1,4,1,8,3,18, + 1,4,1,4,1,26,4,30,3,10,1,12,1,4,2,114, + 243,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,3,0,0,0,67,0,0,0,115,38,0, + 0,0,116,0,160,1,124,0,161,1,125,1,124,1,100,0, + 117,0,114,15,116,2,100,1,124,0,23,0,131,1,130,1, + 116,3,124,1,131,1,83,0,41,2,78,122,25,110,111,32, + 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,32, + 110,97,109,101,100,32,41,4,114,175,0,0,0,114,183,0, + 0,0,114,87,0,0,0,114,173,0,0,0,41,2,114,20, + 0,0,0,114,109,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,218,18,95,98,117,105,108,116,105, + 110,95,102,114,111,109,95,110,97,109,101,130,4,0,0,115, + 8,0,0,0,10,1,8,1,12,1,8,1,114,244,0,0, + 0,99,2,0,0,0,0,0,0,0,0,0,0,0,10,0, + 0,0,5,0,0,0,67,0,0,0,115,166,0,0,0,124, + 1,97,0,124,0,97,1,116,2,116,1,131,1,125,2,116, + 1,106,3,160,4,161,0,68,0,93,36,92,2,125,3,125, + 4,116,5,124,4,124,2,131,2,114,49,124,3,116,1,106, + 6,118,0,114,30,116,7,125,5,110,9,116,0,160,8,124, + 3,161,1,114,38,116,9,125,5,110,1,113,13,116,10,124, + 4,124,5,131,2,125,6,116,11,124,6,124,4,131,2,1, + 0,113,13,116,1,106,3,116,12,25,0,125,7,100,1,68, + 0,93,23,125,8,124,8,116,1,106,3,118,1,114,69,116, + 13,124,8,131,1,125,9,110,5,116,1,106,3,124,8,25, + 0,125,9,116,14,124,7,124,8,124,9,131,3,1,0,113, + 57,100,2,83,0,41,3,122,250,83,101,116,117,112,32,105, + 109,112,111,114,116,108,105,98,32,98,121,32,105,109,112,111, + 114,116,105,110,103,32,110,101,101,100,101,100,32,98,117,105, + 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,110, + 100,32,105,110,106,101,99,116,105,110,103,32,116,104,101,109, + 10,32,32,32,32,105,110,116,111,32,116,104,101,32,103,108, + 111,98,97,108,32,110,97,109,101,115,112,97,99,101,46,10, + 10,32,32,32,32,65,115,32,115,121,115,32,105,115,32,110, + 101,101,100,101,100,32,102,111,114,32,115,121,115,46,109,111, + 100,117,108,101,115,32,97,99,99,101,115,115,32,97,110,100, + 32,95,105,109,112,32,105,115,32,110,101,101,100,101,100,32, + 116,111,32,108,111,97,100,32,98,117,105,108,116,45,105,110, + 10,32,32,32,32,109,111,100,117,108,101,115,44,32,116,104, + 111,115,101,32,116,119,111,32,109,111,100,117,108,101,115,32, + 109,117,115,116,32,98,101,32,101,120,112,108,105,99,105,116, + 108,121,32,112,97,115,115,101,100,32,105,110,46,10,10,32, + 32,32,32,41,3,114,26,0,0,0,114,101,0,0,0,114, + 71,0,0,0,78,41,15,114,64,0,0,0,114,18,0,0, + 0,114,3,0,0,0,114,105,0,0,0,218,5,105,116,101, + 109,115,114,216,0,0,0,114,86,0,0,0,114,175,0,0, + 0,114,98,0,0,0,114,193,0,0,0,114,155,0,0,0, + 114,161,0,0,0,114,9,0,0,0,114,244,0,0,0,114, + 12,0,0,0,41,10,218,10,115,121,115,95,109,111,100,117, + 108,101,218,11,95,105,109,112,95,109,111,100,117,108,101,90, + 11,109,111,100,117,108,101,95,116,121,112,101,114,20,0,0, + 0,114,110,0,0,0,114,122,0,0,0,114,109,0,0,0, + 90,11,115,101,108,102,95,109,111,100,117,108,101,90,12,98, + 117,105,108,116,105,110,95,110,97,109,101,90,14,98,117,105, + 108,116,105,110,95,109,111,100,117,108,101,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,6,95,115,101,116, + 117,112,137,4,0,0,115,40,0,0,0,4,9,4,1,8, + 3,18,1,10,1,10,1,6,1,10,1,6,1,2,2,10, + 1,10,1,2,128,10,3,8,1,10,1,10,1,10,2,14, + 1,4,251,114,248,0,0,0,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, + 0,115,38,0,0,0,116,0,124,0,124,1,131,2,1,0, + 116,1,106,2,160,3,116,4,161,1,1,0,116,1,106,2, + 160,3,116,5,161,1,1,0,100,1,83,0,41,2,122,48, + 73,110,115,116,97,108,108,32,105,109,112,111,114,116,101,114, + 115,32,102,111,114,32,98,117,105,108,116,105,110,32,97,110, + 100,32,102,114,111,122,101,110,32,109,111,100,117,108,101,115, + 78,41,6,114,248,0,0,0,114,18,0,0,0,114,214,0, + 0,0,114,132,0,0,0,114,175,0,0,0,114,193,0,0, + 0,41,2,114,246,0,0,0,114,247,0,0,0,114,5,0, + 0,0,114,5,0,0,0,114,6,0,0,0,218,8,95,105, + 110,115,116,97,108,108,172,4,0,0,115,6,0,0,0,10, + 2,12,2,16,1,114,249,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,67, + 0,0,0,115,32,0,0,0,100,1,100,2,108,0,125,0, + 124,0,97,1,124,0,160,2,116,3,106,4,116,5,25,0, + 161,1,1,0,100,2,83,0,41,3,122,57,73,110,115,116, + 97,108,108,32,105,109,112,111,114,116,101,114,115,32,116,104, + 97,116,32,114,101,113,117,105,114,101,32,101,120,116,101,114, + 110,97,108,32,102,105,108,101,115,121,115,116,101,109,32,97, + 99,99,101,115,115,114,25,0,0,0,78,41,6,218,26,95, + 102,114,111,122,101,110,95,105,109,112,111,114,116,108,105,98, + 95,101,120,116,101,114,110,97,108,114,139,0,0,0,114,249, + 0,0,0,114,18,0,0,0,114,105,0,0,0,114,9,0, + 0,0,41,1,114,250,0,0,0,114,5,0,0,0,114,5, + 0,0,0,114,6,0,0,0,218,27,95,105,110,115,116,97, + 108,108,95,101,120,116,101,114,110,97,108,95,105,109,112,111, + 114,116,101,114,115,180,4,0,0,115,6,0,0,0,8,3, + 4,1,20,1,114,251,0,0,0,114,190,0,0,0,114,0, + 0,0,0,114,24,0,0,0,41,4,78,78,114,5,0,0, + 0,114,25,0,0,0,41,54,114,10,0,0,0,114,7,0, + 0,0,114,26,0,0,0,114,101,0,0,0,114,71,0,0, + 0,114,139,0,0,0,114,17,0,0,0,114,21,0,0,0, + 114,66,0,0,0,114,37,0,0,0,114,47,0,0,0,114, + 22,0,0,0,114,23,0,0,0,114,55,0,0,0,114,57, + 0,0,0,114,60,0,0,0,114,72,0,0,0,114,74,0, + 0,0,114,83,0,0,0,114,95,0,0,0,114,100,0,0, + 0,114,111,0,0,0,114,124,0,0,0,114,125,0,0,0, + 114,104,0,0,0,114,155,0,0,0,114,161,0,0,0,114, + 165,0,0,0,114,119,0,0,0,114,106,0,0,0,114,172, + 0,0,0,114,173,0,0,0,114,107,0,0,0,114,175,0, + 0,0,114,193,0,0,0,114,200,0,0,0,114,211,0,0, + 0,114,213,0,0,0,114,215,0,0,0,114,221,0,0,0, + 90,15,95,69,82,82,95,77,83,71,95,80,82,69,70,73, + 88,114,223,0,0,0,114,226,0,0,0,218,6,111,98,106, + 101,99,116,114,227,0,0,0,114,228,0,0,0,114,229,0, + 0,0,114,234,0,0,0,114,240,0,0,0,114,243,0,0, + 0,114,244,0,0,0,114,248,0,0,0,114,249,0,0,0, + 114,251,0,0,0,114,5,0,0,0,114,5,0,0,0,114, + 5,0,0,0,114,6,0,0,0,218,8,60,109,111,100,117, + 108,101,62,1,0,0,0,115,104,0,0,0,4,0,8,22, + 4,9,4,1,4,1,4,3,8,3,8,8,4,8,4,2, + 16,3,14,4,14,77,14,21,8,16,8,37,8,17,14,11, + 8,8,8,11,8,12,8,19,14,26,16,101,10,26,14,45, + 8,72,8,17,8,17,8,30,8,36,8,45,14,15,14,80, + 14,85,8,13,8,9,10,10,8,47,4,16,8,1,8,2, + 6,32,8,3,10,16,14,15,8,37,10,27,8,37,8,7, + 8,35,12,8, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 8f4eeb0e53483a..bd4d95a61e00a2 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -82,7 +82,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 111,122,101,110,32,105,109,112,111,114,116,108,105,98,46,95, 98,111,111,116,115,116,114,97,112,95,101,120,116,101,114,110, 97,108,62,218,9,60,103,101,110,101,120,112,114,62,46,0, - 0,0,115,4,0,0,0,6,128,22,0,114,9,0,0,0, + 0,0,115,4,0,0,0,2,128,26,0,114,9,0,0,0, 218,0,99,1,0,0,0,0,0,0,0,0,0,0,0,2, 0,0,0,4,0,0,0,67,0,0,0,115,22,0,0,0, 104,0,124,0,93,7,125,1,100,0,124,1,155,0,157,2, @@ -102,715 +102,647 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 89,84,72,79,78,67,65,83,69,79,75,99,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, 19,0,0,0,115,20,0,0,0,116,0,106,1,106,2,12, - 0,111,9,136,0,116,3,106,4,118,0,83,0,41,2,122, + 0,111,9,136,0,116,3,106,4,118,0,83,0,41,1,122, 94,84,114,117,101,32,105,102,32,102,105,108,101,110,97,109, 101,115,32,109,117,115,116,32,98,101,32,99,104,101,99,107, 101,100,32,99,97,115,101,45,105,110,115,101,110,115,105,116, 105,118,101,108,121,32,97,110,100,32,105,103,110,111,114,101, 32,101,110,118,105,114,111,110,109,101,110,116,32,102,108,97, - 103,115,32,97,114,101,32,110,111,116,32,115,101,116,46,78, - 41,5,218,3,115,121,115,218,5,102,108,97,103,115,218,18, - 105,103,110,111,114,101,95,101,110,118,105,114,111,110,109,101, - 110,116,218,3,95,111,115,90,7,101,110,118,105,114,111,110, - 114,7,0,0,0,169,1,218,3,107,101,121,114,7,0,0, - 0,114,8,0,0,0,218,11,95,114,101,108,97,120,95,99, - 97,115,101,67,0,0,0,243,2,0,0,0,20,2,122,37, + 103,115,32,97,114,101,32,110,111,116,32,115,101,116,46,41, + 5,218,3,115,121,115,218,5,102,108,97,103,115,218,18,105, + 103,110,111,114,101,95,101,110,118,105,114,111,110,109,101,110, + 116,218,3,95,111,115,90,7,101,110,118,105,114,111,110,114, + 7,0,0,0,169,1,218,3,107,101,121,114,7,0,0,0, + 114,8,0,0,0,218,11,95,114,101,108,97,120,95,99,97, + 115,101,67,0,0,0,243,2,0,0,0,20,2,122,37,95, + 109,97,107,101,95,114,101,108,97,120,95,99,97,115,101,46, + 60,108,111,99,97,108,115,62,46,95,114,101,108,97,120,95, + 99,97,115,101,99,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,83,0,0,0,243,4,0, + 0,0,100,1,83,0,41,2,122,53,84,114,117,101,32,105, + 102,32,102,105,108,101,110,97,109,101,115,32,109,117,115,116, + 32,98,101,32,99,104,101,99,107,101,100,32,99,97,115,101, + 45,105,110,115,101,110,115,105,116,105,118,101,108,121,46,70, + 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,114,21,0,0,0,71,0, + 0,0,243,2,0,0,0,4,2,41,5,114,15,0,0,0, + 218,8,112,108,97,116,102,111,114,109,218,10,115,116,97,114, + 116,115,119,105,116,104,218,27,95,67,65,83,69,95,73,78, + 83,69,78,83,73,84,73,86,69,95,80,76,65,84,70,79, + 82,77,83,218,35,95,67,65,83,69,95,73,78,83,69,78, + 83,73,84,73,86,69,95,80,76,65,84,70,79,82,77,83, + 95,83,84,82,95,75,69,89,41,1,114,21,0,0,0,114, + 7,0,0,0,114,19,0,0,0,114,8,0,0,0,218,16, 95,109,97,107,101,95,114,101,108,97,120,95,99,97,115,101, - 46,60,108,111,99,97,108,115,62,46,95,114,101,108,97,120, - 95,99,97,115,101,99,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,1,0,0,0,83,0,0,0,243,4, - 0,0,0,100,1,83,0,41,3,122,53,84,114,117,101,32, - 105,102,32,102,105,108,101,110,97,109,101,115,32,109,117,115, - 116,32,98,101,32,99,104,101,99,107,101,100,32,99,97,115, - 101,45,105,110,115,101,110,115,105,116,105,118,101,108,121,46, - 70,78,114,7,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,21,0,0,0, - 71,0,0,0,243,2,0,0,0,4,2,41,5,114,15,0, - 0,0,218,8,112,108,97,116,102,111,114,109,218,10,115,116, - 97,114,116,115,119,105,116,104,218,27,95,67,65,83,69,95, - 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, - 70,79,82,77,83,218,35,95,67,65,83,69,95,73,78,83, - 69,78,83,73,84,73,86,69,95,80,76,65,84,70,79,82, - 77,83,95,83,84,82,95,75,69,89,41,1,114,21,0,0, - 0,114,7,0,0,0,114,19,0,0,0,114,8,0,0,0, - 218,16,95,109,97,107,101,95,114,101,108,97,120,95,99,97, - 115,101,60,0,0,0,115,16,0,0,0,12,1,12,1,6, - 1,4,2,12,2,4,7,8,253,4,3,114,29,0,0,0, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,67,0,0,0,115,20,0,0,0,116,0, - 124,0,131,1,100,1,64,0,160,1,100,2,100,3,161,2, - 83,0,41,5,122,42,67,111,110,118,101,114,116,32,97,32, - 51,50,45,98,105,116,32,105,110,116,101,103,101,114,32,116, - 111,32,108,105,116,116,108,101,45,101,110,100,105,97,110,46, - 236,3,0,0,0,255,127,255,127,3,0,233,4,0,0,0, - 218,6,108,105,116,116,108,101,78,41,2,218,3,105,110,116, - 218,8,116,111,95,98,121,116,101,115,41,1,218,1,120,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,12, - 95,112,97,99,107,95,117,105,110,116,51,50,79,0,0,0, - 114,22,0,0,0,114,36,0,0,0,99,1,0,0,0,0, - 0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,67, - 0,0,0,243,28,0,0,0,116,0,124,0,131,1,100,1, - 107,2,115,8,74,0,130,1,116,1,160,2,124,0,100,2, - 161,2,83,0,41,4,122,47,67,111,110,118,101,114,116,32, - 52,32,98,121,116,101,115,32,105,110,32,108,105,116,116,108, - 101,45,101,110,100,105,97,110,32,116,111,32,97,110,32,105, - 110,116,101,103,101,114,46,114,31,0,0,0,114,32,0,0, - 0,78,169,3,114,4,0,0,0,114,33,0,0,0,218,10, - 102,114,111,109,95,98,121,116,101,115,169,1,218,4,100,97, - 116,97,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,14,95,117,110,112,97,99,107,95,117,105,110,116,51, - 50,84,0,0,0,243,4,0,0,0,16,2,12,1,114,42, - 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,4,0,0,0,67,0,0,0,114,37,0,0, - 0,41,4,122,47,67,111,110,118,101,114,116,32,50,32,98, + 60,0,0,0,115,16,0,0,0,12,1,12,1,6,1,4, + 2,12,2,4,7,8,253,4,3,114,29,0,0,0,99,1, + 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4, + 0,0,0,67,0,0,0,115,20,0,0,0,116,0,124,0, + 131,1,100,1,64,0,160,1,100,2,100,3,161,2,83,0, + 41,4,122,42,67,111,110,118,101,114,116,32,97,32,51,50, + 45,98,105,116,32,105,110,116,101,103,101,114,32,116,111,32, + 108,105,116,116,108,101,45,101,110,100,105,97,110,46,236,3, + 0,0,0,255,127,255,127,3,0,233,4,0,0,0,218,6, + 108,105,116,116,108,101,41,2,218,3,105,110,116,218,8,116, + 111,95,98,121,116,101,115,41,1,218,1,120,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,12,95,112,97, + 99,107,95,117,105,110,116,51,50,79,0,0,0,114,22,0, + 0,0,114,36,0,0,0,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,4,0,0,0,67,0,0,0, + 243,28,0,0,0,116,0,124,0,131,1,100,1,107,2,115, + 8,74,0,130,1,116,1,160,2,124,0,100,2,161,2,83, + 0,41,3,122,47,67,111,110,118,101,114,116,32,52,32,98, 121,116,101,115,32,105,110,32,108,105,116,116,108,101,45,101, 110,100,105,97,110,32,116,111,32,97,110,32,105,110,116,101, - 103,101,114,46,233,2,0,0,0,114,32,0,0,0,78,114, - 38,0,0,0,114,40,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,14,95,117,110,112,97,99, - 107,95,117,105,110,116,49,54,89,0,0,0,114,43,0,0, - 0,114,45,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,5,0,0,0,4,0,0,0,71,0,0,0,115, - 228,0,0,0,124,0,115,4,100,1,83,0,116,0,124,0, - 131,1,100,2,107,2,114,14,124,0,100,3,25,0,83,0, - 100,1,125,1,103,0,125,2,116,1,116,2,106,3,124,0, - 131,2,68,0,93,61,92,2,125,3,125,4,124,3,160,4, - 116,5,161,1,115,38,124,3,160,6,116,5,161,1,114,51, - 124,3,160,7,116,8,161,1,112,44,124,1,125,1,116,9, - 124,4,23,0,103,1,125,2,113,24,124,3,160,6,100,4, - 161,1,114,76,124,1,160,10,161,0,124,3,160,10,161,0, - 107,3,114,70,124,3,125,1,124,4,103,1,125,2,113,24, - 124,2,160,11,124,4,161,1,1,0,113,24,124,3,112,79, - 124,1,125,1,124,2,160,11,124,4,161,1,1,0,113,24, - 100,5,100,6,132,0,124,2,68,0,131,1,125,2,116,0, - 124,2,131,1,100,2,107,2,114,107,124,2,100,3,25,0, - 115,107,124,1,116,9,23,0,83,0,124,1,116,9,160,12, - 124,2,161,1,23,0,83,0,41,8,250,31,82,101,112,108, + 103,101,114,46,114,31,0,0,0,114,32,0,0,0,169,3, + 114,4,0,0,0,114,33,0,0,0,218,10,102,114,111,109, + 95,98,121,116,101,115,169,1,218,4,100,97,116,97,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,14,95, + 117,110,112,97,99,107,95,117,105,110,116,51,50,84,0,0, + 0,243,4,0,0,0,16,2,12,1,114,42,0,0,0,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 4,0,0,0,67,0,0,0,114,37,0,0,0,41,3,122, + 47,67,111,110,118,101,114,116,32,50,32,98,121,116,101,115, + 32,105,110,32,108,105,116,116,108,101,45,101,110,100,105,97, + 110,32,116,111,32,97,110,32,105,110,116,101,103,101,114,46, + 233,2,0,0,0,114,32,0,0,0,114,38,0,0,0,114, + 40,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,14,95,117,110,112,97,99,107,95,117,105,110, + 116,49,54,89,0,0,0,114,43,0,0,0,114,45,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,0,4,0,0,0,71,0,0,0,115,228,0,0,0,124, + 0,115,4,100,1,83,0,116,0,124,0,131,1,100,2,107, + 2,114,14,124,0,100,3,25,0,83,0,100,1,125,1,103, + 0,125,2,116,1,116,2,106,3,124,0,131,2,68,0,93, + 61,92,2,125,3,125,4,124,3,160,4,116,5,161,1,115, + 38,124,3,160,6,116,5,161,1,114,51,124,3,160,7,116, + 8,161,1,112,44,124,1,125,1,116,9,124,4,23,0,103, + 1,125,2,113,24,124,3,160,6,100,4,161,1,114,76,124, + 1,160,10,161,0,124,3,160,10,161,0,107,3,114,70,124, + 3,125,1,124,4,103,1,125,2,113,24,124,2,160,11,124, + 4,161,1,1,0,113,24,124,3,112,79,124,1,125,1,124, + 2,160,11,124,4,161,1,1,0,113,24,100,5,100,6,132, + 0,124,2,68,0,131,1,125,2,116,0,124,2,131,1,100, + 2,107,2,114,107,124,2,100,3,25,0,115,107,124,1,116, + 9,23,0,83,0,124,1,116,9,160,12,124,2,161,1,23, + 0,83,0,41,7,250,31,82,101,112,108,97,99,101,109,101, + 110,116,32,102,111,114,32,111,115,46,112,97,116,104,46,106, + 111,105,110,40,41,46,114,10,0,0,0,114,3,0,0,0, + 114,0,0,0,0,114,11,0,0,0,99,1,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,83, + 0,0,0,243,26,0,0,0,103,0,124,0,93,9,125,1, + 124,1,114,2,124,1,160,0,116,1,161,1,145,2,113,2, + 83,0,114,7,0,0,0,169,2,218,6,114,115,116,114,105, + 112,218,15,112,97,116,104,95,115,101,112,97,114,97,116,111, + 114,115,169,2,114,5,0,0,0,218,1,112,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,10,60,108,105, + 115,116,99,111,109,112,62,119,0,0,0,115,2,0,0,0, + 26,0,250,30,95,112,97,116,104,95,106,111,105,110,46,60, + 108,111,99,97,108,115,62,46,60,108,105,115,116,99,111,109, + 112,62,41,13,114,4,0,0,0,218,3,109,97,112,114,18, + 0,0,0,218,15,95,112,97,116,104,95,115,112,108,105,116, + 114,111,111,116,114,26,0,0,0,218,14,112,97,116,104,95, + 115,101,112,95,116,117,112,108,101,218,8,101,110,100,115,119, + 105,116,104,114,49,0,0,0,114,50,0,0,0,218,8,112, + 97,116,104,95,115,101,112,218,8,99,97,115,101,102,111,108, + 100,218,6,97,112,112,101,110,100,218,4,106,111,105,110,41, + 5,218,10,112,97,116,104,95,112,97,114,116,115,218,4,114, + 111,111,116,218,4,112,97,116,104,90,8,110,101,119,95,114, + 111,111,116,218,4,116,97,105,108,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,218,10,95,112,97,116,104,95, + 106,111,105,110,96,0,0,0,115,42,0,0,0,4,2,4, + 1,12,1,8,1,4,1,4,1,20,1,20,1,14,1,12, + 1,10,1,16,1,4,3,8,1,12,2,8,2,12,1,14, + 1,20,1,8,2,14,1,114,67,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, + 0,71,0,0,0,115,20,0,0,0,116,0,160,1,100,1, + 100,2,132,0,124,0,68,0,131,1,161,1,83,0,41,3, + 114,46,0,0,0,99,1,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,5,0,0,0,83,0,0,0,114,47, + 0,0,0,114,7,0,0,0,114,48,0,0,0,41,2,114, + 5,0,0,0,218,4,112,97,114,116,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,114,53,0,0,0,128,0, + 0,0,115,6,0,0,0,6,0,4,1,16,255,114,54,0, + 0,0,41,2,114,59,0,0,0,114,62,0,0,0,41,1, + 114,63,0,0,0,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,114,67,0,0,0,126,0,0,0,115,6,0, + 0,0,10,2,2,1,8,255,99,1,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,3,0,0, + 0,115,66,0,0,0,116,0,135,0,102,1,100,1,100,2, + 132,8,116,1,68,0,131,1,131,1,125,1,124,1,100,3, + 107,0,114,19,100,4,136,0,102,2,83,0,136,0,100,5, + 124,1,133,2,25,0,136,0,124,1,100,6,23,0,100,5, + 133,2,25,0,102,2,83,0,41,7,122,32,82,101,112,108, 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, - 97,116,104,46,106,111,105,110,40,41,46,114,10,0,0,0, - 114,3,0,0,0,114,0,0,0,0,114,11,0,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 5,0,0,0,83,0,0,0,243,26,0,0,0,103,0,124, - 0,93,9,125,1,124,1,114,2,124,1,160,0,116,1,161, - 1,145,2,113,2,83,0,114,7,0,0,0,169,2,218,6, - 114,115,116,114,105,112,218,15,112,97,116,104,95,115,101,112, - 97,114,97,116,111,114,115,169,2,114,5,0,0,0,218,1, - 112,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 218,10,60,108,105,115,116,99,111,109,112,62,119,0,0,0, - 115,2,0,0,0,26,0,250,30,95,112,97,116,104,95,106, - 111,105,110,46,60,108,111,99,97,108,115,62,46,60,108,105, - 115,116,99,111,109,112,62,78,41,13,114,4,0,0,0,218, - 3,109,97,112,114,18,0,0,0,218,15,95,112,97,116,104, - 95,115,112,108,105,116,114,111,111,116,114,26,0,0,0,218, - 14,112,97,116,104,95,115,101,112,95,116,117,112,108,101,218, - 8,101,110,100,115,119,105,116,104,114,49,0,0,0,114,50, - 0,0,0,218,8,112,97,116,104,95,115,101,112,218,8,99, - 97,115,101,102,111,108,100,218,6,97,112,112,101,110,100,218, - 4,106,111,105,110,41,5,218,10,112,97,116,104,95,112,97, - 114,116,115,218,4,114,111,111,116,218,4,112,97,116,104,90, - 8,110,101,119,95,114,111,111,116,218,4,116,97,105,108,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,10, - 95,112,97,116,104,95,106,111,105,110,96,0,0,0,115,42, - 0,0,0,4,2,4,1,12,1,8,1,4,1,4,1,20, - 1,20,1,14,1,12,1,10,1,16,1,4,3,8,1,12, - 2,8,2,12,1,14,1,20,1,8,2,14,1,114,67,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,4,0,0,0,71,0,0,0,115,20,0,0,0, - 116,0,160,1,100,1,100,2,132,0,124,0,68,0,131,1, - 161,1,83,0,41,4,114,46,0,0,0,99,1,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0, - 83,0,0,0,114,47,0,0,0,114,7,0,0,0,114,48, - 0,0,0,41,2,114,5,0,0,0,218,4,112,97,114,116, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 53,0,0,0,128,0,0,0,115,6,0,0,0,6,0,6, - 1,14,255,114,54,0,0,0,78,41,2,114,59,0,0,0, - 114,62,0,0,0,41,1,114,63,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,67,0,0,0, - 126,0,0,0,115,6,0,0,0,10,2,2,1,8,255,99, - 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,3,0,0,0,115,66,0,0,0,116,0,135, - 0,102,1,100,1,100,2,132,8,116,1,68,0,131,1,131, - 1,125,1,124,1,100,3,107,0,114,19,100,4,136,0,102, - 2,83,0,136,0,100,5,124,1,133,2,25,0,136,0,124, - 1,100,6,23,0,100,5,133,2,25,0,102,2,83,0,41, - 7,122,32,82,101,112,108,97,99,101,109,101,110,116,32,102, - 111,114,32,111,115,46,112,97,116,104,46,115,112,108,105,116, - 40,41,46,99,1,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,4,0,0,0,51,0,0,0,115,26,0,0, - 0,129,0,124,0,93,8,125,1,136,0,160,0,124,1,161, - 1,86,0,1,0,113,2,100,0,83,0,169,1,78,41,1, - 218,5,114,102,105,110,100,114,51,0,0,0,169,1,114,65, - 0,0,0,114,7,0,0,0,114,8,0,0,0,114,9,0, - 0,0,134,0,0,0,115,4,0,0,0,6,128,20,0,122, - 30,95,112,97,116,104,95,115,112,108,105,116,46,60,108,111, - 99,97,108,115,62,46,60,103,101,110,101,120,112,114,62,114, - 0,0,0,0,114,10,0,0,0,78,114,3,0,0,0,41, - 2,218,3,109,97,120,114,50,0,0,0,41,2,114,65,0, - 0,0,218,1,105,114,7,0,0,0,114,71,0,0,0,114, - 8,0,0,0,218,11,95,112,97,116,104,95,115,112,108,105, - 116,132,0,0,0,115,8,0,0,0,22,2,8,1,8,1, - 28,1,114,74,0,0,0,99,1,0,0,0,0,0,0,0, - 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, - 115,10,0,0,0,116,0,160,1,124,0,161,1,83,0,41, - 2,122,126,83,116,97,116,32,116,104,101,32,112,97,116,104, - 46,10,10,32,32,32,32,77,97,100,101,32,97,32,115,101, - 112,97,114,97,116,101,32,102,117,110,99,116,105,111,110,32, - 116,111,32,109,97,107,101,32,105,116,32,101,97,115,105,101, - 114,32,116,111,32,111,118,101,114,114,105,100,101,32,105,110, - 32,101,120,112,101,114,105,109,101,110,116,115,10,32,32,32, - 32,40,101,46,103,46,32,99,97,99,104,101,32,115,116,97, - 116,32,114,101,115,117,108,116,115,41,46,10,10,32,32,32, - 32,78,41,2,114,18,0,0,0,90,4,115,116,97,116,114, - 71,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,218,10,95,112,97,116,104,95,115,116,97,116,140, - 0,0,0,115,2,0,0,0,10,7,114,75,0,0,0,99, - 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 8,0,0,0,67,0,0,0,115,48,0,0,0,122,6,116, - 0,124,0,131,1,125,2,87,0,110,9,4,0,116,1,121, - 23,1,0,1,0,1,0,89,0,100,1,83,0,124,2,106, - 2,100,2,64,0,124,1,107,2,83,0,119,0,41,4,122, - 49,84,101,115,116,32,119,104,101,116,104,101,114,32,116,104, - 101,32,112,97,116,104,32,105,115,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,109,111,100,101,32,116,121,112, - 101,46,70,105,0,240,0,0,78,41,3,114,75,0,0,0, - 218,7,79,83,69,114,114,111,114,218,7,115,116,95,109,111, - 100,101,41,3,114,65,0,0,0,218,4,109,111,100,101,90, - 9,115,116,97,116,95,105,110,102,111,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,218,18,95,112,97,116,104, - 95,105,115,95,109,111,100,101,95,116,121,112,101,150,0,0, - 0,115,12,0,0,0,2,2,12,1,12,1,6,1,14,1, - 2,254,114,79,0,0,0,99,1,0,0,0,0,0,0,0, + 97,116,104,46,115,112,108,105,116,40,41,46,99,1,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, + 0,51,0,0,0,115,26,0,0,0,129,0,124,0,93,8, + 125,1,136,0,160,0,124,1,161,1,86,0,1,0,113,2, + 100,0,83,0,169,1,78,41,1,218,5,114,102,105,110,100, + 114,51,0,0,0,169,1,114,65,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,9,0,0,0,134,0,0,0,115, + 4,0,0,0,2,128,24,0,122,30,95,112,97,116,104,95, + 115,112,108,105,116,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,114,0,0,0,0,114,10,0, + 0,0,78,114,3,0,0,0,41,2,218,3,109,97,120,114, + 50,0,0,0,41,2,114,65,0,0,0,218,1,105,114,7, + 0,0,0,114,71,0,0,0,114,8,0,0,0,218,11,95, + 112,97,116,104,95,115,112,108,105,116,132,0,0,0,115,8, + 0,0,0,22,2,8,1,8,1,28,1,114,74,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,10,0,0,0,116,0, + 160,1,124,0,161,1,83,0,41,1,122,126,83,116,97,116, + 32,116,104,101,32,112,97,116,104,46,10,10,32,32,32,32, + 77,97,100,101,32,97,32,115,101,112,97,114,97,116,101,32, + 102,117,110,99,116,105,111,110,32,116,111,32,109,97,107,101, + 32,105,116,32,101,97,115,105,101,114,32,116,111,32,111,118, + 101,114,114,105,100,101,32,105,110,32,101,120,112,101,114,105, + 109,101,110,116,115,10,32,32,32,32,40,101,46,103,46,32, + 99,97,99,104,101,32,115,116,97,116,32,114,101,115,117,108, + 116,115,41,46,10,10,32,32,32,32,41,2,114,18,0,0, + 0,90,4,115,116,97,116,114,71,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,10,95,112,97, + 116,104,95,115,116,97,116,140,0,0,0,115,2,0,0,0, + 10,7,114,75,0,0,0,99,2,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,8,0,0,0,67,0,0,0, + 115,48,0,0,0,122,6,116,0,124,0,131,1,125,2,87, + 0,110,10,4,0,116,1,121,16,1,0,1,0,1,0,89, + 0,100,1,83,0,119,0,124,2,106,2,100,2,64,0,124, + 1,107,2,83,0,41,3,122,49,84,101,115,116,32,119,104, + 101,116,104,101,114,32,116,104,101,32,112,97,116,104,32,105, + 115,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, + 109,111,100,101,32,116,121,112,101,46,70,105,0,240,0,0, + 41,3,114,75,0,0,0,218,7,79,83,69,114,114,111,114, + 218,7,115,116,95,109,111,100,101,41,3,114,65,0,0,0, + 218,4,109,111,100,101,90,9,115,116,97,116,95,105,110,102, + 111,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, + 218,18,95,112,97,116,104,95,105,115,95,109,111,100,101,95, + 116,121,112,101,150,0,0,0,115,12,0,0,0,2,2,12, + 1,12,1,6,1,2,255,14,2,114,79,0,0,0,99,1, + 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3, + 0,0,0,67,0,0,0,115,10,0,0,0,116,0,124,0, + 100,1,131,2,83,0,41,2,122,31,82,101,112,108,97,99, + 101,109,101,110,116,32,102,111,114,32,111,115,46,112,97,116, + 104,46,105,115,102,105,108,101,46,105,0,128,0,0,41,1, + 114,79,0,0,0,114,71,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,218,12,95,112,97,116,104, + 95,105,115,102,105,108,101,159,0,0,0,243,2,0,0,0, + 10,2,114,80,0,0,0,99,1,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, - 115,10,0,0,0,116,0,124,0,100,1,131,2,83,0,41, - 3,122,31,82,101,112,108,97,99,101,109,101,110,116,32,102, - 111,114,32,111,115,46,112,97,116,104,46,105,115,102,105,108, - 101,46,105,0,128,0,0,78,41,1,114,79,0,0,0,114, + 115,22,0,0,0,124,0,115,6,116,0,160,1,161,0,125, + 0,116,2,124,0,100,1,131,2,83,0,41,2,122,30,82, + 101,112,108,97,99,101,109,101,110,116,32,102,111,114,32,111, + 115,46,112,97,116,104,46,105,115,100,105,114,46,105,0,64, + 0,0,41,3,114,18,0,0,0,218,6,103,101,116,99,119, + 100,114,79,0,0,0,114,71,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,11,95,112,97,116, + 104,95,105,115,100,105,114,164,0,0,0,115,6,0,0,0, + 4,2,8,1,10,1,114,83,0,0,0,99,1,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 67,0,0,0,115,62,0,0,0,124,0,115,4,100,1,83, + 0,116,0,160,1,124,0,161,1,100,2,25,0,160,2,100, + 3,100,4,161,2,125,1,116,3,124,1,131,1,100,5,107, + 4,111,30,124,1,160,4,100,6,161,1,112,30,124,1,160, + 5,100,4,161,1,83,0,41,7,250,30,82,101,112,108,97, + 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, + 116,104,46,105,115,97,98,115,46,70,114,0,0,0,0,114, + 2,0,0,0,114,1,0,0,0,114,3,0,0,0,122,2, + 92,92,41,6,114,18,0,0,0,114,56,0,0,0,218,7, + 114,101,112,108,97,99,101,114,4,0,0,0,114,26,0,0, + 0,114,58,0,0,0,41,2,114,65,0,0,0,114,64,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,218,11,95,112,97,116,104,95,105,115,97,98,115,172,0, + 0,0,115,8,0,0,0,4,2,4,1,22,1,32,1,114, + 86,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,10,0, + 0,0,124,0,160,0,116,1,161,1,83,0,41,1,114,84, + 0,0,0,41,2,114,26,0,0,0,114,50,0,0,0,114, 71,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,218,12,95,112,97,116,104,95,105,115,102,105,108, - 101,159,0,0,0,243,2,0,0,0,10,2,114,80,0,0, - 0,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,22,0,0,0,124, - 0,115,6,116,0,160,1,161,0,125,0,116,2,124,0,100, - 1,131,2,83,0,41,3,122,30,82,101,112,108,97,99,101, - 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, - 46,105,115,100,105,114,46,105,0,64,0,0,78,41,3,114, - 18,0,0,0,218,6,103,101,116,99,119,100,114,79,0,0, - 0,114,71,0,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,11,95,112,97,116,104,95,105,115,100, - 105,114,164,0,0,0,115,6,0,0,0,4,2,8,1,10, - 1,114,83,0,0,0,99,1,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,67,0,0,0,115, - 62,0,0,0,124,0,115,4,100,1,83,0,116,0,160,1, - 124,0,161,1,100,2,25,0,160,2,100,3,100,4,161,2, - 125,1,116,3,124,1,131,1,100,5,107,4,111,30,124,1, - 160,4,100,6,161,1,112,30,124,1,160,5,100,4,161,1, - 83,0,41,8,250,30,82,101,112,108,97,99,101,109,101,110, - 116,32,102,111,114,32,111,115,46,112,97,116,104,46,105,115, - 97,98,115,46,70,114,0,0,0,0,114,2,0,0,0,114, - 1,0,0,0,114,3,0,0,0,122,2,92,92,78,41,6, - 114,18,0,0,0,114,56,0,0,0,218,7,114,101,112,108, - 97,99,101,114,4,0,0,0,114,26,0,0,0,114,58,0, - 0,0,41,2,114,65,0,0,0,114,64,0,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,218,11,95, - 112,97,116,104,95,105,115,97,98,115,172,0,0,0,115,8, - 0,0,0,4,2,4,1,22,1,32,1,114,86,0,0,0, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,10,0,0,0,124,0, - 160,0,116,1,161,1,83,0,41,2,114,84,0,0,0,78, - 41,2,114,26,0,0,0,114,50,0,0,0,114,71,0,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,86,0,0,0,180,0,0,0,114,81,0,0,0,233,182, - 1,0,0,99,3,0,0,0,0,0,0,0,0,0,0,0, - 6,0,0,0,11,0,0,0,67,0,0,0,115,170,0,0, - 0,100,1,160,0,124,0,116,1,124,0,131,1,161,2,125, - 3,116,2,160,3,124,3,116,2,106,4,116,2,106,5,66, - 0,116,2,106,6,66,0,124,2,100,2,64,0,161,3,125, - 4,122,36,116,7,160,8,124,4,100,3,161,2,143,13,125, - 5,124,5,160,9,124,1,161,1,1,0,87,0,100,4,4, - 0,4,0,131,3,1,0,110,8,49,0,115,47,119,1,1, - 0,1,0,1,0,89,0,1,0,116,2,160,10,124,3,124, - 0,161,2,1,0,87,0,100,4,83,0,4,0,116,11,121, - 84,1,0,1,0,1,0,122,7,116,2,160,12,124,3,161, - 1,1,0,87,0,130,0,4,0,116,11,121,83,1,0,1, - 0,1,0,89,0,130,0,119,0,119,0,41,5,122,162,66, - 101,115,116,45,101,102,102,111,114,116,32,102,117,110,99,116, - 105,111,110,32,116,111,32,119,114,105,116,101,32,100,97,116, - 97,32,116,111,32,97,32,112,97,116,104,32,97,116,111,109, - 105,99,97,108,108,121,46,10,32,32,32,32,66,101,32,112, - 114,101,112,97,114,101,100,32,116,111,32,104,97,110,100,108, - 101,32,97,32,70,105,108,101,69,120,105,115,116,115,69,114, - 114,111,114,32,105,102,32,99,111,110,99,117,114,114,101,110, - 116,32,119,114,105,116,105,110,103,32,111,102,32,116,104,101, - 10,32,32,32,32,116,101,109,112,111,114,97,114,121,32,102, - 105,108,101,32,105,115,32,97,116,116,101,109,112,116,101,100, - 46,250,5,123,125,46,123,125,114,87,0,0,0,90,2,119, - 98,78,41,13,218,6,102,111,114,109,97,116,218,2,105,100, - 114,18,0,0,0,90,4,111,112,101,110,90,6,79,95,69, - 88,67,76,90,7,79,95,67,82,69,65,84,90,8,79,95, - 87,82,79,78,76,89,218,3,95,105,111,218,6,70,105,108, - 101,73,79,218,5,119,114,105,116,101,114,85,0,0,0,114, - 76,0,0,0,90,6,117,110,108,105,110,107,41,6,114,65, - 0,0,0,114,41,0,0,0,114,78,0,0,0,90,8,112, - 97,116,104,95,116,109,112,90,2,102,100,218,4,102,105,108, - 101,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 218,13,95,119,114,105,116,101,95,97,116,111,109,105,99,185, - 0,0,0,115,36,0,0,0,16,5,6,1,22,1,4,255, - 2,2,14,3,12,1,28,255,18,2,12,1,2,1,12,1, - 2,3,12,254,2,1,2,1,2,254,2,253,114,95,0,0, - 0,105,111,13,0,0,114,44,0,0,0,114,32,0,0,0, - 115,2,0,0,0,13,10,90,11,95,95,112,121,99,97,99, - 104,101,95,95,122,4,111,112,116,45,122,3,46,112,121,122, - 4,46,112,121,119,122,4,46,112,121,99,41,1,218,12,111, - 112,116,105,109,105,122,97,116,105,111,110,99,2,0,0,0, - 0,0,0,0,1,0,0,0,12,0,0,0,5,0,0,0, - 67,0,0,0,115,80,1,0,0,124,1,100,1,117,1,114, - 26,116,0,160,1,100,2,116,2,161,2,1,0,124,2,100, - 1,117,1,114,20,100,3,125,3,116,3,124,3,131,1,130, - 1,124,1,114,24,100,4,110,1,100,5,125,2,116,4,160, - 5,124,0,161,1,125,0,116,6,124,0,131,1,92,2,125, - 4,125,5,124,5,160,7,100,6,161,1,92,3,125,6,125, - 7,125,8,116,8,106,9,106,10,125,9,124,9,100,1,117, - 0,114,57,116,11,100,7,131,1,130,1,100,4,160,12,124, - 6,114,63,124,6,110,1,124,8,124,7,124,9,103,3,161, - 1,125,10,124,2,100,1,117,0,114,86,116,8,106,13,106, - 14,100,8,107,2,114,82,100,4,125,2,110,4,116,8,106, - 13,106,14,125,2,116,15,124,2,131,1,125,2,124,2,100, - 4,107,3,114,112,124,2,160,16,161,0,115,105,116,17,100, - 9,160,18,124,2,161,1,131,1,130,1,100,10,160,18,124, - 10,116,19,124,2,161,3,125,10,124,10,116,20,100,8,25, - 0,23,0,125,11,116,8,106,21,100,1,117,1,114,162,116, - 22,124,4,131,1,115,134,116,23,116,4,160,24,161,0,124, - 4,131,2,125,4,124,4,100,5,25,0,100,11,107,2,114, - 152,124,4,100,8,25,0,116,25,118,1,114,152,124,4,100, - 12,100,1,133,2,25,0,125,4,116,23,116,8,106,21,124, - 4,160,26,116,25,161,1,124,11,131,3,83,0,116,23,124, - 4,116,27,124,11,131,3,83,0,41,13,97,254,2,0,0, + 0,0,0,114,86,0,0,0,180,0,0,0,114,81,0,0, + 0,233,182,1,0,0,99,3,0,0,0,0,0,0,0,0, + 0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,115, + 170,0,0,0,100,1,160,0,124,0,116,1,124,0,131,1, + 161,2,125,3,116,2,160,3,124,3,116,2,106,4,116,2, + 106,5,66,0,116,2,106,6,66,0,124,2,100,2,64,0, + 161,3,125,4,122,36,116,7,160,8,124,4,100,3,161,2, + 143,13,125,5,124,5,160,9,124,1,161,1,1,0,87,0, + 100,4,4,0,4,0,131,3,1,0,110,8,49,0,115,47, + 119,1,1,0,1,0,1,0,89,0,1,0,116,2,160,10, + 124,3,124,0,161,2,1,0,87,0,100,4,83,0,4,0, + 116,11,121,84,1,0,1,0,1,0,122,7,116,2,160,12, + 124,3,161,1,1,0,87,0,130,0,4,0,116,11,121,83, + 1,0,1,0,1,0,89,0,130,0,119,0,119,0,41,5, + 122,162,66,101,115,116,45,101,102,102,111,114,116,32,102,117, + 110,99,116,105,111,110,32,116,111,32,119,114,105,116,101,32, + 100,97,116,97,32,116,111,32,97,32,112,97,116,104,32,97, + 116,111,109,105,99,97,108,108,121,46,10,32,32,32,32,66, + 101,32,112,114,101,112,97,114,101,100,32,116,111,32,104,97, + 110,100,108,101,32,97,32,70,105,108,101,69,120,105,115,116, + 115,69,114,114,111,114,32,105,102,32,99,111,110,99,117,114, + 114,101,110,116,32,119,114,105,116,105,110,103,32,111,102,32, + 116,104,101,10,32,32,32,32,116,101,109,112,111,114,97,114, + 121,32,102,105,108,101,32,105,115,32,97,116,116,101,109,112, + 116,101,100,46,250,5,123,125,46,123,125,114,87,0,0,0, + 90,2,119,98,78,41,13,218,6,102,111,114,109,97,116,218, + 2,105,100,114,18,0,0,0,90,4,111,112,101,110,90,6, + 79,95,69,88,67,76,90,7,79,95,67,82,69,65,84,90, + 8,79,95,87,82,79,78,76,89,218,3,95,105,111,218,6, + 70,105,108,101,73,79,218,5,119,114,105,116,101,114,85,0, + 0,0,114,76,0,0,0,90,6,117,110,108,105,110,107,41, + 6,114,65,0,0,0,114,41,0,0,0,114,78,0,0,0, + 90,8,112,97,116,104,95,116,109,112,90,2,102,100,218,4, + 102,105,108,101,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,13,95,119,114,105,116,101,95,97,116,111,109, + 105,99,185,0,0,0,115,36,0,0,0,16,5,6,1,22, + 1,4,255,2,2,14,3,12,1,28,255,18,2,12,1,2, + 1,12,1,2,3,12,254,2,1,2,1,2,254,2,253,114, + 95,0,0,0,105,111,13,0,0,114,44,0,0,0,114,32, + 0,0,0,115,2,0,0,0,13,10,90,11,95,95,112,121, + 99,97,99,104,101,95,95,122,4,111,112,116,45,122,3,46, + 112,121,122,4,46,112,121,119,122,4,46,112,121,99,41,1, + 218,12,111,112,116,105,109,105,122,97,116,105,111,110,99,2, + 0,0,0,0,0,0,0,1,0,0,0,12,0,0,0,5, + 0,0,0,67,0,0,0,115,80,1,0,0,124,1,100,1, + 117,1,114,26,116,0,160,1,100,2,116,2,161,2,1,0, + 124,2,100,1,117,1,114,20,100,3,125,3,116,3,124,3, + 131,1,130,1,124,1,114,24,100,4,110,1,100,5,125,2, + 116,4,160,5,124,0,161,1,125,0,116,6,124,0,131,1, + 92,2,125,4,125,5,124,5,160,7,100,6,161,1,92,3, + 125,6,125,7,125,8,116,8,106,9,106,10,125,9,124,9, + 100,1,117,0,114,57,116,11,100,7,131,1,130,1,100,4, + 160,12,124,6,114,63,124,6,110,1,124,8,124,7,124,9, + 103,3,161,1,125,10,124,2,100,1,117,0,114,86,116,8, + 106,13,106,14,100,8,107,2,114,82,100,4,125,2,110,4, + 116,8,106,13,106,14,125,2,116,15,124,2,131,1,125,2, + 124,2,100,4,107,3,114,112,124,2,160,16,161,0,115,105, + 116,17,100,9,160,18,124,2,161,1,131,1,130,1,100,10, + 160,18,124,10,116,19,124,2,161,3,125,10,124,10,116,20, + 100,8,25,0,23,0,125,11,116,8,106,21,100,1,117,1, + 114,162,116,22,124,4,131,1,115,134,116,23,116,4,160,24, + 161,0,124,4,131,2,125,4,124,4,100,5,25,0,100,11, + 107,2,114,152,124,4,100,8,25,0,116,25,118,1,114,152, + 124,4,100,12,100,1,133,2,25,0,125,4,116,23,116,8, + 106,21,124,4,160,26,116,25,161,1,124,11,131,3,83,0, + 116,23,124,4,116,27,124,11,131,3,83,0,41,13,97,254, + 2,0,0,71,105,118,101,110,32,116,104,101,32,112,97,116, + 104,32,116,111,32,97,32,46,112,121,32,102,105,108,101,44, + 32,114,101,116,117,114,110,32,116,104,101,32,112,97,116,104, + 32,116,111,32,105,116,115,32,46,112,121,99,32,102,105,108, + 101,46,10,10,32,32,32,32,84,104,101,32,46,112,121,32, + 102,105,108,101,32,100,111,101,115,32,110,111,116,32,110,101, + 101,100,32,116,111,32,101,120,105,115,116,59,32,116,104,105, + 115,32,115,105,109,112,108,121,32,114,101,116,117,114,110,115, + 32,116,104,101,32,112,97,116,104,32,116,111,32,116,104,101, + 10,32,32,32,32,46,112,121,99,32,102,105,108,101,32,99, + 97,108,99,117,108,97,116,101,100,32,97,115,32,105,102,32, + 116,104,101,32,46,112,121,32,102,105,108,101,32,119,101,114, + 101,32,105,109,112,111,114,116,101,100,46,10,10,32,32,32, + 32,84,104,101,32,39,111,112,116,105,109,105,122,97,116,105, + 111,110,39,32,112,97,114,97,109,101,116,101,114,32,99,111, + 110,116,114,111,108,115,32,116,104,101,32,112,114,101,115,117, + 109,101,100,32,111,112,116,105,109,105,122,97,116,105,111,110, + 32,108,101,118,101,108,32,111,102,10,32,32,32,32,116,104, + 101,32,98,121,116,101,99,111,100,101,32,102,105,108,101,46, + 32,73,102,32,39,111,112,116,105,109,105,122,97,116,105,111, + 110,39,32,105,115,32,110,111,116,32,78,111,110,101,44,32, + 116,104,101,32,115,116,114,105,110,103,32,114,101,112,114,101, + 115,101,110,116,97,116,105,111,110,10,32,32,32,32,111,102, + 32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115, + 32,116,97,107,101,110,32,97,110,100,32,118,101,114,105,102, + 105,101,100,32,116,111,32,98,101,32,97,108,112,104,97,110, + 117,109,101,114,105,99,32,40,101,108,115,101,32,86,97,108, + 117,101,69,114,114,111,114,10,32,32,32,32,105,115,32,114, + 97,105,115,101,100,41,46,10,10,32,32,32,32,84,104,101, + 32,100,101,98,117,103,95,111,118,101,114,114,105,100,101,32, + 112,97,114,97,109,101,116,101,114,32,105,115,32,100,101,112, + 114,101,99,97,116,101,100,46,32,73,102,32,100,101,98,117, + 103,95,111,118,101,114,114,105,100,101,32,105,115,32,110,111, + 116,32,78,111,110,101,44,10,32,32,32,32,97,32,84,114, + 117,101,32,118,97,108,117,101,32,105,115,32,116,104,101,32, + 115,97,109,101,32,97,115,32,115,101,116,116,105,110,103,32, + 39,111,112,116,105,109,105,122,97,116,105,111,110,39,32,116, + 111,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105, + 110,103,10,32,32,32,32,119,104,105,108,101,32,97,32,70, + 97,108,115,101,32,118,97,108,117,101,32,105,115,32,101,113, + 117,105,118,97,108,101,110,116,32,116,111,32,115,101,116,116, + 105,110,103,32,39,111,112,116,105,109,105,122,97,116,105,111, + 110,39,32,116,111,32,39,49,39,46,10,10,32,32,32,32, + 73,102,32,115,121,115,46,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,46,99,97,99,104,101,95,116,97,103,32, + 105,115,32,78,111,110,101,32,116,104,101,110,32,78,111,116, + 73,109,112,108,101,109,101,110,116,101,100,69,114,114,111,114, + 32,105,115,32,114,97,105,115,101,100,46,10,10,32,32,32, + 32,78,122,70,116,104,101,32,100,101,98,117,103,95,111,118, + 101,114,114,105,100,101,32,112,97,114,97,109,101,116,101,114, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32, + 117,115,101,32,39,111,112,116,105,109,105,122,97,116,105,111, + 110,39,32,105,110,115,116,101,97,100,122,50,100,101,98,117, + 103,95,111,118,101,114,114,105,100,101,32,111,114,32,111,112, + 116,105,109,105,122,97,116,105,111,110,32,109,117,115,116,32, + 98,101,32,115,101,116,32,116,111,32,78,111,110,101,114,10, + 0,0,0,114,3,0,0,0,218,1,46,250,36,115,121,115, + 46,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46, + 99,97,99,104,101,95,116,97,103,32,105,115,32,78,111,110, + 101,114,0,0,0,0,122,24,123,33,114,125,32,105,115,32, + 110,111,116,32,97,108,112,104,97,110,117,109,101,114,105,99, + 122,7,123,125,46,123,125,123,125,114,11,0,0,0,114,44, + 0,0,0,41,28,218,9,95,119,97,114,110,105,110,103,115, + 218,4,119,97,114,110,218,18,68,101,112,114,101,99,97,116, + 105,111,110,87,97,114,110,105,110,103,218,9,84,121,112,101, + 69,114,114,111,114,114,18,0,0,0,218,6,102,115,112,97, + 116,104,114,74,0,0,0,218,10,114,112,97,114,116,105,116, + 105,111,110,114,15,0,0,0,218,14,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,218,9,99,97,99,104,101,95, + 116,97,103,218,19,78,111,116,73,109,112,108,101,109,101,110, + 116,101,100,69,114,114,111,114,114,62,0,0,0,114,16,0, + 0,0,218,8,111,112,116,105,109,105,122,101,218,3,115,116, + 114,218,7,105,115,97,108,110,117,109,218,10,86,97,108,117, + 101,69,114,114,111,114,114,89,0,0,0,218,4,95,79,80, + 84,218,17,66,89,84,69,67,79,68,69,95,83,85,70,70, + 73,88,69,83,218,14,112,121,99,97,99,104,101,95,112,114, + 101,102,105,120,114,86,0,0,0,114,67,0,0,0,114,82, + 0,0,0,114,50,0,0,0,218,6,108,115,116,114,105,112, + 218,8,95,80,89,67,65,67,72,69,41,12,114,65,0,0, + 0,90,14,100,101,98,117,103,95,111,118,101,114,114,105,100, + 101,114,96,0,0,0,218,7,109,101,115,115,97,103,101,218, + 4,104,101,97,100,114,66,0,0,0,90,4,98,97,115,101, + 114,6,0,0,0,218,4,114,101,115,116,90,3,116,97,103, + 90,15,97,108,109,111,115,116,95,102,105,108,101,110,97,109, + 101,218,8,102,105,108,101,110,97,109,101,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,17,99,97,99,104, + 101,95,102,114,111,109,95,115,111,117,114,99,101,124,1,0, + 0,115,72,0,0,0,8,18,6,1,2,1,4,255,8,2, + 4,1,8,1,12,1,10,1,12,1,16,1,8,1,8,1, + 8,1,24,1,8,1,12,1,6,1,8,2,8,1,8,1, + 8,1,14,1,14,1,12,1,10,1,8,9,14,1,24,5, + 12,1,2,4,4,1,8,1,2,1,4,253,12,5,114,121, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 10,0,0,0,5,0,0,0,67,0,0,0,115,40,1,0, + 0,116,0,106,1,106,2,100,1,117,0,114,10,116,3,100, + 2,131,1,130,1,116,4,160,5,124,0,161,1,125,0,116, + 6,124,0,131,1,92,2,125,1,125,2,100,3,125,3,116, + 0,106,7,100,1,117,1,114,51,116,0,106,7,160,8,116, + 9,161,1,125,4,124,1,160,10,124,4,116,11,23,0,161, + 1,114,51,124,1,116,12,124,4,131,1,100,1,133,2,25, + 0,125,1,100,4,125,3,124,3,115,72,116,6,124,1,131, + 1,92,2,125,1,125,5,124,5,116,13,107,3,114,72,116, + 14,116,13,155,0,100,5,124,0,155,2,157,3,131,1,130, + 1,124,2,160,15,100,6,161,1,125,6,124,6,100,7,118, + 1,114,88,116,14,100,8,124,2,155,2,157,2,131,1,130, + 1,124,6,100,9,107,2,114,132,124,2,160,16,100,6,100, + 10,161,2,100,11,25,0,125,7,124,7,160,10,116,17,161, + 1,115,112,116,14,100,12,116,17,155,2,157,2,131,1,130, + 1,124,7,116,12,116,17,131,1,100,1,133,2,25,0,125, + 8,124,8,160,18,161,0,115,132,116,14,100,13,124,7,155, + 2,100,14,157,3,131,1,130,1,124,2,160,19,100,6,161, + 1,100,15,25,0,125,9,116,20,124,1,124,9,116,21,100, + 15,25,0,23,0,131,2,83,0,41,16,97,110,1,0,0, 71,105,118,101,110,32,116,104,101,32,112,97,116,104,32,116, - 111,32,97,32,46,112,121,32,102,105,108,101,44,32,114,101, - 116,117,114,110,32,116,104,101,32,112,97,116,104,32,116,111, - 32,105,116,115,32,46,112,121,99,32,102,105,108,101,46,10, - 10,32,32,32,32,84,104,101,32,46,112,121,32,102,105,108, - 101,32,100,111,101,115,32,110,111,116,32,110,101,101,100,32, - 116,111,32,101,120,105,115,116,59,32,116,104,105,115,32,115, - 105,109,112,108,121,32,114,101,116,117,114,110,115,32,116,104, - 101,32,112,97,116,104,32,116,111,32,116,104,101,10,32,32, - 32,32,46,112,121,99,32,102,105,108,101,32,99,97,108,99, - 117,108,97,116,101,100,32,97,115,32,105,102,32,116,104,101, - 32,46,112,121,32,102,105,108,101,32,119,101,114,101,32,105, - 109,112,111,114,116,101,100,46,10,10,32,32,32,32,84,104, - 101,32,39,111,112,116,105,109,105,122,97,116,105,111,110,39, - 32,112,97,114,97,109,101,116,101,114,32,99,111,110,116,114, - 111,108,115,32,116,104,101,32,112,114,101,115,117,109,101,100, - 32,111,112,116,105,109,105,122,97,116,105,111,110,32,108,101, - 118,101,108,32,111,102,10,32,32,32,32,116,104,101,32,98, - 121,116,101,99,111,100,101,32,102,105,108,101,46,32,73,102, - 32,39,111,112,116,105,109,105,122,97,116,105,111,110,39,32, - 105,115,32,110,111,116,32,78,111,110,101,44,32,116,104,101, - 32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110, - 116,97,116,105,111,110,10,32,32,32,32,111,102,32,116,104, - 101,32,97,114,103,117,109,101,110,116,32,105,115,32,116,97, - 107,101,110,32,97,110,100,32,118,101,114,105,102,105,101,100, - 32,116,111,32,98,101,32,97,108,112,104,97,110,117,109,101, - 114,105,99,32,40,101,108,115,101,32,86,97,108,117,101,69, - 114,114,111,114,10,32,32,32,32,105,115,32,114,97,105,115, - 101,100,41,46,10,10,32,32,32,32,84,104,101,32,100,101, - 98,117,103,95,111,118,101,114,114,105,100,101,32,112,97,114, - 97,109,101,116,101,114,32,105,115,32,100,101,112,114,101,99, - 97,116,101,100,46,32,73,102,32,100,101,98,117,103,95,111, - 118,101,114,114,105,100,101,32,105,115,32,110,111,116,32,78, - 111,110,101,44,10,32,32,32,32,97,32,84,114,117,101,32, - 118,97,108,117,101,32,105,115,32,116,104,101,32,115,97,109, - 101,32,97,115,32,115,101,116,116,105,110,103,32,39,111,112, - 116,105,109,105,122,97,116,105,111,110,39,32,116,111,32,116, - 104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,10, - 32,32,32,32,119,104,105,108,101,32,97,32,70,97,108,115, - 101,32,118,97,108,117,101,32,105,115,32,101,113,117,105,118, - 97,108,101,110,116,32,116,111,32,115,101,116,116,105,110,103, - 32,39,111,112,116,105,109,105,122,97,116,105,111,110,39,32, - 116,111,32,39,49,39,46,10,10,32,32,32,32,73,102,32, + 111,32,97,32,46,112,121,99,46,32,102,105,108,101,44,32, + 114,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, + 116,111,32,105,116,115,32,46,112,121,32,102,105,108,101,46, + 10,10,32,32,32,32,84,104,101,32,46,112,121,99,32,102, + 105,108,101,32,100,111,101,115,32,110,111,116,32,110,101,101, + 100,32,116,111,32,101,120,105,115,116,59,32,116,104,105,115, + 32,115,105,109,112,108,121,32,114,101,116,117,114,110,115,32, + 116,104,101,32,112,97,116,104,32,116,111,10,32,32,32,32, + 116,104,101,32,46,112,121,32,102,105,108,101,32,99,97,108, + 99,117,108,97,116,101,100,32,116,111,32,99,111,114,114,101, + 115,112,111,110,100,32,116,111,32,116,104,101,32,46,112,121, + 99,32,102,105,108,101,46,32,32,73,102,32,112,97,116,104, + 32,100,111,101,115,10,32,32,32,32,110,111,116,32,99,111, + 110,102,111,114,109,32,116,111,32,80,69,80,32,51,49,52, + 55,47,52,56,56,32,102,111,114,109,97,116,44,32,86,97, + 108,117,101,69,114,114,111,114,32,119,105,108,108,32,98,101, + 32,114,97,105,115,101,100,46,32,73,102,10,32,32,32,32, 115,121,115,46,105,109,112,108,101,109,101,110,116,97,116,105, 111,110,46,99,97,99,104,101,95,116,97,103,32,105,115,32, 78,111,110,101,32,116,104,101,110,32,78,111,116,73,109,112, 108,101,109,101,110,116,101,100,69,114,114,111,114,32,105,115, - 32,114,97,105,115,101,100,46,10,10,32,32,32,32,78,122, - 70,116,104,101,32,100,101,98,117,103,95,111,118,101,114,114, - 105,100,101,32,112,97,114,97,109,101,116,101,114,32,105,115, - 32,100,101,112,114,101,99,97,116,101,100,59,32,117,115,101, - 32,39,111,112,116,105,109,105,122,97,116,105,111,110,39,32, - 105,110,115,116,101,97,100,122,50,100,101,98,117,103,95,111, - 118,101,114,114,105,100,101,32,111,114,32,111,112,116,105,109, - 105,122,97,116,105,111,110,32,109,117,115,116,32,98,101,32, - 115,101,116,32,116,111,32,78,111,110,101,114,10,0,0,0, - 114,3,0,0,0,218,1,46,250,36,115,121,115,46,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,46,99,97,99, - 104,101,95,116,97,103,32,105,115,32,78,111,110,101,114,0, - 0,0,0,122,24,123,33,114,125,32,105,115,32,110,111,116, - 32,97,108,112,104,97,110,117,109,101,114,105,99,122,7,123, - 125,46,123,125,123,125,114,11,0,0,0,114,44,0,0,0, - 41,28,218,9,95,119,97,114,110,105,110,103,115,218,4,119, - 97,114,110,218,18,68,101,112,114,101,99,97,116,105,111,110, - 87,97,114,110,105,110,103,218,9,84,121,112,101,69,114,114, - 111,114,114,18,0,0,0,218,6,102,115,112,97,116,104,114, - 74,0,0,0,218,10,114,112,97,114,116,105,116,105,111,110, - 114,15,0,0,0,218,14,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,218,9,99,97,99,104,101,95,116,97,103, - 218,19,78,111,116,73,109,112,108,101,109,101,110,116,101,100, - 69,114,114,111,114,114,62,0,0,0,114,16,0,0,0,218, - 8,111,112,116,105,109,105,122,101,218,3,115,116,114,218,7, - 105,115,97,108,110,117,109,218,10,86,97,108,117,101,69,114, - 114,111,114,114,89,0,0,0,218,4,95,79,80,84,218,17, - 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, - 83,218,14,112,121,99,97,99,104,101,95,112,114,101,102,105, - 120,114,86,0,0,0,114,67,0,0,0,114,82,0,0,0, - 114,50,0,0,0,218,6,108,115,116,114,105,112,218,8,95, - 80,89,67,65,67,72,69,41,12,114,65,0,0,0,90,14, - 100,101,98,117,103,95,111,118,101,114,114,105,100,101,114,96, - 0,0,0,218,7,109,101,115,115,97,103,101,218,4,104,101, - 97,100,114,66,0,0,0,90,4,98,97,115,101,114,6,0, - 0,0,218,4,114,101,115,116,90,3,116,97,103,90,15,97, - 108,109,111,115,116,95,102,105,108,101,110,97,109,101,218,8, - 102,105,108,101,110,97,109,101,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,17,99,97,99,104,101,95,102, - 114,111,109,95,115,111,117,114,99,101,124,1,0,0,115,72, - 0,0,0,8,18,6,1,2,1,4,255,8,2,4,1,8, - 1,12,1,10,1,12,1,16,1,8,1,8,1,8,1,24, - 1,8,1,12,1,6,1,8,2,8,1,8,1,8,1,14, - 1,14,1,12,1,10,1,8,9,14,1,24,5,12,1,2, - 4,4,1,8,1,2,1,4,253,12,5,114,121,0,0,0, - 99,1,0,0,0,0,0,0,0,0,0,0,0,10,0,0, - 0,5,0,0,0,67,0,0,0,115,40,1,0,0,116,0, - 106,1,106,2,100,1,117,0,114,10,116,3,100,2,131,1, - 130,1,116,4,160,5,124,0,161,1,125,0,116,6,124,0, - 131,1,92,2,125,1,125,2,100,3,125,3,116,0,106,7, - 100,1,117,1,114,51,116,0,106,7,160,8,116,9,161,1, - 125,4,124,1,160,10,124,4,116,11,23,0,161,1,114,51, - 124,1,116,12,124,4,131,1,100,1,133,2,25,0,125,1, - 100,4,125,3,124,3,115,72,116,6,124,1,131,1,92,2, - 125,1,125,5,124,5,116,13,107,3,114,72,116,14,116,13, - 155,0,100,5,124,0,155,2,157,3,131,1,130,1,124,2, - 160,15,100,6,161,1,125,6,124,6,100,7,118,1,114,88, - 116,14,100,8,124,2,155,2,157,2,131,1,130,1,124,6, - 100,9,107,2,114,132,124,2,160,16,100,6,100,10,161,2, - 100,11,25,0,125,7,124,7,160,10,116,17,161,1,115,112, - 116,14,100,12,116,17,155,2,157,2,131,1,130,1,124,7, - 116,12,116,17,131,1,100,1,133,2,25,0,125,8,124,8, - 160,18,161,0,115,132,116,14,100,13,124,7,155,2,100,14, - 157,3,131,1,130,1,124,2,160,19,100,6,161,1,100,15, - 25,0,125,9,116,20,124,1,124,9,116,21,100,15,25,0, - 23,0,131,2,83,0,41,16,97,110,1,0,0,71,105,118, - 101,110,32,116,104,101,32,112,97,116,104,32,116,111,32,97, - 32,46,112,121,99,46,32,102,105,108,101,44,32,114,101,116, - 117,114,110,32,116,104,101,32,112,97,116,104,32,116,111,32, - 105,116,115,32,46,112,121,32,102,105,108,101,46,10,10,32, - 32,32,32,84,104,101,32,46,112,121,99,32,102,105,108,101, - 32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116, - 111,32,101,120,105,115,116,59,32,116,104,105,115,32,115,105, - 109,112,108,121,32,114,101,116,117,114,110,115,32,116,104,101, - 32,112,97,116,104,32,116,111,10,32,32,32,32,116,104,101, - 32,46,112,121,32,102,105,108,101,32,99,97,108,99,117,108, - 97,116,101,100,32,116,111,32,99,111,114,114,101,115,112,111, - 110,100,32,116,111,32,116,104,101,32,46,112,121,99,32,102, - 105,108,101,46,32,32,73,102,32,112,97,116,104,32,100,111, - 101,115,10,32,32,32,32,110,111,116,32,99,111,110,102,111, - 114,109,32,116,111,32,80,69,80,32,51,49,52,55,47,52, - 56,56,32,102,111,114,109,97,116,44,32,86,97,108,117,101, - 69,114,114,111,114,32,119,105,108,108,32,98,101,32,114,97, - 105,115,101,100,46,32,73,102,10,32,32,32,32,115,121,115, - 46,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46, - 99,97,99,104,101,95,116,97,103,32,105,115,32,78,111,110, - 101,32,116,104,101,110,32,78,111,116,73,109,112,108,101,109, - 101,110,116,101,100,69,114,114,111,114,32,105,115,32,114,97, - 105,115,101,100,46,10,10,32,32,32,32,78,114,98,0,0, - 0,70,84,122,31,32,110,111,116,32,98,111,116,116,111,109, - 45,108,101,118,101,108,32,100,105,114,101,99,116,111,114,121, - 32,105,110,32,114,97,0,0,0,62,2,0,0,0,114,44, - 0,0,0,233,3,0,0,0,122,29,101,120,112,101,99,116, - 101,100,32,111,110,108,121,32,50,32,111,114,32,51,32,100, - 111,116,115,32,105,110,32,114,122,0,0,0,114,44,0,0, - 0,233,254,255,255,255,122,53,111,112,116,105,109,105,122,97, - 116,105,111,110,32,112,111,114,116,105,111,110,32,111,102,32, - 102,105,108,101,110,97,109,101,32,100,111,101,115,32,110,111, - 116,32,115,116,97,114,116,32,119,105,116,104,32,122,19,111, - 112,116,105,109,105,122,97,116,105,111,110,32,108,101,118,101, - 108,32,122,29,32,105,115,32,110,111,116,32,97,110,32,97, - 108,112,104,97,110,117,109,101,114,105,99,32,118,97,108,117, - 101,114,0,0,0,0,41,22,114,15,0,0,0,114,105,0, - 0,0,114,106,0,0,0,114,107,0,0,0,114,18,0,0, - 0,114,103,0,0,0,114,74,0,0,0,114,114,0,0,0, - 114,49,0,0,0,114,50,0,0,0,114,26,0,0,0,114, - 59,0,0,0,114,4,0,0,0,114,116,0,0,0,114,111, - 0,0,0,218,5,99,111,117,110,116,218,6,114,115,112,108, - 105,116,114,112,0,0,0,114,110,0,0,0,218,9,112,97, - 114,116,105,116,105,111,110,114,67,0,0,0,218,15,83,79, - 85,82,67,69,95,83,85,70,70,73,88,69,83,41,10,114, - 65,0,0,0,114,118,0,0,0,90,16,112,121,99,97,99, - 104,101,95,102,105,108,101,110,97,109,101,90,23,102,111,117, - 110,100,95,105,110,95,112,121,99,97,99,104,101,95,112,114, - 101,102,105,120,90,13,115,116,114,105,112,112,101,100,95,112, - 97,116,104,90,7,112,121,99,97,99,104,101,90,9,100,111, - 116,95,99,111,117,110,116,114,96,0,0,0,90,9,111,112, - 116,95,108,101,118,101,108,90,13,98,97,115,101,95,102,105, - 108,101,110,97,109,101,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,17,115,111,117,114,99,101,95,102,114, - 111,109,95,99,97,99,104,101,195,1,0,0,115,60,0,0, - 0,12,9,8,1,10,1,12,1,4,1,10,1,12,1,14, - 1,16,1,4,1,4,1,12,1,8,1,8,1,2,1,8, - 255,10,2,8,1,14,1,8,1,16,1,10,1,4,1,2, - 1,8,255,16,2,8,1,16,1,14,2,18,1,114,128,0, - 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,5, - 0,0,0,9,0,0,0,67,0,0,0,115,122,0,0,0, - 116,0,124,0,131,1,100,1,107,2,114,8,100,2,83,0, - 124,0,160,1,100,3,161,1,92,3,125,1,125,2,125,3, - 124,1,114,28,124,3,160,2,161,0,100,4,100,5,133,2, - 25,0,100,6,107,3,114,30,124,0,83,0,122,6,116,3, - 124,0,131,1,125,4,87,0,110,15,4,0,116,4,116,5, - 102,2,121,60,1,0,1,0,1,0,124,0,100,2,100,5, - 133,2,25,0,125,4,89,0,116,6,124,4,131,1,114,58, - 124,4,83,0,124,0,83,0,119,0,41,7,122,188,67,111, - 110,118,101,114,116,32,97,32,98,121,116,101,99,111,100,101, - 32,102,105,108,101,32,112,97,116,104,32,116,111,32,97,32, - 115,111,117,114,99,101,32,112,97,116,104,32,40,105,102,32, - 112,111,115,115,105,98,108,101,41,46,10,10,32,32,32,32, - 84,104,105,115,32,102,117,110,99,116,105,111,110,32,101,120, - 105,115,116,115,32,112,117,114,101,108,121,32,102,111,114,32, - 98,97,99,107,119,97,114,100,115,45,99,111,109,112,97,116, - 105,98,105,108,105,116,121,32,102,111,114,10,32,32,32,32, - 80,121,73,109,112,111,114,116,95,69,120,101,99,67,111,100, - 101,77,111,100,117,108,101,87,105,116,104,70,105,108,101,110, - 97,109,101,115,40,41,32,105,110,32,116,104,101,32,67,32, - 65,80,73,46,10,10,32,32,32,32,114,0,0,0,0,78, - 114,97,0,0,0,233,253,255,255,255,233,255,255,255,255,90, - 2,112,121,41,7,114,4,0,0,0,114,104,0,0,0,218, - 5,108,111,119,101,114,114,128,0,0,0,114,107,0,0,0, - 114,111,0,0,0,114,80,0,0,0,41,5,218,13,98,121, - 116,101,99,111,100,101,95,112,97,116,104,114,119,0,0,0, - 218,1,95,90,9,101,120,116,101,110,115,105,111,110,218,11, - 115,111,117,114,99,101,95,112,97,116,104,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,218,15,95,103,101,116, - 95,115,111,117,114,99,101,102,105,108,101,235,1,0,0,115, - 22,0,0,0,12,7,4,1,16,1,24,1,4,1,2,1, - 12,1,16,1,14,1,16,1,2,254,114,135,0,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, - 8,0,0,0,67,0,0,0,115,68,0,0,0,124,0,160, - 0,116,1,116,2,131,1,161,1,114,22,122,5,116,3,124, - 0,131,1,87,0,83,0,4,0,116,4,121,33,1,0,1, - 0,1,0,89,0,100,0,83,0,124,0,160,0,116,1,116, - 5,131,1,161,1,114,31,124,0,83,0,100,0,83,0,119, - 0,114,69,0,0,0,41,6,114,58,0,0,0,218,5,116, - 117,112,108,101,114,127,0,0,0,114,121,0,0,0,114,107, - 0,0,0,114,113,0,0,0,41,1,114,120,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,11, - 95,103,101,116,95,99,97,99,104,101,100,254,1,0,0,115, - 18,0,0,0,14,1,2,1,10,1,12,1,6,1,14,1, - 4,1,4,2,2,251,114,137,0,0,0,99,1,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,8,0,0,0, - 67,0,0,0,115,48,0,0,0,122,7,116,0,124,0,131, - 1,106,1,125,1,87,0,110,9,4,0,116,2,121,23,1, - 0,1,0,1,0,100,1,125,1,89,0,124,1,100,2,79, - 0,125,1,124,1,83,0,119,0,41,4,122,51,67,97,108, - 99,117,108,97,116,101,32,116,104,101,32,109,111,100,101,32, - 112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32, - 97,32,98,121,116,101,99,111,100,101,32,102,105,108,101,46, - 114,87,0,0,0,233,128,0,0,0,78,41,3,114,75,0, - 0,0,114,77,0,0,0,114,76,0,0,0,41,2,114,65, - 0,0,0,114,78,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,10,95,99,97,108,99,95,109, - 111,100,101,10,2,0,0,115,14,0,0,0,2,2,14,1, - 12,1,6,1,8,3,4,1,2,251,114,139,0,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 4,0,0,0,3,0,0,0,115,52,0,0,0,100,6,135, - 0,102,1,100,2,100,3,132,9,125,1,116,0,100,1,117, - 1,114,15,116,0,106,1,125,2,110,4,100,4,100,5,132, - 0,125,2,124,2,124,1,136,0,131,2,1,0,124,1,83, - 0,41,7,122,252,68,101,99,111,114,97,116,111,114,32,116, - 111,32,118,101,114,105,102,121,32,116,104,97,116,32,116,104, - 101,32,109,111,100,117,108,101,32,98,101,105,110,103,32,114, - 101,113,117,101,115,116,101,100,32,109,97,116,99,104,101,115, - 32,116,104,101,32,111,110,101,32,116,104,101,10,32,32,32, - 32,108,111,97,100,101,114,32,99,97,110,32,104,97,110,100, - 108,101,46,10,10,32,32,32,32,84,104,101,32,102,105,114, - 115,116,32,97,114,103,117,109,101,110,116,32,40,115,101,108, - 102,41,32,109,117,115,116,32,100,101,102,105,110,101,32,95, - 110,97,109,101,32,119,104,105,99,104,32,116,104,101,32,115, - 101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105, - 115,10,32,32,32,32,99,111,109,112,97,114,101,100,32,97, - 103,97,105,110,115,116,46,32,73,102,32,116,104,101,32,99, - 111,109,112,97,114,105,115,111,110,32,102,97,105,108,115,32, - 116,104,101,110,32,73,109,112,111,114,116,69,114,114,111,114, - 32,105,115,32,114,97,105,115,101,100,46,10,10,32,32,32, - 32,78,99,2,0,0,0,0,0,0,0,0,0,0,0,4, - 0,0,0,4,0,0,0,31,0,0,0,115,72,0,0,0, - 124,1,100,0,117,0,114,8,124,0,106,0,125,1,110,16, - 124,0,106,0,124,1,107,3,114,24,116,1,100,1,124,0, - 106,0,124,1,102,2,22,0,124,1,100,2,141,2,130,1, - 136,0,124,0,124,1,103,2,124,2,162,1,82,0,105,0, - 124,3,164,1,142,1,83,0,41,3,78,122,30,108,111,97, - 100,101,114,32,102,111,114,32,37,115,32,99,97,110,110,111, - 116,32,104,97,110,100,108,101,32,37,115,169,1,218,4,110, - 97,109,101,41,2,114,141,0,0,0,218,11,73,109,112,111, - 114,116,69,114,114,111,114,41,4,218,4,115,101,108,102,114, - 141,0,0,0,218,4,97,114,103,115,218,6,107,119,97,114, - 103,115,169,1,218,6,109,101,116,104,111,100,114,7,0,0, - 0,114,8,0,0,0,218,19,95,99,104,101,99,107,95,110, - 97,109,101,95,119,114,97,112,112,101,114,30,2,0,0,115, - 18,0,0,0,8,1,8,1,10,1,4,1,8,1,2,255, - 2,1,6,255,24,2,122,40,95,99,104,101,99,107,95,110, - 97,109,101,46,60,108,111,99,97,108,115,62,46,95,99,104, - 101,99,107,95,110,97,109,101,95,119,114,97,112,112,101,114, - 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, - 0,7,0,0,0,83,0,0,0,115,56,0,0,0,100,1, - 68,0,93,16,125,2,116,0,124,1,124,2,131,2,114,18, - 116,1,124,0,124,2,116,2,124,1,124,2,131,2,131,3, - 1,0,113,2,124,0,106,3,160,4,124,1,106,3,161,1, - 1,0,100,0,83,0,41,2,78,41,4,218,10,95,95,109, - 111,100,117,108,101,95,95,218,8,95,95,110,97,109,101,95, - 95,218,12,95,95,113,117,97,108,110,97,109,101,95,95,218, - 7,95,95,100,111,99,95,95,41,5,218,7,104,97,115,97, - 116,116,114,218,7,115,101,116,97,116,116,114,218,7,103,101, - 116,97,116,116,114,218,8,95,95,100,105,99,116,95,95,218, - 6,117,112,100,97,116,101,41,3,90,3,110,101,119,90,3, - 111,108,100,114,85,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,5,95,119,114,97,112,43,2, - 0,0,115,10,0,0,0,8,1,10,1,18,1,2,128,18, - 1,122,26,95,99,104,101,99,107,95,110,97,109,101,46,60, - 108,111,99,97,108,115,62,46,95,119,114,97,112,114,69,0, - 0,0,41,2,218,10,95,98,111,111,116,115,116,114,97,112, - 114,158,0,0,0,41,3,114,147,0,0,0,114,148,0,0, - 0,114,158,0,0,0,114,7,0,0,0,114,146,0,0,0, - 114,8,0,0,0,218,11,95,99,104,101,99,107,95,110,97, - 109,101,22,2,0,0,115,12,0,0,0,14,8,8,10,8, - 1,8,2,10,6,4,1,114,160,0,0,0,99,2,0,0, - 0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0, - 0,67,0,0,0,115,72,0,0,0,116,0,160,1,100,1, - 116,2,161,2,1,0,124,0,160,3,124,1,161,1,92,2, - 125,2,125,3,124,2,100,2,117,0,114,34,116,4,124,3, - 131,1,114,34,100,3,125,4,116,0,160,1,124,4,160,5, - 124,3,100,4,25,0,161,1,116,6,161,2,1,0,124,2, - 83,0,41,5,122,155,84,114,121,32,116,111,32,102,105,110, - 100,32,97,32,108,111,97,100,101,114,32,102,111,114,32,116, - 104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100, - 117,108,101,32,98,121,32,100,101,108,101,103,97,116,105,110, - 103,32,116,111,10,32,32,32,32,115,101,108,102,46,102,105, - 110,100,95,108,111,97,100,101,114,40,41,46,10,10,32,32, - 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, - 32,100,101,112,114,101,99,97,116,101,100,32,105,110,32,102, - 97,118,111,114,32,111,102,32,102,105,110,100,101,114,46,102, - 105,110,100,95,115,112,101,99,40,41,46,10,10,32,32,32, - 32,122,90,102,105,110,100,95,109,111,100,117,108,101,40,41, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97, - 110,100,32,115,108,97,116,101,100,32,102,111,114,32,114,101, - 109,111,118,97,108,32,105,110,32,80,121,116,104,111,110,32, - 51,46,49,50,59,32,117,115,101,32,102,105,110,100,95,115, - 112,101,99,40,41,32,105,110,115,116,101,97,100,78,122,44, - 78,111,116,32,105,109,112,111,114,116,105,110,103,32,100,105, - 114,101,99,116,111,114,121,32,123,125,58,32,109,105,115,115, - 105,110,103,32,95,95,105,110,105,116,95,95,114,0,0,0, - 0,41,7,114,99,0,0,0,114,100,0,0,0,114,101,0, - 0,0,218,11,102,105,110,100,95,108,111,97,100,101,114,114, - 4,0,0,0,114,89,0,0,0,218,13,73,109,112,111,114, - 116,87,97,114,110,105,110,103,41,5,114,143,0,0,0,218, - 8,102,117,108,108,110,97,109,101,218,6,108,111,97,100,101, - 114,218,8,112,111,114,116,105,111,110,115,218,3,109,115,103, + 32,114,97,105,115,101,100,46,10,10,32,32,32,32,78,114, + 98,0,0,0,70,84,122,31,32,110,111,116,32,98,111,116, + 116,111,109,45,108,101,118,101,108,32,100,105,114,101,99,116, + 111,114,121,32,105,110,32,114,97,0,0,0,62,2,0,0, + 0,114,44,0,0,0,233,3,0,0,0,122,29,101,120,112, + 101,99,116,101,100,32,111,110,108,121,32,50,32,111,114,32, + 51,32,100,111,116,115,32,105,110,32,114,122,0,0,0,114, + 44,0,0,0,233,254,255,255,255,122,53,111,112,116,105,109, + 105,122,97,116,105,111,110,32,112,111,114,116,105,111,110,32, + 111,102,32,102,105,108,101,110,97,109,101,32,100,111,101,115, + 32,110,111,116,32,115,116,97,114,116,32,119,105,116,104,32, + 122,19,111,112,116,105,109,105,122,97,116,105,111,110,32,108, + 101,118,101,108,32,122,29,32,105,115,32,110,111,116,32,97, + 110,32,97,108,112,104,97,110,117,109,101,114,105,99,32,118, + 97,108,117,101,114,0,0,0,0,41,22,114,15,0,0,0, + 114,105,0,0,0,114,106,0,0,0,114,107,0,0,0,114, + 18,0,0,0,114,103,0,0,0,114,74,0,0,0,114,114, + 0,0,0,114,49,0,0,0,114,50,0,0,0,114,26,0, + 0,0,114,59,0,0,0,114,4,0,0,0,114,116,0,0, + 0,114,111,0,0,0,218,5,99,111,117,110,116,218,6,114, + 115,112,108,105,116,114,112,0,0,0,114,110,0,0,0,218, + 9,112,97,114,116,105,116,105,111,110,114,67,0,0,0,218, + 15,83,79,85,82,67,69,95,83,85,70,70,73,88,69,83, + 41,10,114,65,0,0,0,114,118,0,0,0,90,16,112,121, + 99,97,99,104,101,95,102,105,108,101,110,97,109,101,90,23, + 102,111,117,110,100,95,105,110,95,112,121,99,97,99,104,101, + 95,112,114,101,102,105,120,90,13,115,116,114,105,112,112,101, + 100,95,112,97,116,104,90,7,112,121,99,97,99,104,101,90, + 9,100,111,116,95,99,111,117,110,116,114,96,0,0,0,90, + 9,111,112,116,95,108,101,118,101,108,90,13,98,97,115,101, + 95,102,105,108,101,110,97,109,101,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,218,17,115,111,117,114,99,101, + 95,102,114,111,109,95,99,97,99,104,101,195,1,0,0,115, + 60,0,0,0,12,9,8,1,10,1,12,1,4,1,10,1, + 12,1,14,1,16,1,4,1,4,1,12,1,8,1,8,1, + 2,1,8,255,10,2,8,1,14,1,8,1,16,1,10,1, + 4,1,2,1,8,255,16,2,8,1,16,1,14,2,18,1, + 114,128,0,0,0,99,1,0,0,0,0,0,0,0,0,0, + 0,0,5,0,0,0,9,0,0,0,67,0,0,0,115,124, + 0,0,0,116,0,124,0,131,1,100,1,107,2,114,8,100, + 2,83,0,124,0,160,1,100,3,161,1,92,3,125,1,125, + 2,125,3,124,1,114,28,124,3,160,2,161,0,100,4,100, + 5,133,2,25,0,100,6,107,3,114,30,124,0,83,0,122, + 6,116,3,124,0,131,1,125,4,87,0,110,17,4,0,116, + 4,116,5,102,2,121,53,1,0,1,0,1,0,124,0,100, + 2,100,5,133,2,25,0,125,4,89,0,110,1,119,0,116, + 6,124,4,131,1,114,60,124,4,83,0,124,0,83,0,41, + 7,122,188,67,111,110,118,101,114,116,32,97,32,98,121,116, + 101,99,111,100,101,32,102,105,108,101,32,112,97,116,104,32, + 116,111,32,97,32,115,111,117,114,99,101,32,112,97,116,104, + 32,40,105,102,32,112,111,115,115,105,98,108,101,41,46,10, + 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105, + 111,110,32,101,120,105,115,116,115,32,112,117,114,101,108,121, + 32,102,111,114,32,98,97,99,107,119,97,114,100,115,45,99, + 111,109,112,97,116,105,98,105,108,105,116,121,32,102,111,114, + 10,32,32,32,32,80,121,73,109,112,111,114,116,95,69,120, + 101,99,67,111,100,101,77,111,100,117,108,101,87,105,116,104, + 70,105,108,101,110,97,109,101,115,40,41,32,105,110,32,116, + 104,101,32,67,32,65,80,73,46,10,10,32,32,32,32,114, + 0,0,0,0,78,114,97,0,0,0,233,253,255,255,255,233, + 255,255,255,255,90,2,112,121,41,7,114,4,0,0,0,114, + 104,0,0,0,218,5,108,111,119,101,114,114,128,0,0,0, + 114,107,0,0,0,114,111,0,0,0,114,80,0,0,0,41, + 5,218,13,98,121,116,101,99,111,100,101,95,112,97,116,104, + 114,119,0,0,0,218,1,95,90,9,101,120,116,101,110,115, + 105,111,110,218,11,115,111,117,114,99,101,95,112,97,116,104, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 17,95,102,105,110,100,95,109,111,100,117,108,101,95,115,104, - 105,109,53,2,0,0,115,16,0,0,0,6,7,2,2,4, - 254,14,6,16,1,4,1,22,1,4,1,114,167,0,0,0, - 99,3,0,0,0,0,0,0,0,0,0,0,0,6,0,0, - 0,4,0,0,0,67,0,0,0,115,166,0,0,0,124,0, - 100,1,100,2,133,2,25,0,125,3,124,3,116,0,107,3, - 114,32,100,3,124,1,155,2,100,4,124,3,155,2,157,4, - 125,4,116,1,160,2,100,5,124,4,161,2,1,0,116,3, - 124,4,102,1,105,0,124,2,164,1,142,1,130,1,116,4, - 124,0,131,1,100,6,107,0,114,53,100,7,124,1,155,2, - 157,2,125,4,116,1,160,2,100,5,124,4,161,2,1,0, - 116,5,124,4,131,1,130,1,116,6,124,0,100,2,100,8, - 133,2,25,0,131,1,125,5,124,5,100,9,64,0,114,81, - 100,10,124,5,155,2,100,11,124,1,155,2,157,4,125,4, - 116,3,124,4,102,1,105,0,124,2,164,1,142,1,130,1, - 124,5,83,0,41,12,97,84,2,0,0,80,101,114,102,111, - 114,109,32,98,97,115,105,99,32,118,97,108,105,100,105,116, - 121,32,99,104,101,99,107,105,110,103,32,111,102,32,97,32, - 112,121,99,32,104,101,97,100,101,114,32,97,110,100,32,114, - 101,116,117,114,110,32,116,104,101,32,102,108,97,103,115,32, - 102,105,101,108,100,44,10,32,32,32,32,119,104,105,99,104, - 32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32, - 116,104,101,32,112,121,99,32,115,104,111,117,108,100,32,98, - 101,32,102,117,114,116,104,101,114,32,118,97,108,105,100,97, - 116,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32, - 115,111,117,114,99,101,46,10,10,32,32,32,32,42,100,97, - 116,97,42,32,105,115,32,116,104,101,32,99,111,110,116,101, - 110,116,115,32,111,102,32,116,104,101,32,112,121,99,32,102, - 105,108,101,46,32,40,79,110,108,121,32,116,104,101,32,102, - 105,114,115,116,32,49,54,32,98,121,116,101,115,32,97,114, - 101,10,32,32,32,32,114,101,113,117,105,114,101,100,44,32, - 116,104,111,117,103,104,46,41,10,10,32,32,32,32,42,110, - 97,109,101,42,32,105,115,32,116,104,101,32,110,97,109,101, - 32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,98, - 101,105,110,103,32,105,109,112,111,114,116,101,100,46,32,73, - 116,32,105,115,32,117,115,101,100,32,102,111,114,32,108,111, - 103,103,105,110,103,46,10,10,32,32,32,32,42,101,120,99, - 95,100,101,116,97,105,108,115,42,32,105,115,32,97,32,100, - 105,99,116,105,111,110,97,114,121,32,112,97,115,115,101,100, - 32,116,111,32,73,109,112,111,114,116,69,114,114,111,114,32, - 105,102,32,105,116,32,114,97,105,115,101,100,32,102,111,114, - 10,32,32,32,32,105,109,112,114,111,118,101,100,32,100,101, - 98,117,103,103,105,110,103,46,10,10,32,32,32,32,73,109, - 112,111,114,116,69,114,114,111,114,32,105,115,32,114,97,105, - 115,101,100,32,119,104,101,110,32,116,104,101,32,109,97,103, - 105,99,32,110,117,109,98,101,114,32,105,115,32,105,110,99, - 111,114,114,101,99,116,32,111,114,32,119,104,101,110,32,116, - 104,101,32,102,108,97,103,115,10,32,32,32,32,102,105,101, - 108,100,32,105,115,32,105,110,118,97,108,105,100,46,32,69, - 79,70,69,114,114,111,114,32,105,115,32,114,97,105,115,101, - 100,32,119,104,101,110,32,116,104,101,32,100,97,116,97,32, - 105,115,32,102,111,117,110,100,32,116,111,32,98,101,32,116, - 114,117,110,99,97,116,101,100,46,10,10,32,32,32,32,78, - 114,31,0,0,0,122,20,98,97,100,32,109,97,103,105,99, - 32,110,117,109,98,101,114,32,105,110,32,122,2,58,32,250, - 2,123,125,233,16,0,0,0,122,40,114,101,97,99,104,101, - 100,32,69,79,70,32,119,104,105,108,101,32,114,101,97,100, - 105,110,103,32,112,121,99,32,104,101,97,100,101,114,32,111, - 102,32,233,8,0,0,0,233,252,255,255,255,122,14,105,110, - 118,97,108,105,100,32,102,108,97,103,115,32,122,4,32,105, - 110,32,41,7,218,12,77,65,71,73,67,95,78,85,77,66, - 69,82,114,159,0,0,0,218,16,95,118,101,114,98,111,115, - 101,95,109,101,115,115,97,103,101,114,142,0,0,0,114,4, - 0,0,0,218,8,69,79,70,69,114,114,111,114,114,42,0, - 0,0,41,6,114,41,0,0,0,114,141,0,0,0,218,11, - 101,120,99,95,100,101,116,97,105,108,115,90,5,109,97,103, - 105,99,114,117,0,0,0,114,16,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,218,13,95,99,108, - 97,115,115,105,102,121,95,112,121,99,73,2,0,0,115,28, - 0,0,0,12,16,8,1,16,1,12,1,16,1,12,1,10, - 1,12,1,8,1,16,1,8,2,16,1,16,1,4,1,114, - 176,0,0,0,99,5,0,0,0,0,0,0,0,0,0,0, - 0,6,0,0,0,4,0,0,0,67,0,0,0,115,124,0, - 0,0,116,0,124,0,100,1,100,2,133,2,25,0,131,1, - 124,1,100,3,64,0,107,3,114,31,100,4,124,3,155,2, - 157,2,125,5,116,1,160,2,100,5,124,5,161,2,1,0, - 116,3,124,5,102,1,105,0,124,4,164,1,142,1,130,1, - 124,2,100,6,117,1,114,60,116,0,124,0,100,2,100,7, - 133,2,25,0,131,1,124,2,100,3,64,0,107,3,114,58, - 116,3,100,4,124,3,155,2,157,2,102,1,105,0,124,4, - 164,1,142,1,130,1,100,6,83,0,100,6,83,0,41,8, - 97,7,2,0,0,86,97,108,105,100,97,116,101,32,97,32, - 112,121,99,32,97,103,97,105,110,115,116,32,116,104,101,32, - 115,111,117,114,99,101,32,108,97,115,116,45,109,111,100,105, - 102,105,101,100,32,116,105,109,101,46,10,10,32,32,32,32, - 42,100,97,116,97,42,32,105,115,32,116,104,101,32,99,111, - 110,116,101,110,116,115,32,111,102,32,116,104,101,32,112,121, - 99,32,102,105,108,101,46,32,40,79,110,108,121,32,116,104, - 101,32,102,105,114,115,116,32,49,54,32,98,121,116,101,115, - 32,97,114,101,10,32,32,32,32,114,101,113,117,105,114,101, - 100,46,41,10,10,32,32,32,32,42,115,111,117,114,99,101, - 95,109,116,105,109,101,42,32,105,115,32,116,104,101,32,108, - 97,115,116,32,109,111,100,105,102,105,101,100,32,116,105,109, - 101,115,116,97,109,112,32,111,102,32,116,104,101,32,115,111, - 117,114,99,101,32,102,105,108,101,46,10,10,32,32,32,32, - 42,115,111,117,114,99,101,95,115,105,122,101,42,32,105,115, - 32,78,111,110,101,32,111,114,32,116,104,101,32,115,105,122, - 101,32,111,102,32,116,104,101,32,115,111,117,114,99,101,32, - 102,105,108,101,32,105,110,32,98,121,116,101,115,46,10,10, + 15,95,103,101,116,95,115,111,117,114,99,101,102,105,108,101, + 235,1,0,0,115,22,0,0,0,12,7,4,1,16,1,24, + 1,4,1,2,1,12,1,16,1,16,1,2,255,16,2,114, + 135,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,8,0,0,0,67,0,0,0,115,68,0, + 0,0,124,0,160,0,116,1,116,2,131,1,161,1,114,23, + 122,5,116,3,124,0,131,1,87,0,83,0,4,0,116,4, + 121,22,1,0,1,0,1,0,89,0,100,0,83,0,119,0, + 124,0,160,0,116,1,116,5,131,1,161,1,114,32,124,0, + 83,0,100,0,83,0,114,69,0,0,0,41,6,114,58,0, + 0,0,218,5,116,117,112,108,101,114,127,0,0,0,114,121, + 0,0,0,114,107,0,0,0,114,113,0,0,0,41,1,114, + 120,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,11,95,103,101,116,95,99,97,99,104,101,100, + 254,1,0,0,115,18,0,0,0,14,1,2,1,10,1,12, + 1,6,1,2,255,14,2,4,1,4,2,114,137,0,0,0, + 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,8,0,0,0,67,0,0,0,115,50,0,0,0,122,7, + 116,0,124,0,131,1,106,1,125,1,87,0,110,11,4,0, + 116,2,121,18,1,0,1,0,1,0,100,1,125,1,89,0, + 110,1,119,0,124,1,100,2,79,0,125,1,124,1,83,0, + 41,3,122,51,67,97,108,99,117,108,97,116,101,32,116,104, + 101,32,109,111,100,101,32,112,101,114,109,105,115,115,105,111, + 110,115,32,102,111,114,32,97,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,46,114,87,0,0,0,233,128,0,0, + 0,41,3,114,75,0,0,0,114,77,0,0,0,114,76,0, + 0,0,41,2,114,65,0,0,0,114,78,0,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,10,95, + 99,97,108,99,95,109,111,100,101,10,2,0,0,115,14,0, + 0,0,2,2,14,1,12,1,8,1,2,255,8,4,4,1, + 114,139,0,0,0,99,1,0,0,0,0,0,0,0,0,0, + 0,0,3,0,0,0,4,0,0,0,3,0,0,0,115,52, + 0,0,0,100,6,135,0,102,1,100,2,100,3,132,9,125, + 1,116,0,100,1,117,1,114,15,116,0,106,1,125,2,110, + 4,100,4,100,5,132,0,125,2,124,2,124,1,136,0,131, + 2,1,0,124,1,83,0,41,7,122,252,68,101,99,111,114, + 97,116,111,114,32,116,111,32,118,101,114,105,102,121,32,116, + 104,97,116,32,116,104,101,32,109,111,100,117,108,101,32,98, + 101,105,110,103,32,114,101,113,117,101,115,116,101,100,32,109, + 97,116,99,104,101,115,32,116,104,101,32,111,110,101,32,116, + 104,101,10,32,32,32,32,108,111,97,100,101,114,32,99,97, + 110,32,104,97,110,100,108,101,46,10,10,32,32,32,32,84, + 104,101,32,102,105,114,115,116,32,97,114,103,117,109,101,110, + 116,32,40,115,101,108,102,41,32,109,117,115,116,32,100,101, + 102,105,110,101,32,95,110,97,109,101,32,119,104,105,99,104, + 32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117, + 109,101,110,116,32,105,115,10,32,32,32,32,99,111,109,112, + 97,114,101,100,32,97,103,97,105,110,115,116,46,32,73,102, + 32,116,104,101,32,99,111,109,112,97,114,105,115,111,110,32, + 102,97,105,108,115,32,116,104,101,110,32,73,109,112,111,114, + 116,69,114,114,111,114,32,105,115,32,114,97,105,115,101,100, + 46,10,10,32,32,32,32,78,99,2,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,4,0,0,0,31,0,0, + 0,115,72,0,0,0,124,1,100,0,117,0,114,8,124,0, + 106,0,125,1,110,16,124,0,106,0,124,1,107,3,114,24, + 116,1,100,1,124,0,106,0,124,1,102,2,22,0,124,1, + 100,2,141,2,130,1,136,0,124,0,124,1,103,2,124,2, + 162,1,82,0,105,0,124,3,164,1,142,1,83,0,41,3, + 78,122,30,108,111,97,100,101,114,32,102,111,114,32,37,115, + 32,99,97,110,110,111,116,32,104,97,110,100,108,101,32,37, + 115,169,1,218,4,110,97,109,101,41,2,114,141,0,0,0, + 218,11,73,109,112,111,114,116,69,114,114,111,114,41,4,218, + 4,115,101,108,102,114,141,0,0,0,218,4,97,114,103,115, + 218,6,107,119,97,114,103,115,169,1,218,6,109,101,116,104, + 111,100,114,7,0,0,0,114,8,0,0,0,218,19,95,99, + 104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101, + 114,30,2,0,0,115,18,0,0,0,8,1,8,1,10,1, + 4,1,8,1,2,255,2,1,6,255,24,2,122,40,95,99, + 104,101,99,107,95,110,97,109,101,46,60,108,111,99,97,108, + 115,62,46,95,99,104,101,99,107,95,110,97,109,101,95,119, + 114,97,112,112,101,114,99,2,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,7,0,0,0,83,0,0,0,115, + 56,0,0,0,100,1,68,0,93,16,125,2,116,0,124,1, + 124,2,131,2,114,18,116,1,124,0,124,2,116,2,124,1, + 124,2,131,2,131,3,1,0,113,2,124,0,106,3,160,4, + 124,1,106,3,161,1,1,0,100,0,83,0,41,2,78,41, + 4,218,10,95,95,109,111,100,117,108,101,95,95,218,8,95, + 95,110,97,109,101,95,95,218,12,95,95,113,117,97,108,110, + 97,109,101,95,95,218,7,95,95,100,111,99,95,95,41,5, + 218,7,104,97,115,97,116,116,114,218,7,115,101,116,97,116, + 116,114,218,7,103,101,116,97,116,116,114,218,8,95,95,100, + 105,99,116,95,95,218,6,117,112,100,97,116,101,41,3,90, + 3,110,101,119,90,3,111,108,100,114,85,0,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,5,95, + 119,114,97,112,43,2,0,0,115,10,0,0,0,8,1,10, + 1,18,1,2,128,18,1,122,26,95,99,104,101,99,107,95, + 110,97,109,101,46,60,108,111,99,97,108,115,62,46,95,119, + 114,97,112,114,69,0,0,0,41,2,218,10,95,98,111,111, + 116,115,116,114,97,112,114,158,0,0,0,41,3,114,147,0, + 0,0,114,148,0,0,0,114,158,0,0,0,114,7,0,0, + 0,114,146,0,0,0,114,8,0,0,0,218,11,95,99,104, + 101,99,107,95,110,97,109,101,22,2,0,0,115,12,0,0, + 0,14,8,8,10,8,1,8,2,10,6,4,1,114,160,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,6,0,0,0,67,0,0,0,115,72,0,0,0, + 116,0,160,1,100,1,116,2,161,2,1,0,124,0,160,3, + 124,1,161,1,92,2,125,2,125,3,124,2,100,2,117,0, + 114,34,116,4,124,3,131,1,114,34,100,3,125,4,116,0, + 160,1,124,4,160,5,124,3,100,4,25,0,161,1,116,6, + 161,2,1,0,124,2,83,0,41,5,122,155,84,114,121,32, + 116,111,32,102,105,110,100,32,97,32,108,111,97,100,101,114, + 32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105, + 101,100,32,109,111,100,117,108,101,32,98,121,32,100,101,108, + 101,103,97,116,105,110,103,32,116,111,10,32,32,32,32,115, + 101,108,102,46,102,105,110,100,95,108,111,97,100,101,114,40, + 41,46,10,10,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,32,105,110,32,102,97,118,111,114,32,111,102,32,102,105, + 110,100,101,114,46,102,105,110,100,95,115,112,101,99,40,41, + 46,10,10,32,32,32,32,122,90,102,105,110,100,95,109,111, + 100,117,108,101,40,41,32,105,115,32,100,101,112,114,101,99, + 97,116,101,100,32,97,110,100,32,115,108,97,116,101,100,32, + 102,111,114,32,114,101,109,111,118,97,108,32,105,110,32,80, + 121,116,104,111,110,32,51,46,49,50,59,32,117,115,101,32, + 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, + 101,97,100,78,122,44,78,111,116,32,105,109,112,111,114,116, + 105,110,103,32,100,105,114,101,99,116,111,114,121,32,123,125, + 58,32,109,105,115,115,105,110,103,32,95,95,105,110,105,116, + 95,95,114,0,0,0,0,41,7,114,99,0,0,0,114,100, + 0,0,0,114,101,0,0,0,218,11,102,105,110,100,95,108, + 111,97,100,101,114,114,4,0,0,0,114,89,0,0,0,218, + 13,73,109,112,111,114,116,87,97,114,110,105,110,103,41,5, + 114,143,0,0,0,218,8,102,117,108,108,110,97,109,101,218, + 6,108,111,97,100,101,114,218,8,112,111,114,116,105,111,110, + 115,218,3,109,115,103,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,218,17,95,102,105,110,100,95,109,111,100, + 117,108,101,95,115,104,105,109,53,2,0,0,115,16,0,0, + 0,6,7,2,2,4,254,14,6,16,1,4,1,22,1,4, + 1,114,167,0,0,0,99,3,0,0,0,0,0,0,0,0, + 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, + 166,0,0,0,124,0,100,1,100,2,133,2,25,0,125,3, + 124,3,116,0,107,3,114,32,100,3,124,1,155,2,100,4, + 124,3,155,2,157,4,125,4,116,1,160,2,100,5,124,4, + 161,2,1,0,116,3,124,4,102,1,105,0,124,2,164,1, + 142,1,130,1,116,4,124,0,131,1,100,6,107,0,114,53, + 100,7,124,1,155,2,157,2,125,4,116,1,160,2,100,5, + 124,4,161,2,1,0,116,5,124,4,131,1,130,1,116,6, + 124,0,100,2,100,8,133,2,25,0,131,1,125,5,124,5, + 100,9,64,0,114,81,100,10,124,5,155,2,100,11,124,1, + 155,2,157,4,125,4,116,3,124,4,102,1,105,0,124,2, + 164,1,142,1,130,1,124,5,83,0,41,12,97,84,2,0, + 0,80,101,114,102,111,114,109,32,98,97,115,105,99,32,118, + 97,108,105,100,105,116,121,32,99,104,101,99,107,105,110,103, + 32,111,102,32,97,32,112,121,99,32,104,101,97,100,101,114, + 32,97,110,100,32,114,101,116,117,114,110,32,116,104,101,32, + 102,108,97,103,115,32,102,105,101,108,100,44,10,32,32,32, + 32,119,104,105,99,104,32,100,101,116,101,114,109,105,110,101, + 115,32,104,111,119,32,116,104,101,32,112,121,99,32,115,104, + 111,117,108,100,32,98,101,32,102,117,114,116,104,101,114,32, + 118,97,108,105,100,97,116,101,100,32,97,103,97,105,110,115, + 116,32,116,104,101,32,115,111,117,114,99,101,46,10,10,32, + 32,32,32,42,100,97,116,97,42,32,105,115,32,116,104,101, + 32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101, + 32,112,121,99,32,102,105,108,101,46,32,40,79,110,108,121, + 32,116,104,101,32,102,105,114,115,116,32,49,54,32,98,121, + 116,101,115,32,97,114,101,10,32,32,32,32,114,101,113,117, + 105,114,101,100,44,32,116,104,111,117,103,104,46,41,10,10, 32,32,32,32,42,110,97,109,101,42,32,105,115,32,116,104, 101,32,110,97,109,101,32,111,102,32,116,104,101,32,109,111, 100,117,108,101,32,98,101,105,110,103,32,105,109,112,111,114, @@ -822,499 +754,590 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 69,114,114,111,114,32,105,102,32,105,116,32,114,97,105,115, 101,100,32,102,111,114,10,32,32,32,32,105,109,112,114,111, 118,101,100,32,100,101,98,117,103,103,105,110,103,46,10,10, - 32,32,32,32,65,110,32,73,109,112,111,114,116,69,114,114, - 111,114,32,105,115,32,114,97,105,115,101,100,32,105,102,32, - 116,104,101,32,98,121,116,101,99,111,100,101,32,105,115,32, - 115,116,97,108,101,46,10,10,32,32,32,32,114,170,0,0, - 0,233,12,0,0,0,114,30,0,0,0,122,22,98,121,116, - 101,99,111,100,101,32,105,115,32,115,116,97,108,101,32,102, - 111,114,32,114,168,0,0,0,78,114,169,0,0,0,41,4, - 114,42,0,0,0,114,159,0,0,0,114,173,0,0,0,114, - 142,0,0,0,41,6,114,41,0,0,0,218,12,115,111,117, - 114,99,101,95,109,116,105,109,101,218,11,115,111,117,114,99, - 101,95,115,105,122,101,114,141,0,0,0,114,175,0,0,0, - 114,117,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,23,95,118,97,108,105,100,97,116,101,95, - 116,105,109,101,115,116,97,109,112,95,112,121,99,106,2,0, - 0,115,18,0,0,0,24,19,10,1,12,1,16,1,8,1, - 22,1,2,255,22,2,8,254,114,180,0,0,0,99,4,0, - 0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0, - 0,0,67,0,0,0,115,42,0,0,0,124,0,100,1,100, - 2,133,2,25,0,124,1,107,3,114,19,116,0,100,3,124, - 2,155,2,157,2,102,1,105,0,124,3,164,1,142,1,130, - 1,100,4,83,0,41,5,97,243,1,0,0,86,97,108,105, - 100,97,116,101,32,97,32,104,97,115,104,45,98,97,115,101, - 100,32,112,121,99,32,98,121,32,99,104,101,99,107,105,110, - 103,32,116,104,101,32,114,101,97,108,32,115,111,117,114,99, - 101,32,104,97,115,104,32,97,103,97,105,110,115,116,32,116, - 104,101,32,111,110,101,32,105,110,10,32,32,32,32,116,104, - 101,32,112,121,99,32,104,101,97,100,101,114,46,10,10,32, - 32,32,32,42,100,97,116,97,42,32,105,115,32,116,104,101, - 32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101, - 32,112,121,99,32,102,105,108,101,46,32,40,79,110,108,121, - 32,116,104,101,32,102,105,114,115,116,32,49,54,32,98,121, - 116,101,115,32,97,114,101,10,32,32,32,32,114,101,113,117, - 105,114,101,100,46,41,10,10,32,32,32,32,42,115,111,117, - 114,99,101,95,104,97,115,104,42,32,105,115,32,116,104,101, - 32,105,109,112,111,114,116,108,105,98,46,117,116,105,108,46, - 115,111,117,114,99,101,95,104,97,115,104,40,41,32,111,102, - 32,116,104,101,32,115,111,117,114,99,101,32,102,105,108,101, - 46,10,10,32,32,32,32,42,110,97,109,101,42,32,105,115, - 32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101, - 32,109,111,100,117,108,101,32,98,101,105,110,103,32,105,109, - 112,111,114,116,101,100,46,32,73,116,32,105,115,32,117,115, - 101,100,32,102,111,114,32,108,111,103,103,105,110,103,46,10, - 10,32,32,32,32,42,101,120,99,95,100,101,116,97,105,108, - 115,42,32,105,115,32,97,32,100,105,99,116,105,111,110,97, - 114,121,32,112,97,115,115,101,100,32,116,111,32,73,109,112, - 111,114,116,69,114,114,111,114,32,105,102,32,105,116,32,114, - 97,105,115,101,100,32,102,111,114,10,32,32,32,32,105,109, - 112,114,111,118,101,100,32,100,101,98,117,103,103,105,110,103, - 46,10,10,32,32,32,32,65,110,32,73,109,112,111,114,116, - 69,114,114,111,114,32,105,115,32,114,97,105,115,101,100,32, - 105,102,32,116,104,101,32,98,121,116,101,99,111,100,101,32, - 105,115,32,115,116,97,108,101,46,10,10,32,32,32,32,114, - 170,0,0,0,114,169,0,0,0,122,46,104,97,115,104,32, - 105,110,32,98,121,116,101,99,111,100,101,32,100,111,101,115, - 110,39,116,32,109,97,116,99,104,32,104,97,115,104,32,111, - 102,32,115,111,117,114,99,101,32,78,41,1,114,142,0,0, - 0,41,4,114,41,0,0,0,218,11,115,111,117,114,99,101, - 95,104,97,115,104,114,141,0,0,0,114,175,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,18, - 95,118,97,108,105,100,97,116,101,95,104,97,115,104,95,112, - 121,99,134,2,0,0,115,14,0,0,0,16,17,2,1,8, - 1,4,255,2,2,6,254,4,255,114,182,0,0,0,99,4, - 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,76,0,0,0,116,0,160,1, - 124,0,161,1,125,4,116,2,124,4,116,3,131,2,114,28, - 116,4,160,5,100,1,124,2,161,2,1,0,124,3,100,2, - 117,1,114,26,116,6,160,7,124,4,124,3,161,2,1,0, - 124,4,83,0,116,8,100,3,160,9,124,2,161,1,124,1, - 124,2,100,4,141,3,130,1,41,5,122,35,67,111,109,112, - 105,108,101,32,98,121,116,101,99,111,100,101,32,97,115,32, - 102,111,117,110,100,32,105,110,32,97,32,112,121,99,46,122, - 21,99,111,100,101,32,111,98,106,101,99,116,32,102,114,111, - 109,32,123,33,114,125,78,122,23,78,111,110,45,99,111,100, - 101,32,111,98,106,101,99,116,32,105,110,32,123,33,114,125, - 169,2,114,141,0,0,0,114,65,0,0,0,41,10,218,7, - 109,97,114,115,104,97,108,90,5,108,111,97,100,115,218,10, - 105,115,105,110,115,116,97,110,99,101,218,10,95,99,111,100, - 101,95,116,121,112,101,114,159,0,0,0,114,173,0,0,0, - 218,4,95,105,109,112,90,16,95,102,105,120,95,99,111,95, - 102,105,108,101,110,97,109,101,114,142,0,0,0,114,89,0, - 0,0,41,5,114,41,0,0,0,114,141,0,0,0,114,132, - 0,0,0,114,134,0,0,0,218,4,99,111,100,101,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,218,17,95, - 99,111,109,112,105,108,101,95,98,121,116,101,99,111,100,101, - 158,2,0,0,115,18,0,0,0,10,2,10,1,12,1,8, - 1,12,1,4,1,10,2,4,1,6,255,114,189,0,0,0, - 99,3,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,5,0,0,0,67,0,0,0,115,70,0,0,0,116,0, - 116,1,131,1,125,3,124,3,160,2,116,3,100,1,131,1, - 161,1,1,0,124,3,160,2,116,3,124,1,131,1,161,1, - 1,0,124,3,160,2,116,3,124,2,131,1,161,1,1,0, - 124,3,160,2,116,4,160,5,124,0,161,1,161,1,1,0, - 124,3,83,0,41,3,122,43,80,114,111,100,117,99,101,32, - 116,104,101,32,100,97,116,97,32,102,111,114,32,97,32,116, - 105,109,101,115,116,97,109,112,45,98,97,115,101,100,32,112, - 121,99,46,114,0,0,0,0,78,41,6,218,9,98,121,116, - 101,97,114,114,97,121,114,172,0,0,0,218,6,101,120,116, - 101,110,100,114,36,0,0,0,114,184,0,0,0,218,5,100, - 117,109,112,115,41,4,114,188,0,0,0,218,5,109,116,105, - 109,101,114,179,0,0,0,114,41,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,218,22,95,99,111, - 100,101,95,116,111,95,116,105,109,101,115,116,97,109,112,95, - 112,121,99,171,2,0,0,115,12,0,0,0,8,2,14,1, - 14,1,14,1,16,1,4,1,114,194,0,0,0,84,99,3, - 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,80,0,0,0,116,0,116,1, - 131,1,125,3,100,1,124,2,100,1,62,0,66,0,125,4, - 124,3,160,2,116,3,124,4,131,1,161,1,1,0,116,4, - 124,1,131,1,100,2,107,2,115,25,74,0,130,1,124,3, - 160,2,124,1,161,1,1,0,124,3,160,2,116,5,160,6, - 124,0,161,1,161,1,1,0,124,3,83,0,41,4,122,38, - 80,114,111,100,117,99,101,32,116,104,101,32,100,97,116,97, - 32,102,111,114,32,97,32,104,97,115,104,45,98,97,115,101, - 100,32,112,121,99,46,114,3,0,0,0,114,170,0,0,0, - 78,41,7,114,190,0,0,0,114,172,0,0,0,114,191,0, - 0,0,114,36,0,0,0,114,4,0,0,0,114,184,0,0, - 0,114,192,0,0,0,41,5,114,188,0,0,0,114,181,0, - 0,0,90,7,99,104,101,99,107,101,100,114,41,0,0,0, - 114,16,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,17,95,99,111,100,101,95,116,111,95,104, - 97,115,104,95,112,121,99,181,2,0,0,115,14,0,0,0, - 8,2,12,1,14,1,16,1,10,1,16,1,4,1,114,195, - 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, - 5,0,0,0,6,0,0,0,67,0,0,0,115,62,0,0, - 0,100,1,100,2,108,0,125,1,116,1,160,2,124,0,161, - 1,106,3,125,2,124,1,160,4,124,2,161,1,125,3,116, - 1,160,5,100,2,100,3,161,2,125,4,124,4,160,6,124, - 0,160,6,124,3,100,1,25,0,161,1,161,1,83,0,41, - 4,122,121,68,101,99,111,100,101,32,98,121,116,101,115,32, - 114,101,112,114,101,115,101,110,116,105,110,103,32,115,111,117, - 114,99,101,32,99,111,100,101,32,97,110,100,32,114,101,116, - 117,114,110,32,116,104,101,32,115,116,114,105,110,103,46,10, - 10,32,32,32,32,85,110,105,118,101,114,115,97,108,32,110, - 101,119,108,105,110,101,32,115,117,112,112,111,114,116,32,105, - 115,32,117,115,101,100,32,105,110,32,116,104,101,32,100,101, - 99,111,100,105,110,103,46,10,32,32,32,32,114,0,0,0, - 0,78,84,41,7,218,8,116,111,107,101,110,105,122,101,114, - 91,0,0,0,90,7,66,121,116,101,115,73,79,90,8,114, - 101,97,100,108,105,110,101,90,15,100,101,116,101,99,116,95, - 101,110,99,111,100,105,110,103,90,25,73,110,99,114,101,109, - 101,110,116,97,108,78,101,119,108,105,110,101,68,101,99,111, - 100,101,114,218,6,100,101,99,111,100,101,41,5,218,12,115, - 111,117,114,99,101,95,98,121,116,101,115,114,196,0,0,0, - 90,21,115,111,117,114,99,101,95,98,121,116,101,115,95,114, - 101,97,100,108,105,110,101,218,8,101,110,99,111,100,105,110, - 103,90,15,110,101,119,108,105,110,101,95,100,101,99,111,100, - 101,114,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,13,100,101,99,111,100,101,95,115,111,117,114,99,101, - 192,2,0,0,115,10,0,0,0,8,5,12,1,10,1,12, - 1,20,1,114,200,0,0,0,169,2,114,164,0,0,0,218, - 26,115,117,98,109,111,100,117,108,101,95,115,101,97,114,99, - 104,95,108,111,99,97,116,105,111,110,115,99,2,0,0,0, - 0,0,0,0,2,0,0,0,9,0,0,0,8,0,0,0, - 67,0,0,0,115,52,1,0,0,124,1,100,1,117,0,114, - 28,100,2,125,1,116,0,124,2,100,3,131,2,114,27,122, - 7,124,2,160,1,124,0,161,1,125,1,87,0,110,35,4, - 0,116,2,121,153,1,0,1,0,1,0,89,0,110,27,110, - 26,116,3,160,4,124,1,161,1,125,1,116,5,124,1,131, - 1,115,54,122,9,116,6,116,3,160,7,161,0,124,1,131, - 2,125,1,87,0,110,7,4,0,116,8,121,152,1,0,1, - 0,1,0,89,0,116,9,106,10,124,0,124,2,124,1,100, - 4,141,3,125,4,100,5,124,4,95,11,124,2,100,1,117, - 0,114,96,116,12,131,0,68,0,93,21,92,2,125,5,125, - 6,124,1,160,13,116,14,124,6,131,1,161,1,114,93,124, - 5,124,0,124,1,131,2,125,2,124,2,124,4,95,15,1, - 0,113,96,113,72,100,1,83,0,124,3,116,16,117,0,114, - 127,116,0,124,2,100,6,131,2,114,126,122,7,124,2,160, - 17,124,0,161,1,125,7,87,0,110,8,4,0,116,2,121, - 151,1,0,1,0,1,0,89,0,110,9,124,7,114,126,103, - 0,124,4,95,18,110,3,124,3,124,4,95,18,124,4,106, - 18,103,0,107,2,114,149,124,1,114,149,116,19,124,1,131, - 1,100,7,25,0,125,8,124,4,106,18,160,20,124,8,161, - 1,1,0,124,4,83,0,119,0,119,0,119,0,41,8,97, - 61,1,0,0,82,101,116,117,114,110,32,97,32,109,111,100, - 117,108,101,32,115,112,101,99,32,98,97,115,101,100,32,111, - 110,32,97,32,102,105,108,101,32,108,111,99,97,116,105,111, - 110,46,10,10,32,32,32,32,84,111,32,105,110,100,105,99, - 97,116,101,32,116,104,97,116,32,116,104,101,32,109,111,100, - 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, - 44,32,115,101,116,10,32,32,32,32,115,117,98,109,111,100, - 117,108,101,95,115,101,97,114,99,104,95,108,111,99,97,116, - 105,111,110,115,32,116,111,32,97,32,108,105,115,116,32,111, - 102,32,100,105,114,101,99,116,111,114,121,32,112,97,116,104, - 115,46,32,32,65,110,10,32,32,32,32,101,109,112,116,121, - 32,108,105,115,116,32,105,115,32,115,117,102,102,105,99,105, - 101,110,116,44,32,116,104,111,117,103,104,32,105,116,115,32, - 110,111,116,32,111,116,104,101,114,119,105,115,101,32,117,115, - 101,102,117,108,32,116,111,32,116,104,101,10,32,32,32,32, - 105,109,112,111,114,116,32,115,121,115,116,101,109,46,10,10, - 32,32,32,32,84,104,101,32,108,111,97,100,101,114,32,109, - 117,115,116,32,116,97,107,101,32,97,32,115,112,101,99,32, - 97,115,32,105,116,115,32,111,110,108,121,32,95,95,105,110, - 105,116,95,95,40,41,32,97,114,103,46,10,10,32,32,32, - 32,78,122,9,60,117,110,107,110,111,119,110,62,218,12,103, - 101,116,95,102,105,108,101,110,97,109,101,169,1,218,6,111, - 114,105,103,105,110,84,218,10,105,115,95,112,97,99,107,97, - 103,101,114,0,0,0,0,41,21,114,153,0,0,0,114,203, - 0,0,0,114,142,0,0,0,114,18,0,0,0,114,103,0, - 0,0,114,86,0,0,0,114,67,0,0,0,114,82,0,0, - 0,114,76,0,0,0,114,159,0,0,0,218,10,77,111,100, - 117,108,101,83,112,101,99,90,13,95,115,101,116,95,102,105, - 108,101,97,116,116,114,218,27,95,103,101,116,95,115,117,112, - 112,111,114,116,101,100,95,102,105,108,101,95,108,111,97,100, - 101,114,115,114,58,0,0,0,114,136,0,0,0,114,164,0, - 0,0,218,9,95,80,79,80,85,76,65,84,69,114,206,0, - 0,0,114,202,0,0,0,114,74,0,0,0,114,61,0,0, - 0,41,9,114,141,0,0,0,90,8,108,111,99,97,116,105, - 111,110,114,164,0,0,0,114,202,0,0,0,218,4,115,112, - 101,99,218,12,108,111,97,100,101,114,95,99,108,97,115,115, - 218,8,115,117,102,102,105,120,101,115,114,206,0,0,0,90, - 7,100,105,114,110,97,109,101,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,23,115,112,101,99,95,102,114, - 111,109,95,102,105,108,101,95,108,111,99,97,116,105,111,110, - 209,2,0,0,115,84,0,0,0,8,12,4,4,10,1,2, - 2,14,1,12,1,4,1,2,251,10,7,8,1,2,1,18, - 1,12,1,2,1,16,8,6,1,8,3,14,1,14,1,10, - 1,6,1,4,1,2,253,4,5,8,3,10,2,2,1,14, - 1,12,1,4,1,4,2,6,1,2,128,6,2,10,1,4, - 1,12,1,12,1,4,2,2,244,2,228,2,249,114,213,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,4,0,0,0,64,0,0,0,115,88,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,90,4, - 100,3,90,5,101,6,111,15,100,4,101,7,118,0,90,8, - 101,9,100,5,100,6,132,0,131,1,90,10,101,11,100,7, - 100,8,132,0,131,1,90,12,101,11,100,14,100,10,100,11, - 132,1,131,1,90,13,101,11,100,15,100,12,100,13,132,1, - 131,1,90,14,100,9,83,0,41,16,218,21,87,105,110,100, - 111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101, - 114,122,62,77,101,116,97,32,112,97,116,104,32,102,105,110, - 100,101,114,32,102,111,114,32,109,111,100,117,108,101,115,32, - 100,101,99,108,97,114,101,100,32,105,110,32,116,104,101,32, - 87,105,110,100,111,119,115,32,114,101,103,105,115,116,114,121, - 46,122,59,83,111,102,116,119,97,114,101,92,80,121,116,104, - 111,110,92,80,121,116,104,111,110,67,111,114,101,92,123,115, - 121,115,95,118,101,114,115,105,111,110,125,92,77,111,100,117, - 108,101,115,92,123,102,117,108,108,110,97,109,101,125,122,65, - 83,111,102,116,119,97,114,101,92,80,121,116,104,111,110,92, - 80,121,116,104,111,110,67,111,114,101,92,123,115,121,115,95, - 118,101,114,115,105,111,110,125,92,77,111,100,117,108,101,115, - 92,123,102,117,108,108,110,97,109,101,125,92,68,101,98,117, - 103,122,6,95,100,46,112,121,100,99,1,0,0,0,0,0, - 0,0,0,0,0,0,1,0,0,0,8,0,0,0,67,0, - 0,0,115,50,0,0,0,122,8,116,0,160,1,116,0,106, - 2,124,0,161,2,87,0,83,0,4,0,116,3,121,24,1, - 0,1,0,1,0,116,0,160,1,116,0,106,4,124,0,161, - 2,6,0,89,0,83,0,119,0,114,69,0,0,0,41,5, - 218,6,119,105,110,114,101,103,90,7,79,112,101,110,75,101, - 121,90,17,72,75,69,89,95,67,85,82,82,69,78,84,95, - 85,83,69,82,114,76,0,0,0,90,18,72,75,69,89,95, - 76,79,67,65,76,95,77,65,67,72,73,78,69,114,19,0, + 32,32,32,32,73,109,112,111,114,116,69,114,114,111,114,32, + 105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,116, + 104,101,32,109,97,103,105,99,32,110,117,109,98,101,114,32, + 105,115,32,105,110,99,111,114,114,101,99,116,32,111,114,32, + 119,104,101,110,32,116,104,101,32,102,108,97,103,115,10,32, + 32,32,32,102,105,101,108,100,32,105,115,32,105,110,118,97, + 108,105,100,46,32,69,79,70,69,114,114,111,114,32,105,115, + 32,114,97,105,115,101,100,32,119,104,101,110,32,116,104,101, + 32,100,97,116,97,32,105,115,32,102,111,117,110,100,32,116, + 111,32,98,101,32,116,114,117,110,99,97,116,101,100,46,10, + 10,32,32,32,32,78,114,31,0,0,0,122,20,98,97,100, + 32,109,97,103,105,99,32,110,117,109,98,101,114,32,105,110, + 32,122,2,58,32,250,2,123,125,233,16,0,0,0,122,40, + 114,101,97,99,104,101,100,32,69,79,70,32,119,104,105,108, + 101,32,114,101,97,100,105,110,103,32,112,121,99,32,104,101, + 97,100,101,114,32,111,102,32,233,8,0,0,0,233,252,255, + 255,255,122,14,105,110,118,97,108,105,100,32,102,108,97,103, + 115,32,122,4,32,105,110,32,41,7,218,12,77,65,71,73, + 67,95,78,85,77,66,69,82,114,159,0,0,0,218,16,95, + 118,101,114,98,111,115,101,95,109,101,115,115,97,103,101,114, + 142,0,0,0,114,4,0,0,0,218,8,69,79,70,69,114, + 114,111,114,114,42,0,0,0,41,6,114,41,0,0,0,114, + 141,0,0,0,218,11,101,120,99,95,100,101,116,97,105,108, + 115,90,5,109,97,103,105,99,114,117,0,0,0,114,16,0, 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,14,95,111,112,101,110,95,114,101,103,105,115,116,114, - 121,38,3,0,0,115,10,0,0,0,2,2,16,1,12,1, - 18,1,2,255,122,36,87,105,110,100,111,119,115,82,101,103, - 105,115,116,114,121,70,105,110,100,101,114,46,95,111,112,101, - 110,95,114,101,103,105,115,116,114,121,99,2,0,0,0,0, - 0,0,0,0,0,0,0,6,0,0,0,8,0,0,0,67, - 0,0,0,115,130,0,0,0,124,0,106,0,114,7,124,0, - 106,1,125,2,110,3,124,0,106,2,125,2,124,2,106,3, - 124,1,100,1,116,4,106,5,100,0,100,2,133,2,25,0, - 22,0,100,3,141,2,125,3,122,30,124,0,160,6,124,3, - 161,1,143,14,125,4,116,7,160,8,124,4,100,4,161,2, - 125,5,87,0,100,0,4,0,4,0,131,3,1,0,110,8, - 49,0,115,47,119,1,1,0,1,0,1,0,89,0,1,0, - 87,0,124,5,83,0,4,0,116,9,121,64,1,0,1,0, - 1,0,89,0,100,0,83,0,119,0,41,5,78,122,5,37, - 100,46,37,100,114,44,0,0,0,41,2,114,163,0,0,0, - 90,11,115,121,115,95,118,101,114,115,105,111,110,114,10,0, - 0,0,41,10,218,11,68,69,66,85,71,95,66,85,73,76, - 68,218,18,82,69,71,73,83,84,82,89,95,75,69,89,95, - 68,69,66,85,71,218,12,82,69,71,73,83,84,82,89,95, - 75,69,89,114,89,0,0,0,114,15,0,0,0,218,12,118, - 101,114,115,105,111,110,95,105,110,102,111,114,216,0,0,0, - 114,215,0,0,0,90,10,81,117,101,114,121,86,97,108,117, - 101,114,76,0,0,0,41,6,218,3,99,108,115,114,163,0, - 0,0,90,12,114,101,103,105,115,116,114,121,95,107,101,121, - 114,20,0,0,0,90,4,104,107,101,121,218,8,102,105,108, - 101,112,97,116,104,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,16,95,115,101,97,114,99,104,95,114,101, - 103,105,115,116,114,121,45,3,0,0,115,30,0,0,0,6, - 2,8,1,6,2,6,1,16,1,6,255,2,2,12,1,14, - 1,28,255,2,128,4,4,12,254,6,1,2,255,122,38,87, - 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, - 110,100,101,114,46,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,78,99,4,0,0,0,0,0,0,0,0, - 0,0,0,8,0,0,0,8,0,0,0,67,0,0,0,115, - 120,0,0,0,124,0,160,0,124,1,161,1,125,4,124,4, - 100,0,117,0,114,11,100,0,83,0,122,6,116,1,124,4, - 131,1,1,0,87,0,110,9,4,0,116,2,121,59,1,0, - 1,0,1,0,89,0,100,0,83,0,116,3,131,0,68,0, - 93,26,92,2,125,5,125,6,124,4,160,4,116,5,124,6, - 131,1,161,1,114,56,116,6,106,7,124,1,124,5,124,1, - 124,4,131,2,124,4,100,1,141,3,125,7,124,7,2,0, - 1,0,83,0,113,30,100,0,83,0,119,0,41,2,78,114, - 204,0,0,0,41,8,114,223,0,0,0,114,75,0,0,0, - 114,76,0,0,0,114,208,0,0,0,114,58,0,0,0,114, - 136,0,0,0,114,159,0,0,0,218,16,115,112,101,99,95, - 102,114,111,109,95,108,111,97,100,101,114,41,8,114,221,0, - 0,0,114,163,0,0,0,114,65,0,0,0,218,6,116,97, - 114,103,101,116,114,222,0,0,0,114,164,0,0,0,114,212, - 0,0,0,114,210,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,9,102,105,110,100,95,115,112, - 101,99,60,3,0,0,115,34,0,0,0,10,2,8,1,4, - 1,2,1,12,1,12,1,6,1,14,1,14,1,6,1,8, - 1,2,1,6,254,8,3,2,252,4,255,2,254,122,31,87, - 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, - 110,100,101,114,46,102,105,110,100,95,115,112,101,99,99,3, - 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4, - 0,0,0,67,0,0,0,115,42,0,0,0,116,0,160,1, - 100,1,116,2,161,2,1,0,124,0,160,3,124,1,124,2, - 161,2,125,3,124,3,100,2,117,1,114,19,124,3,106,4, - 83,0,100,2,83,0,41,3,122,106,70,105,110,100,32,109, - 111,100,117,108,101,32,110,97,109,101,100,32,105,110,32,116, - 104,101,32,114,101,103,105,115,116,114,121,46,10,10,32,32, - 32,32,32,32,32,32,84,104,105,115,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,122,112,87,105,110,100,111,119,115,82,101,103, - 105,115,116,114,121,70,105,110,100,101,114,46,102,105,110,100, - 95,109,111,100,117,108,101,40,41,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,32,97,110,100,32,115,108,97,116, - 101,100,32,102,111,114,32,114,101,109,111,118,97,108,32,105, - 110,32,80,121,116,104,111,110,32,51,46,49,50,59,32,117, - 115,101,32,102,105,110,100,95,115,112,101,99,40,41,32,105, - 110,115,116,101,97,100,78,169,5,114,99,0,0,0,114,100, - 0,0,0,114,101,0,0,0,114,226,0,0,0,114,164,0, - 0,0,169,4,114,221,0,0,0,114,163,0,0,0,114,65, - 0,0,0,114,210,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,11,102,105,110,100,95,109,111, - 100,117,108,101,76,3,0,0,115,14,0,0,0,6,7,2, - 2,4,254,12,3,8,1,6,1,4,2,122,33,87,105,110, - 100,111,119,115,82,101,103,105,115,116,114,121,70,105,110,100, - 101,114,46,102,105,110,100,95,109,111,100,117,108,101,169,2, - 78,78,114,69,0,0,0,41,15,114,150,0,0,0,114,149, - 0,0,0,114,151,0,0,0,114,152,0,0,0,114,219,0, - 0,0,114,218,0,0,0,218,11,95,77,83,95,87,73,78, - 68,79,87,83,218,18,69,88,84,69,78,83,73,79,78,95, - 83,85,70,70,73,88,69,83,114,217,0,0,0,218,12,115, - 116,97,116,105,99,109,101,116,104,111,100,114,216,0,0,0, - 218,11,99,108,97,115,115,109,101,116,104,111,100,114,223,0, - 0,0,114,226,0,0,0,114,229,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,214,0,0,0,26,3,0,0,115,30,0,0,0,8,0, - 4,2,2,3,2,255,2,4,2,255,12,3,2,2,10,1, - 2,6,10,1,2,14,12,1,2,15,16,1,114,214,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,64,0,0,0,115,48,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, - 0,90,6,100,8,100,9,132,0,90,7,100,10,83,0,41, - 11,218,13,95,76,111,97,100,101,114,66,97,115,105,99,115, - 122,83,66,97,115,101,32,99,108,97,115,115,32,111,102,32, - 99,111,109,109,111,110,32,99,111,100,101,32,110,101,101,100, - 101,100,32,98,121,32,98,111,116,104,32,83,111,117,114,99, - 101,76,111,97,100,101,114,32,97,110,100,10,32,32,32,32, - 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, - 97,100,101,114,46,99,2,0,0,0,0,0,0,0,0,0, - 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,64, - 0,0,0,116,0,124,0,160,1,124,1,161,1,131,1,100, - 1,25,0,125,2,124,2,160,2,100,2,100,1,161,2,100, - 3,25,0,125,3,124,1,160,3,100,2,161,1,100,4,25, - 0,125,4,124,3,100,5,107,2,111,31,124,4,100,5,107, - 3,83,0,41,7,122,141,67,111,110,99,114,101,116,101,32, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, - 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, - 105,115,95,112,97,99,107,97,103,101,32,98,121,32,99,104, - 101,99,107,105,110,103,32,105,102,10,32,32,32,32,32,32, - 32,32,116,104,101,32,112,97,116,104,32,114,101,116,117,114, - 110,101,100,32,98,121,32,103,101,116,95,102,105,108,101,110, - 97,109,101,32,104,97,115,32,97,32,102,105,108,101,110,97, - 109,101,32,111,102,32,39,95,95,105,110,105,116,95,95,46, - 112,121,39,46,114,3,0,0,0,114,97,0,0,0,114,0, - 0,0,0,114,44,0,0,0,218,8,95,95,105,110,105,116, - 95,95,78,41,4,114,74,0,0,0,114,203,0,0,0,114, - 125,0,0,0,114,104,0,0,0,41,5,114,143,0,0,0, - 114,163,0,0,0,114,120,0,0,0,90,13,102,105,108,101, - 110,97,109,101,95,98,97,115,101,90,9,116,97,105,108,95, - 110,97,109,101,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,206,0,0,0,98,3,0,0,115,8,0,0, - 0,18,3,16,1,14,1,16,1,122,24,95,76,111,97,100, - 101,114,66,97,115,105,99,115,46,105,115,95,112,97,99,107, - 97,103,101,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,114,23,0,0, - 0,169,2,122,42,85,115,101,32,100,101,102,97,117,108,116, - 32,115,101,109,97,110,116,105,99,115,32,102,111,114,32,109, - 111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,78, - 114,7,0,0,0,169,2,114,143,0,0,0,114,210,0,0, + 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, + 73,2,0,0,115,28,0,0,0,12,16,8,1,16,1,12, + 1,16,1,12,1,10,1,12,1,8,1,16,1,8,2,16, + 1,16,1,4,1,114,176,0,0,0,99,5,0,0,0,0, + 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, + 0,0,0,115,124,0,0,0,116,0,124,0,100,1,100,2, + 133,2,25,0,131,1,124,1,100,3,64,0,107,3,114,31, + 100,4,124,3,155,2,157,2,125,5,116,1,160,2,100,5, + 124,5,161,2,1,0,116,3,124,5,102,1,105,0,124,4, + 164,1,142,1,130,1,124,2,100,6,117,1,114,58,116,0, + 124,0,100,2,100,7,133,2,25,0,131,1,124,2,100,3, + 64,0,107,3,114,60,116,3,100,4,124,3,155,2,157,2, + 102,1,105,0,124,4,164,1,142,1,130,1,100,6,83,0, + 100,6,83,0,41,8,97,7,2,0,0,86,97,108,105,100, + 97,116,101,32,97,32,112,121,99,32,97,103,97,105,110,115, + 116,32,116,104,101,32,115,111,117,114,99,101,32,108,97,115, + 116,45,109,111,100,105,102,105,101,100,32,116,105,109,101,46, + 10,10,32,32,32,32,42,100,97,116,97,42,32,105,115,32, + 116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32, + 116,104,101,32,112,121,99,32,102,105,108,101,46,32,40,79, + 110,108,121,32,116,104,101,32,102,105,114,115,116,32,49,54, + 32,98,121,116,101,115,32,97,114,101,10,32,32,32,32,114, + 101,113,117,105,114,101,100,46,41,10,10,32,32,32,32,42, + 115,111,117,114,99,101,95,109,116,105,109,101,42,32,105,115, + 32,116,104,101,32,108,97,115,116,32,109,111,100,105,102,105, + 101,100,32,116,105,109,101,115,116,97,109,112,32,111,102,32, + 116,104,101,32,115,111,117,114,99,101,32,102,105,108,101,46, + 10,10,32,32,32,32,42,115,111,117,114,99,101,95,115,105, + 122,101,42,32,105,115,32,78,111,110,101,32,111,114,32,116, + 104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,115, + 111,117,114,99,101,32,102,105,108,101,32,105,110,32,98,121, + 116,101,115,46,10,10,32,32,32,32,42,110,97,109,101,42, + 32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32, + 116,104,101,32,109,111,100,117,108,101,32,98,101,105,110,103, + 32,105,109,112,111,114,116,101,100,46,32,73,116,32,105,115, + 32,117,115,101,100,32,102,111,114,32,108,111,103,103,105,110, + 103,46,10,10,32,32,32,32,42,101,120,99,95,100,101,116, + 97,105,108,115,42,32,105,115,32,97,32,100,105,99,116,105, + 111,110,97,114,121,32,112,97,115,115,101,100,32,116,111,32, + 73,109,112,111,114,116,69,114,114,111,114,32,105,102,32,105, + 116,32,114,97,105,115,101,100,32,102,111,114,10,32,32,32, + 32,105,109,112,114,111,118,101,100,32,100,101,98,117,103,103, + 105,110,103,46,10,10,32,32,32,32,65,110,32,73,109,112, + 111,114,116,69,114,114,111,114,32,105,115,32,114,97,105,115, + 101,100,32,105,102,32,116,104,101,32,98,121,116,101,99,111, + 100,101,32,105,115,32,115,116,97,108,101,46,10,10,32,32, + 32,32,114,170,0,0,0,233,12,0,0,0,114,30,0,0, + 0,122,22,98,121,116,101,99,111,100,101,32,105,115,32,115, + 116,97,108,101,32,102,111,114,32,114,168,0,0,0,78,114, + 169,0,0,0,41,4,114,42,0,0,0,114,159,0,0,0, + 114,173,0,0,0,114,142,0,0,0,41,6,114,41,0,0, + 0,218,12,115,111,117,114,99,101,95,109,116,105,109,101,218, + 11,115,111,117,114,99,101,95,115,105,122,101,114,141,0,0, + 0,114,175,0,0,0,114,117,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,23,95,118,97,108, + 105,100,97,116,101,95,116,105,109,101,115,116,97,109,112,95, + 112,121,99,106,2,0,0,115,18,0,0,0,24,19,10,1, + 12,1,16,1,8,1,22,1,2,255,22,2,8,254,114,180, + 0,0,0,99,4,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,4,0,0,0,67,0,0,0,115,42,0,0, + 0,124,0,100,1,100,2,133,2,25,0,124,1,107,3,114, + 19,116,0,100,3,124,2,155,2,157,2,102,1,105,0,124, + 3,164,1,142,1,130,1,100,4,83,0,41,5,97,243,1, + 0,0,86,97,108,105,100,97,116,101,32,97,32,104,97,115, + 104,45,98,97,115,101,100,32,112,121,99,32,98,121,32,99, + 104,101,99,107,105,110,103,32,116,104,101,32,114,101,97,108, + 32,115,111,117,114,99,101,32,104,97,115,104,32,97,103,97, + 105,110,115,116,32,116,104,101,32,111,110,101,32,105,110,10, + 32,32,32,32,116,104,101,32,112,121,99,32,104,101,97,100, + 101,114,46,10,10,32,32,32,32,42,100,97,116,97,42,32, + 105,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32, + 111,102,32,116,104,101,32,112,121,99,32,102,105,108,101,46, + 32,40,79,110,108,121,32,116,104,101,32,102,105,114,115,116, + 32,49,54,32,98,121,116,101,115,32,97,114,101,10,32,32, + 32,32,114,101,113,117,105,114,101,100,46,41,10,10,32,32, + 32,32,42,115,111,117,114,99,101,95,104,97,115,104,42,32, + 105,115,32,116,104,101,32,105,109,112,111,114,116,108,105,98, + 46,117,116,105,108,46,115,111,117,114,99,101,95,104,97,115, + 104,40,41,32,111,102,32,116,104,101,32,115,111,117,114,99, + 101,32,102,105,108,101,46,10,10,32,32,32,32,42,110,97, + 109,101,42,32,105,115,32,116,104,101,32,110,97,109,101,32, + 111,102,32,116,104,101,32,109,111,100,117,108,101,32,98,101, + 105,110,103,32,105,109,112,111,114,116,101,100,46,32,73,116, + 32,105,115,32,117,115,101,100,32,102,111,114,32,108,111,103, + 103,105,110,103,46,10,10,32,32,32,32,42,101,120,99,95, + 100,101,116,97,105,108,115,42,32,105,115,32,97,32,100,105, + 99,116,105,111,110,97,114,121,32,112,97,115,115,101,100,32, + 116,111,32,73,109,112,111,114,116,69,114,114,111,114,32,105, + 102,32,105,116,32,114,97,105,115,101,100,32,102,111,114,10, + 32,32,32,32,105,109,112,114,111,118,101,100,32,100,101,98, + 117,103,103,105,110,103,46,10,10,32,32,32,32,65,110,32, + 73,109,112,111,114,116,69,114,114,111,114,32,105,115,32,114, + 97,105,115,101,100,32,105,102,32,116,104,101,32,98,121,116, + 101,99,111,100,101,32,105,115,32,115,116,97,108,101,46,10, + 10,32,32,32,32,114,170,0,0,0,114,169,0,0,0,122, + 46,104,97,115,104,32,105,110,32,98,121,116,101,99,111,100, + 101,32,100,111,101,115,110,39,116,32,109,97,116,99,104,32, + 104,97,115,104,32,111,102,32,115,111,117,114,99,101,32,78, + 41,1,114,142,0,0,0,41,4,114,41,0,0,0,218,11, + 115,111,117,114,99,101,95,104,97,115,104,114,141,0,0,0, + 114,175,0,0,0,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,218,18,95,118,97,108,105,100,97,116,101,95, + 104,97,115,104,95,112,121,99,134,2,0,0,115,14,0,0, + 0,16,17,2,1,8,1,4,255,2,2,6,254,4,255,114, + 182,0,0,0,99,4,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,5,0,0,0,67,0,0,0,115,76,0, + 0,0,116,0,160,1,124,0,161,1,125,4,116,2,124,4, + 116,3,131,2,114,28,116,4,160,5,100,1,124,2,161,2, + 1,0,124,3,100,2,117,1,114,26,116,6,160,7,124,4, + 124,3,161,2,1,0,124,4,83,0,116,8,100,3,160,9, + 124,2,161,1,124,1,124,2,100,4,141,3,130,1,41,5, + 122,35,67,111,109,112,105,108,101,32,98,121,116,101,99,111, + 100,101,32,97,115,32,102,111,117,110,100,32,105,110,32,97, + 32,112,121,99,46,122,21,99,111,100,101,32,111,98,106,101, + 99,116,32,102,114,111,109,32,123,33,114,125,78,122,23,78, + 111,110,45,99,111,100,101,32,111,98,106,101,99,116,32,105, + 110,32,123,33,114,125,169,2,114,141,0,0,0,114,65,0, + 0,0,41,10,218,7,109,97,114,115,104,97,108,90,5,108, + 111,97,100,115,218,10,105,115,105,110,115,116,97,110,99,101, + 218,10,95,99,111,100,101,95,116,121,112,101,114,159,0,0, + 0,114,173,0,0,0,218,4,95,105,109,112,90,16,95,102, + 105,120,95,99,111,95,102,105,108,101,110,97,109,101,114,142, + 0,0,0,114,89,0,0,0,41,5,114,41,0,0,0,114, + 141,0,0,0,114,132,0,0,0,114,134,0,0,0,218,4, + 99,111,100,101,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,17,95,99,111,109,112,105,108,101,95,98,121, + 116,101,99,111,100,101,158,2,0,0,115,18,0,0,0,10, + 2,10,1,12,1,8,1,12,1,4,1,10,2,4,1,6, + 255,114,189,0,0,0,99,3,0,0,0,0,0,0,0,0, + 0,0,0,4,0,0,0,5,0,0,0,67,0,0,0,115, + 70,0,0,0,116,0,116,1,131,1,125,3,124,3,160,2, + 116,3,100,1,131,1,161,1,1,0,124,3,160,2,116,3, + 124,1,131,1,161,1,1,0,124,3,160,2,116,3,124,2, + 131,1,161,1,1,0,124,3,160,2,116,4,160,5,124,0, + 161,1,161,1,1,0,124,3,83,0,41,2,122,43,80,114, + 111,100,117,99,101,32,116,104,101,32,100,97,116,97,32,102, + 111,114,32,97,32,116,105,109,101,115,116,97,109,112,45,98, + 97,115,101,100,32,112,121,99,46,114,0,0,0,0,41,6, + 218,9,98,121,116,101,97,114,114,97,121,114,172,0,0,0, + 218,6,101,120,116,101,110,100,114,36,0,0,0,114,184,0, + 0,0,218,5,100,117,109,112,115,41,4,114,188,0,0,0, + 218,5,109,116,105,109,101,114,179,0,0,0,114,41,0,0, 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 218,13,99,114,101,97,116,101,95,109,111,100,117,108,101,106, - 3,0,0,243,2,0,0,0,4,0,122,27,95,76,111,97, - 100,101,114,66,97,115,105,99,115,46,99,114,101,97,116,101, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,5,0,0,0,67,0,0,0, - 115,56,0,0,0,124,0,160,0,124,1,106,1,161,1,125, - 2,124,2,100,1,117,0,114,18,116,2,100,2,160,3,124, - 1,106,1,161,1,131,1,130,1,116,4,160,5,116,6,124, - 2,124,1,106,7,161,3,1,0,100,1,83,0,41,3,122, - 19,69,120,101,99,117,116,101,32,116,104,101,32,109,111,100, - 117,108,101,46,78,122,52,99,97,110,110,111,116,32,108,111, - 97,100,32,109,111,100,117,108,101,32,123,33,114,125,32,119, - 104,101,110,32,103,101,116,95,99,111,100,101,40,41,32,114, - 101,116,117,114,110,115,32,78,111,110,101,41,8,218,8,103, - 101,116,95,99,111,100,101,114,150,0,0,0,114,142,0,0, - 0,114,89,0,0,0,114,159,0,0,0,218,25,95,99,97, - 108,108,95,119,105,116,104,95,102,114,97,109,101,115,95,114, - 101,109,111,118,101,100,218,4,101,120,101,99,114,156,0,0, - 0,41,3,114,143,0,0,0,218,6,109,111,100,117,108,101, - 114,188,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108, - 101,109,3,0,0,115,12,0,0,0,12,2,8,1,4,1, - 8,1,4,255,20,2,122,25,95,76,111,97,100,101,114,66, - 97,115,105,99,115,46,101,120,101,99,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,4,0,0,0,67,0,0,0,115,12,0,0,0,116, - 0,160,1,124,0,124,1,161,2,83,0,41,2,122,26,84, - 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,46,78,41,2,114,159,0,0, - 0,218,17,95,108,111,97,100,95,109,111,100,117,108,101,95, - 115,104,105,109,169,2,114,143,0,0,0,114,163,0,0,0, + 218,22,95,99,111,100,101,95,116,111,95,116,105,109,101,115, + 116,97,109,112,95,112,121,99,171,2,0,0,115,12,0,0, + 0,8,2,14,1,14,1,14,1,16,1,4,1,114,194,0, + 0,0,84,99,3,0,0,0,0,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,67,0,0,0,115,80,0,0, + 0,116,0,116,1,131,1,125,3,100,1,124,2,100,1,62, + 0,66,0,125,4,124,3,160,2,116,3,124,4,131,1,161, + 1,1,0,116,4,124,1,131,1,100,2,107,2,115,25,74, + 0,130,1,124,3,160,2,124,1,161,1,1,0,124,3,160, + 2,116,5,160,6,124,0,161,1,161,1,1,0,124,3,83, + 0,41,3,122,38,80,114,111,100,117,99,101,32,116,104,101, + 32,100,97,116,97,32,102,111,114,32,97,32,104,97,115,104, + 45,98,97,115,101,100,32,112,121,99,46,114,3,0,0,0, + 114,170,0,0,0,41,7,114,190,0,0,0,114,172,0,0, + 0,114,191,0,0,0,114,36,0,0,0,114,4,0,0,0, + 114,184,0,0,0,114,192,0,0,0,41,5,114,188,0,0, + 0,114,181,0,0,0,90,7,99,104,101,99,107,101,100,114, + 41,0,0,0,114,16,0,0,0,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,218,17,95,99,111,100,101,95, + 116,111,95,104,97,115,104,95,112,121,99,181,2,0,0,115, + 14,0,0,0,8,2,12,1,14,1,16,1,10,1,16,1, + 4,1,114,195,0,0,0,99,1,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,0, + 115,62,0,0,0,100,1,100,2,108,0,125,1,116,1,160, + 2,124,0,161,1,106,3,125,2,124,1,160,4,124,2,161, + 1,125,3,116,1,160,5,100,2,100,3,161,2,125,4,124, + 4,160,6,124,0,160,6,124,3,100,1,25,0,161,1,161, + 1,83,0,41,4,122,121,68,101,99,111,100,101,32,98,121, + 116,101,115,32,114,101,112,114,101,115,101,110,116,105,110,103, + 32,115,111,117,114,99,101,32,99,111,100,101,32,97,110,100, + 32,114,101,116,117,114,110,32,116,104,101,32,115,116,114,105, + 110,103,46,10,10,32,32,32,32,85,110,105,118,101,114,115, + 97,108,32,110,101,119,108,105,110,101,32,115,117,112,112,111, + 114,116,32,105,115,32,117,115,101,100,32,105,110,32,116,104, + 101,32,100,101,99,111,100,105,110,103,46,10,32,32,32,32, + 114,0,0,0,0,78,84,41,7,218,8,116,111,107,101,110, + 105,122,101,114,91,0,0,0,90,7,66,121,116,101,115,73, + 79,90,8,114,101,97,100,108,105,110,101,90,15,100,101,116, + 101,99,116,95,101,110,99,111,100,105,110,103,90,25,73,110, + 99,114,101,109,101,110,116,97,108,78,101,119,108,105,110,101, + 68,101,99,111,100,101,114,218,6,100,101,99,111,100,101,41, + 5,218,12,115,111,117,114,99,101,95,98,121,116,101,115,114, + 196,0,0,0,90,21,115,111,117,114,99,101,95,98,121,116, + 101,115,95,114,101,97,100,108,105,110,101,218,8,101,110,99, + 111,100,105,110,103,90,15,110,101,119,108,105,110,101,95,100, + 101,99,111,100,101,114,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,218,13,100,101,99,111,100,101,95,115,111, + 117,114,99,101,192,2,0,0,115,10,0,0,0,8,5,12, + 1,10,1,12,1,20,1,114,200,0,0,0,169,2,114,164, + 0,0,0,218,26,115,117,98,109,111,100,117,108,101,95,115, + 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,99, + 2,0,0,0,0,0,0,0,2,0,0,0,9,0,0,0, + 8,0,0,0,67,0,0,0,115,54,1,0,0,124,1,100, + 1,117,0,114,29,100,2,125,1,116,0,124,2,100,3,131, + 2,114,28,122,7,124,2,160,1,124,0,161,1,125,1,87, + 0,113,57,4,0,116,2,121,27,1,0,1,0,1,0,89, + 0,113,57,119,0,110,28,116,3,160,4,124,1,161,1,125, + 1,116,5,124,1,131,1,115,57,122,9,116,6,116,3,160, + 7,161,0,124,1,131,2,125,1,87,0,110,9,4,0,116, + 8,121,56,1,0,1,0,1,0,89,0,110,1,119,0,116, + 9,106,10,124,0,124,2,124,1,100,4,141,3,125,4,100, + 5,124,4,95,11,124,2,100,1,117,0,114,99,116,12,131, + 0,68,0,93,21,92,2,125,5,125,6,124,1,160,13,116, + 14,124,6,131,1,161,1,114,96,124,5,124,0,124,1,131, + 2,125,2,124,2,124,4,95,15,1,0,113,99,113,75,100, + 1,83,0,124,3,116,16,117,0,114,131,116,0,124,2,100, + 6,131,2,114,130,122,7,124,2,160,17,124,0,161,1,125, + 7,87,0,110,9,4,0,116,2,121,124,1,0,1,0,1, + 0,89,0,113,134,119,0,124,7,114,130,103,0,124,4,95, + 18,110,3,124,3,124,4,95,18,124,4,106,18,103,0,107, + 2,114,153,124,1,114,153,116,19,124,1,131,1,100,7,25, + 0,125,8,124,4,106,18,160,20,124,8,161,1,1,0,124, + 4,83,0,41,8,97,61,1,0,0,82,101,116,117,114,110, + 32,97,32,109,111,100,117,108,101,32,115,112,101,99,32,98, + 97,115,101,100,32,111,110,32,97,32,102,105,108,101,32,108, + 111,99,97,116,105,111,110,46,10,10,32,32,32,32,84,111, + 32,105,110,100,105,99,97,116,101,32,116,104,97,116,32,116, + 104,101,32,109,111,100,117,108,101,32,105,115,32,97,32,112, + 97,99,107,97,103,101,44,32,115,101,116,10,32,32,32,32, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,32,116,111,32,97,32, + 108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114, + 121,32,112,97,116,104,115,46,32,32,65,110,10,32,32,32, + 32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,115, + 117,102,102,105,99,105,101,110,116,44,32,116,104,111,117,103, + 104,32,105,116,115,32,110,111,116,32,111,116,104,101,114,119, + 105,115,101,32,117,115,101,102,117,108,32,116,111,32,116,104, + 101,10,32,32,32,32,105,109,112,111,114,116,32,115,121,115, + 116,101,109,46,10,10,32,32,32,32,84,104,101,32,108,111, + 97,100,101,114,32,109,117,115,116,32,116,97,107,101,32,97, + 32,115,112,101,99,32,97,115,32,105,116,115,32,111,110,108, + 121,32,95,95,105,110,105,116,95,95,40,41,32,97,114,103, + 46,10,10,32,32,32,32,78,122,9,60,117,110,107,110,111, + 119,110,62,218,12,103,101,116,95,102,105,108,101,110,97,109, + 101,169,1,218,6,111,114,105,103,105,110,84,218,10,105,115, + 95,112,97,99,107,97,103,101,114,0,0,0,0,41,21,114, + 153,0,0,0,114,203,0,0,0,114,142,0,0,0,114,18, + 0,0,0,114,103,0,0,0,114,86,0,0,0,114,67,0, + 0,0,114,82,0,0,0,114,76,0,0,0,114,159,0,0, + 0,218,10,77,111,100,117,108,101,83,112,101,99,90,13,95, + 115,101,116,95,102,105,108,101,97,116,116,114,218,27,95,103, + 101,116,95,115,117,112,112,111,114,116,101,100,95,102,105,108, + 101,95,108,111,97,100,101,114,115,114,58,0,0,0,114,136, + 0,0,0,114,164,0,0,0,218,9,95,80,79,80,85,76, + 65,84,69,114,206,0,0,0,114,202,0,0,0,114,74,0, + 0,0,114,61,0,0,0,41,9,114,141,0,0,0,90,8, + 108,111,99,97,116,105,111,110,114,164,0,0,0,114,202,0, + 0,0,218,4,115,112,101,99,218,12,108,111,97,100,101,114, + 95,99,108,97,115,115,218,8,115,117,102,102,105,120,101,115, + 114,206,0,0,0,90,7,100,105,114,110,97,109,101,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,23,115, + 112,101,99,95,102,114,111,109,95,102,105,108,101,95,108,111, + 99,97,116,105,111,110,209,2,0,0,115,84,0,0,0,8, + 12,4,4,10,1,2,2,14,1,12,1,4,1,2,255,2, + 252,10,7,8,1,2,1,18,1,12,1,4,1,2,255,16, + 9,6,1,8,3,14,1,14,1,10,1,6,1,4,1,2, + 253,4,5,8,3,10,2,2,1,14,1,12,1,4,1,2, + 255,4,3,6,1,2,128,6,2,10,1,4,1,12,1,12, + 1,4,2,114,213,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, + 0,115,88,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,90,4,100,3,90,5,101,6,111,15,100,4, + 101,7,118,0,90,8,101,9,100,5,100,6,132,0,131,1, + 90,10,101,11,100,7,100,8,132,0,131,1,90,12,101,11, + 100,14,100,10,100,11,132,1,131,1,90,13,101,11,100,15, + 100,12,100,13,132,1,131,1,90,14,100,9,83,0,41,16, + 218,21,87,105,110,100,111,119,115,82,101,103,105,115,116,114, + 121,70,105,110,100,101,114,122,62,77,101,116,97,32,112,97, + 116,104,32,102,105,110,100,101,114,32,102,111,114,32,109,111, + 100,117,108,101,115,32,100,101,99,108,97,114,101,100,32,105, + 110,32,116,104,101,32,87,105,110,100,111,119,115,32,114,101, + 103,105,115,116,114,121,46,122,59,83,111,102,116,119,97,114, + 101,92,80,121,116,104,111,110,92,80,121,116,104,111,110,67, + 111,114,101,92,123,115,121,115,95,118,101,114,115,105,111,110, + 125,92,77,111,100,117,108,101,115,92,123,102,117,108,108,110, + 97,109,101,125,122,65,83,111,102,116,119,97,114,101,92,80, + 121,116,104,111,110,92,80,121,116,104,111,110,67,111,114,101, + 92,123,115,121,115,95,118,101,114,115,105,111,110,125,92,77, + 111,100,117,108,101,115,92,123,102,117,108,108,110,97,109,101, + 125,92,68,101,98,117,103,122,6,95,100,46,112,121,100,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 8,0,0,0,67,0,0,0,115,50,0,0,0,122,8,116, + 0,160,1,116,0,106,2,124,0,161,2,87,0,83,0,4, + 0,116,3,121,24,1,0,1,0,1,0,116,0,160,1,116, + 0,106,4,124,0,161,2,6,0,89,0,83,0,119,0,114, + 69,0,0,0,41,5,218,6,119,105,110,114,101,103,90,7, + 79,112,101,110,75,101,121,90,17,72,75,69,89,95,67,85, + 82,82,69,78,84,95,85,83,69,82,114,76,0,0,0,90, + 18,72,75,69,89,95,76,79,67,65,76,95,77,65,67,72, + 73,78,69,114,19,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,218,14,95,111,112,101,110,95,114, + 101,103,105,115,116,114,121,38,3,0,0,115,10,0,0,0, + 2,2,16,1,12,1,18,1,2,255,122,36,87,105,110,100, + 111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101, + 114,46,95,111,112,101,110,95,114,101,103,105,115,116,114,121, + 99,2,0,0,0,0,0,0,0,0,0,0,0,6,0,0, + 0,8,0,0,0,67,0,0,0,115,134,0,0,0,124,0, + 106,0,114,7,124,0,106,1,125,2,110,3,124,0,106,2, + 125,2,124,2,106,3,124,1,100,1,116,4,106,5,100,0, + 100,2,133,2,25,0,22,0,100,3,141,2,125,3,122,32, + 124,0,160,6,124,3,161,1,143,16,125,4,116,7,160,8, + 124,4,100,4,161,2,125,5,87,0,100,0,4,0,4,0, + 131,3,1,0,87,0,124,5,83,0,49,0,115,49,119,1, + 1,0,1,0,1,0,89,0,1,0,87,0,124,5,83,0, + 4,0,116,9,121,66,1,0,1,0,1,0,89,0,100,0, + 83,0,119,0,41,5,78,122,5,37,100,46,37,100,114,44, + 0,0,0,41,2,114,163,0,0,0,90,11,115,121,115,95, + 118,101,114,115,105,111,110,114,10,0,0,0,41,10,218,11, + 68,69,66,85,71,95,66,85,73,76,68,218,18,82,69,71, + 73,83,84,82,89,95,75,69,89,95,68,69,66,85,71,218, + 12,82,69,71,73,83,84,82,89,95,75,69,89,114,89,0, + 0,0,114,15,0,0,0,218,12,118,101,114,115,105,111,110, + 95,105,110,102,111,114,216,0,0,0,114,215,0,0,0,90, + 10,81,117,101,114,121,86,97,108,117,101,114,76,0,0,0, + 41,6,218,3,99,108,115,114,163,0,0,0,90,12,114,101, + 103,105,115,116,114,121,95,107,101,121,114,20,0,0,0,90, + 4,104,107,101,121,218,8,102,105,108,101,112,97,116,104,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,16, + 95,115,101,97,114,99,104,95,114,101,103,105,115,116,114,121, + 45,3,0,0,115,32,0,0,0,6,2,8,1,6,2,6, + 1,16,1,6,255,2,2,12,1,14,1,12,255,4,4,18, + 252,4,4,12,254,6,1,2,255,122,38,87,105,110,100,111, + 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, + 46,95,115,101,97,114,99,104,95,114,101,103,105,115,116,114, + 121,78,99,4,0,0,0,0,0,0,0,0,0,0,0,8, + 0,0,0,8,0,0,0,67,0,0,0,115,120,0,0,0, + 124,0,160,0,124,1,161,1,125,4,124,4,100,0,117,0, + 114,11,100,0,83,0,122,6,116,1,124,4,131,1,1,0, + 87,0,110,10,4,0,116,2,121,27,1,0,1,0,1,0, + 89,0,100,0,83,0,119,0,116,3,131,0,68,0,93,26, + 92,2,125,5,125,6,124,4,160,4,116,5,124,6,131,1, + 161,1,114,57,116,6,106,7,124,1,124,5,124,1,124,4, + 131,2,124,4,100,1,141,3,125,7,124,7,2,0,1,0, + 83,0,113,31,100,0,83,0,41,2,78,114,204,0,0,0, + 41,8,114,223,0,0,0,114,75,0,0,0,114,76,0,0, + 0,114,208,0,0,0,114,58,0,0,0,114,136,0,0,0, + 114,159,0,0,0,218,16,115,112,101,99,95,102,114,111,109, + 95,108,111,97,100,101,114,41,8,114,221,0,0,0,114,163, + 0,0,0,114,65,0,0,0,218,6,116,97,114,103,101,116, + 114,222,0,0,0,114,164,0,0,0,114,212,0,0,0,114, + 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,9,102,105,110,100,95,115,112,101,99,60,3, + 0,0,115,34,0,0,0,10,2,8,1,4,1,2,1,12, + 1,12,1,6,1,2,255,14,2,14,1,6,1,8,1,2, + 1,6,254,8,3,2,252,4,255,122,31,87,105,110,100,111, + 119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114, + 46,102,105,110,100,95,115,112,101,99,99,3,0,0,0,0, + 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, + 0,0,0,115,42,0,0,0,116,0,160,1,100,1,116,2, + 161,2,1,0,124,0,160,3,124,1,124,2,161,2,125,3, + 124,3,100,2,117,1,114,19,124,3,106,4,83,0,100,2, + 83,0,41,3,122,106,70,105,110,100,32,109,111,100,117,108, + 101,32,110,97,109,101,100,32,105,110,32,116,104,101,32,114, + 101,103,105,115,116,114,121,46,10,10,32,32,32,32,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, + 122,112,87,105,110,100,111,119,115,82,101,103,105,115,116,114, + 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, + 117,108,101,40,41,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, + 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, + 116,104,111,110,32,51,46,49,50,59,32,117,115,101,32,102, + 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, + 97,100,78,169,5,114,99,0,0,0,114,100,0,0,0,114, + 101,0,0,0,114,226,0,0,0,114,164,0,0,0,169,4, + 114,221,0,0,0,114,163,0,0,0,114,65,0,0,0,114, + 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,11,102,105,110,100,95,109,111,100,117,108,101, + 76,3,0,0,115,14,0,0,0,6,7,2,2,4,254,12, + 3,8,1,6,1,4,2,122,33,87,105,110,100,111,119,115, + 82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,102, + 105,110,100,95,109,111,100,117,108,101,169,2,78,78,114,69, + 0,0,0,41,15,114,150,0,0,0,114,149,0,0,0,114, + 151,0,0,0,114,152,0,0,0,114,219,0,0,0,114,218, + 0,0,0,218,11,95,77,83,95,87,73,78,68,79,87,83, + 218,18,69,88,84,69,78,83,73,79,78,95,83,85,70,70, + 73,88,69,83,114,217,0,0,0,218,12,115,116,97,116,105, + 99,109,101,116,104,111,100,114,216,0,0,0,218,11,99,108, + 97,115,115,109,101,116,104,111,100,114,223,0,0,0,114,226, + 0,0,0,114,229,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,214,0,0, + 0,26,3,0,0,115,30,0,0,0,8,0,4,2,2,3, + 2,255,2,4,2,255,12,3,2,2,10,1,2,6,10,1, + 2,14,12,1,2,15,16,1,114,214,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,64,0,0,0,115,48,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, + 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, + 8,100,9,132,0,90,7,100,10,83,0,41,11,218,13,95, + 76,111,97,100,101,114,66,97,115,105,99,115,122,83,66,97, + 115,101,32,99,108,97,115,115,32,111,102,32,99,111,109,109, + 111,110,32,99,111,100,101,32,110,101,101,100,101,100,32,98, + 121,32,98,111,116,104,32,83,111,117,114,99,101,76,111,97, + 100,101,114,32,97,110,100,10,32,32,32,32,83,111,117,114, + 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, + 46,99,2,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,0,4,0,0,0,67,0,0,0,115,64,0,0,0,116, + 0,124,0,160,1,124,1,161,1,131,1,100,1,25,0,125, + 2,124,2,160,2,100,2,100,1,161,2,100,3,25,0,125, + 3,124,1,160,3,100,2,161,1,100,4,25,0,125,4,124, + 3,100,5,107,2,111,31,124,4,100,5,107,3,83,0,41, + 6,122,141,67,111,110,99,114,101,116,101,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,111,102,32,73,110, + 115,112,101,99,116,76,111,97,100,101,114,46,105,115,95,112, + 97,99,107,97,103,101,32,98,121,32,99,104,101,99,107,105, + 110,103,32,105,102,10,32,32,32,32,32,32,32,32,116,104, + 101,32,112,97,116,104,32,114,101,116,117,114,110,101,100,32, + 98,121,32,103,101,116,95,102,105,108,101,110,97,109,101,32, + 104,97,115,32,97,32,102,105,108,101,110,97,109,101,32,111, + 102,32,39,95,95,105,110,105,116,95,95,46,112,121,39,46, + 114,3,0,0,0,114,97,0,0,0,114,0,0,0,0,114, + 44,0,0,0,218,8,95,95,105,110,105,116,95,95,41,4, + 114,74,0,0,0,114,203,0,0,0,114,125,0,0,0,114, + 104,0,0,0,41,5,114,143,0,0,0,114,163,0,0,0, + 114,120,0,0,0,90,13,102,105,108,101,110,97,109,101,95, + 98,97,115,101,90,9,116,97,105,108,95,110,97,109,101,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,206, + 0,0,0,98,3,0,0,115,8,0,0,0,18,3,16,1, + 14,1,16,1,122,24,95,76,111,97,100,101,114,66,97,115, + 105,99,115,46,105,115,95,112,97,99,107,97,103,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,114,23,0,0,0,169,2,122,42, + 85,115,101,32,100,101,102,97,117,108,116,32,115,101,109,97, + 110,116,105,99,115,32,102,111,114,32,109,111,100,117,108,101, + 32,99,114,101,97,116,105,111,110,46,78,114,7,0,0,0, + 169,2,114,143,0,0,0,114,210,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,13,99,114,101, + 97,116,101,95,109,111,100,117,108,101,106,3,0,0,243,2, + 0,0,0,4,0,122,27,95,76,111,97,100,101,114,66,97, + 115,105,99,115,46,99,114,101,97,116,101,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,5,0,0,0,67,0,0,0,115,56,0,0,0, + 124,0,160,0,124,1,106,1,161,1,125,2,124,2,100,1, + 117,0,114,18,116,2,100,2,160,3,124,1,106,1,161,1, + 131,1,130,1,116,4,160,5,116,6,124,2,124,1,106,7, + 161,3,1,0,100,1,83,0,41,3,122,19,69,120,101,99, + 117,116,101,32,116,104,101,32,109,111,100,117,108,101,46,78, + 122,52,99,97,110,110,111,116,32,108,111,97,100,32,109,111, + 100,117,108,101,32,123,33,114,125,32,119,104,101,110,32,103, + 101,116,95,99,111,100,101,40,41,32,114,101,116,117,114,110, + 115,32,78,111,110,101,41,8,218,8,103,101,116,95,99,111, + 100,101,114,150,0,0,0,114,142,0,0,0,114,89,0,0, + 0,114,159,0,0,0,218,25,95,99,97,108,108,95,119,105, + 116,104,95,102,114,97,109,101,115,95,114,101,109,111,118,101, + 100,218,4,101,120,101,99,114,156,0,0,0,41,3,114,143, + 0,0,0,218,6,109,111,100,117,108,101,114,188,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 11,108,111,97,100,95,109,111,100,117,108,101,117,3,0,0, - 115,2,0,0,0,12,3,122,25,95,76,111,97,100,101,114, - 66,97,115,105,99,115,46,108,111,97,100,95,109,111,100,117, - 108,101,78,41,8,114,150,0,0,0,114,149,0,0,0,114, - 151,0,0,0,114,152,0,0,0,114,206,0,0,0,114,239, - 0,0,0,114,245,0,0,0,114,248,0,0,0,114,7,0, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,235,0,0,0,93,3,0,0,115,12,0,0,0,8, - 0,4,2,8,3,8,8,8,3,12,8,114,235,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,64,0,0,0,115,74,0,0,0,101,0, - 90,1,100,0,90,2,100,1,100,2,132,0,90,3,100,3, - 100,4,132,0,90,4,100,5,100,6,132,0,90,5,100,7, - 100,8,132,0,90,6,100,9,100,10,132,0,90,7,100,11, - 100,12,156,1,100,13,100,14,132,2,90,8,100,15,100,16, - 132,0,90,9,100,17,83,0,41,18,218,12,83,111,117,114, - 99,101,76,111,97,100,101,114,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,116,0,130,1,41,2,122,165,79,112, - 116,105,111,110,97,108,32,109,101,116,104,111,100,32,116,104, - 97,116,32,114,101,116,117,114,110,115,32,116,104,101,32,109, - 111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101, - 32,40,97,110,32,105,110,116,41,32,102,111,114,32,116,104, - 101,10,32,32,32,32,32,32,32,32,115,112,101,99,105,102, - 105,101,100,32,112,97,116,104,32,40,97,32,115,116,114,41, - 46,10,10,32,32,32,32,32,32,32,32,82,97,105,115,101, - 115,32,79,83,69,114,114,111,114,32,119,104,101,110,32,116, - 104,101,32,112,97,116,104,32,99,97,110,110,111,116,32,98, - 101,32,104,97,110,100,108,101,100,46,10,32,32,32,32,32, - 32,32,32,78,41,1,114,76,0,0,0,169,2,114,143,0, - 0,0,114,65,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,218,10,112,97,116,104,95,109,116,105, - 109,101,125,3,0,0,115,2,0,0,0,4,6,122,23,83, - 111,117,114,99,101,76,111,97,100,101,114,46,112,97,116,104, - 95,109,116,105,109,101,99,2,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,67,0,0,0,115, - 14,0,0,0,100,1,124,0,160,0,124,1,161,1,105,1, - 83,0,41,3,97,158,1,0,0,79,112,116,105,111,110,97, - 108,32,109,101,116,104,111,100,32,114,101,116,117,114,110,105, - 110,103,32,97,32,109,101,116,97,100,97,116,97,32,100,105, - 99,116,32,102,111,114,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,10,32,32,32,32,32,32,32,32,112,97,116, - 104,32,40,97,32,115,116,114,41,46,10,10,32,32,32,32, - 32,32,32,32,80,111,115,115,105,98,108,101,32,107,101,121, - 115,58,10,32,32,32,32,32,32,32,32,45,32,39,109,116, - 105,109,101,39,32,40,109,97,110,100,97,116,111,114,121,41, - 32,105,115,32,116,104,101,32,110,117,109,101,114,105,99,32, - 116,105,109,101,115,116,97,109,112,32,111,102,32,108,97,115, - 116,32,115,111,117,114,99,101,10,32,32,32,32,32,32,32, - 32,32,32,99,111,100,101,32,109,111,100,105,102,105,99,97, - 116,105,111,110,59,10,32,32,32,32,32,32,32,32,45,32, - 39,115,105,122,101,39,32,40,111,112,116,105,111,110,97,108, - 41,32,105,115,32,116,104,101,32,115,105,122,101,32,105,110, - 32,98,121,116,101,115,32,111,102,32,116,104,101,32,115,111, - 117,114,99,101,32,99,111,100,101,46,10,10,32,32,32,32, - 32,32,32,32,73,109,112,108,101,109,101,110,116,105,110,103, - 32,116,104,105,115,32,109,101,116,104,111,100,32,97,108,108, - 111,119,115,32,116,104,101,32,108,111,97,100,101,114,32,116, - 111,32,114,101,97,100,32,98,121,116,101,99,111,100,101,32, - 102,105,108,101,115,46,10,32,32,32,32,32,32,32,32,82, - 97,105,115,101,115,32,79,83,69,114,114,111,114,32,119,104, - 101,110,32,116,104,101,32,112,97,116,104,32,99,97,110,110, - 111,116,32,98,101,32,104,97,110,100,108,101,100,46,10,32, - 32,32,32,32,32,32,32,114,193,0,0,0,78,41,1,114, - 251,0,0,0,114,250,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,10,112,97,116,104,95,115, - 116,97,116,115,133,3,0,0,115,2,0,0,0,14,12,122, - 23,83,111,117,114,99,101,76,111,97,100,101,114,46,112,97, - 116,104,95,115,116,97,116,115,99,4,0,0,0,0,0,0, - 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, - 0,115,12,0,0,0,124,0,160,0,124,2,124,3,161,2, - 83,0,41,2,122,228,79,112,116,105,111,110,97,108,32,109, + 11,101,120,101,99,95,109,111,100,117,108,101,109,3,0,0, + 115,12,0,0,0,12,2,8,1,4,1,8,1,4,255,20, + 2,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, + 0,67,0,0,0,115,12,0,0,0,116,0,160,1,124,0, + 124,1,161,2,83,0,41,1,122,26,84,104,105,115,32,109, + 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,46,41,2,114,159,0,0,0,218,17,95,108,111, + 97,100,95,109,111,100,117,108,101,95,115,104,105,109,169,2, + 114,143,0,0,0,114,163,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,218,11,108,111,97,100,95, + 109,111,100,117,108,101,117,3,0,0,115,2,0,0,0,12, + 3,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,108,111,97,100,95,109,111,100,117,108,101,78,41,8,114, + 150,0,0,0,114,149,0,0,0,114,151,0,0,0,114,152, + 0,0,0,114,206,0,0,0,114,239,0,0,0,114,245,0, + 0,0,114,248,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,235,0,0,0, + 93,3,0,0,115,12,0,0,0,8,0,4,2,8,3,8, + 8,8,3,12,8,114,235,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, + 0,0,0,115,74,0,0,0,101,0,90,1,100,0,90,2, + 100,1,100,2,132,0,90,3,100,3,100,4,132,0,90,4, + 100,5,100,6,132,0,90,5,100,7,100,8,132,0,90,6, + 100,9,100,10,132,0,90,7,100,11,100,12,156,1,100,13, + 100,14,132,2,90,8,100,15,100,16,132,0,90,9,100,17, + 83,0,41,18,218,12,83,111,117,114,99,101,76,111,97,100, + 101,114,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, + 116,0,130,1,41,1,122,165,79,112,116,105,111,110,97,108, + 32,109,101,116,104,111,100,32,116,104,97,116,32,114,101,116, + 117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,99, + 97,116,105,111,110,32,116,105,109,101,32,40,97,110,32,105, + 110,116,41,32,102,111,114,32,116,104,101,10,32,32,32,32, + 32,32,32,32,115,112,101,99,105,102,105,101,100,32,112,97, + 116,104,32,40,97,32,115,116,114,41,46,10,10,32,32,32, + 32,32,32,32,32,82,97,105,115,101,115,32,79,83,69,114, + 114,111,114,32,119,104,101,110,32,116,104,101,32,112,97,116, + 104,32,99,97,110,110,111,116,32,98,101,32,104,97,110,100, + 108,101,100,46,10,32,32,32,32,32,32,32,32,41,1,114, + 76,0,0,0,169,2,114,143,0,0,0,114,65,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, + 10,112,97,116,104,95,109,116,105,109,101,125,3,0,0,115, + 2,0,0,0,4,6,122,23,83,111,117,114,99,101,76,111, + 97,100,101,114,46,112,97,116,104,95,109,116,105,109,101,99, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 4,0,0,0,67,0,0,0,115,14,0,0,0,100,1,124, + 0,160,0,124,1,161,1,105,1,83,0,41,2,97,158,1, + 0,0,79,112,116,105,111,110,97,108,32,109,101,116,104,111, + 100,32,114,101,116,117,114,110,105,110,103,32,97,32,109,101, + 116,97,100,97,116,97,32,100,105,99,116,32,102,111,114,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,10,32,32, + 32,32,32,32,32,32,112,97,116,104,32,40,97,32,115,116, + 114,41,46,10,10,32,32,32,32,32,32,32,32,80,111,115, + 115,105,98,108,101,32,107,101,121,115,58,10,32,32,32,32, + 32,32,32,32,45,32,39,109,116,105,109,101,39,32,40,109, + 97,110,100,97,116,111,114,121,41,32,105,115,32,116,104,101, + 32,110,117,109,101,114,105,99,32,116,105,109,101,115,116,97, + 109,112,32,111,102,32,108,97,115,116,32,115,111,117,114,99, + 101,10,32,32,32,32,32,32,32,32,32,32,99,111,100,101, + 32,109,111,100,105,102,105,99,97,116,105,111,110,59,10,32, + 32,32,32,32,32,32,32,45,32,39,115,105,122,101,39,32, + 40,111,112,116,105,111,110,97,108,41,32,105,115,32,116,104, + 101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32, + 111,102,32,116,104,101,32,115,111,117,114,99,101,32,99,111, + 100,101,46,10,10,32,32,32,32,32,32,32,32,73,109,112, + 108,101,109,101,110,116,105,110,103,32,116,104,105,115,32,109, + 101,116,104,111,100,32,97,108,108,111,119,115,32,116,104,101, + 32,108,111,97,100,101,114,32,116,111,32,114,101,97,100,32, + 98,121,116,101,99,111,100,101,32,102,105,108,101,115,46,10, + 32,32,32,32,32,32,32,32,82,97,105,115,101,115,32,79, + 83,69,114,114,111,114,32,119,104,101,110,32,116,104,101,32, + 112,97,116,104,32,99,97,110,110,111,116,32,98,101,32,104, + 97,110,100,108,101,100,46,10,32,32,32,32,32,32,32,32, + 114,193,0,0,0,41,1,114,251,0,0,0,114,250,0,0, + 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, + 218,10,112,97,116,104,95,115,116,97,116,115,133,3,0,0, + 115,2,0,0,0,14,12,122,23,83,111,117,114,99,101,76, + 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, + 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, + 0,4,0,0,0,67,0,0,0,115,12,0,0,0,124,0, + 160,0,124,2,124,3,161,2,83,0,41,1,122,228,79,112, + 116,105,111,110,97,108,32,109,101,116,104,111,100,32,119,104, + 105,99,104,32,119,114,105,116,101,115,32,100,97,116,97,32, + 40,98,121,116,101,115,41,32,116,111,32,97,32,102,105,108, + 101,32,112,97,116,104,32,40,97,32,115,116,114,41,46,10, + 10,32,32,32,32,32,32,32,32,73,109,112,108,101,109,101, + 110,116,105,110,103,32,116,104,105,115,32,109,101,116,104,111, + 100,32,97,108,108,111,119,115,32,102,111,114,32,116,104,101, + 32,119,114,105,116,105,110,103,32,111,102,32,98,121,116,101, + 99,111,100,101,32,102,105,108,101,115,46,10,10,32,32,32, + 32,32,32,32,32,84,104,101,32,115,111,117,114,99,101,32, + 112,97,116,104,32,105,115,32,110,101,101,100,101,100,32,105, + 110,32,111,114,100,101,114,32,116,111,32,99,111,114,114,101, + 99,116,108,121,32,116,114,97,110,115,102,101,114,32,112,101, + 114,109,105,115,115,105,111,110,115,10,32,32,32,32,32,32, + 32,32,41,1,218,8,115,101,116,95,100,97,116,97,41,4, + 114,143,0,0,0,114,134,0,0,0,90,10,99,97,99,104, + 101,95,112,97,116,104,114,41,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,15,95,99,97,99, + 104,101,95,98,121,116,101,99,111,100,101,147,3,0,0,115, + 2,0,0,0,12,8,122,28,83,111,117,114,99,101,76,111, + 97,100,101,114,46,95,99,97,99,104,101,95,98,121,116,101, + 99,111,100,101,99,3,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,1,0,0,0,67,0,0,0,114,23,0, + 0,0,41,2,122,150,79,112,116,105,111,110,97,108,32,109, 101,116,104,111,100,32,119,104,105,99,104,32,119,114,105,116, 101,115,32,100,97,116,97,32,40,98,121,116,101,115,41,32, 116,111,32,97,32,102,105,108,101,32,112,97,116,104,32,40, @@ -1323,778 +1346,753 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,115,32,109,101,116,104,111,100,32,97,108,108,111,119,115, 32,102,111,114,32,116,104,101,32,119,114,105,116,105,110,103, 32,111,102,32,98,121,116,101,99,111,100,101,32,102,105,108, - 101,115,46,10,10,32,32,32,32,32,32,32,32,84,104,101, - 32,115,111,117,114,99,101,32,112,97,116,104,32,105,115,32, - 110,101,101,100,101,100,32,105,110,32,111,114,100,101,114,32, - 116,111,32,99,111,114,114,101,99,116,108,121,32,116,114,97, - 110,115,102,101,114,32,112,101,114,109,105,115,115,105,111,110, - 115,10,32,32,32,32,32,32,32,32,78,41,1,218,8,115, - 101,116,95,100,97,116,97,41,4,114,143,0,0,0,114,134, - 0,0,0,90,10,99,97,99,104,101,95,112,97,116,104,114, - 41,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,218,15,95,99,97,99,104,101,95,98,121,116,101, - 99,111,100,101,147,3,0,0,115,2,0,0,0,12,8,122, - 28,83,111,117,114,99,101,76,111,97,100,101,114,46,95,99, - 97,99,104,101,95,98,121,116,101,99,111,100,101,99,3,0, - 0,0,0,0,0,0,0,0,0,0,3,0,0,0,1,0, - 0,0,67,0,0,0,114,23,0,0,0,41,2,122,150,79, - 112,116,105,111,110,97,108,32,109,101,116,104,111,100,32,119, - 104,105,99,104,32,119,114,105,116,101,115,32,100,97,116,97, - 32,40,98,121,116,101,115,41,32,116,111,32,97,32,102,105, - 108,101,32,112,97,116,104,32,40,97,32,115,116,114,41,46, - 10,10,32,32,32,32,32,32,32,32,73,109,112,108,101,109, - 101,110,116,105,110,103,32,116,104,105,115,32,109,101,116,104, - 111,100,32,97,108,108,111,119,115,32,102,111,114,32,116,104, - 101,32,119,114,105,116,105,110,103,32,111,102,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,115,46,10,32,32,32, - 32,32,32,32,32,78,114,7,0,0,0,41,3,114,143,0, - 0,0,114,65,0,0,0,114,41,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,253,0,0,0, - 157,3,0,0,114,240,0,0,0,122,21,83,111,117,114,99, - 101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,97, - 99,2,0,0,0,0,0,0,0,0,0,0,0,5,0,0, - 0,10,0,0,0,67,0,0,0,115,70,0,0,0,124,0, - 160,0,124,1,161,1,125,2,122,10,124,0,160,1,124,2, - 161,1,125,3,87,0,116,4,124,3,131,1,83,0,4,0, - 116,2,121,34,1,0,125,4,1,0,122,7,116,3,100,1, - 124,1,100,2,141,2,124,4,130,2,100,3,125,4,126,4, - 119,1,119,0,41,4,122,52,67,111,110,99,114,101,116,101, - 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, - 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,46,122,39,115,111, - 117,114,99,101,32,110,111,116,32,97,118,97,105,108,97,98, - 108,101,32,116,104,114,111,117,103,104,32,103,101,116,95,100, - 97,116,97,40,41,114,140,0,0,0,78,41,5,114,203,0, - 0,0,218,8,103,101,116,95,100,97,116,97,114,76,0,0, - 0,114,142,0,0,0,114,200,0,0,0,41,5,114,143,0, - 0,0,114,163,0,0,0,114,65,0,0,0,114,198,0,0, - 0,218,3,101,120,99,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,10,103,101,116,95,115,111,117,114,99, - 101,164,3,0,0,115,24,0,0,0,10,2,2,1,12,1, - 8,4,14,253,4,1,2,1,4,255,2,1,2,255,8,128, - 2,255,122,23,83,111,117,114,99,101,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,114,130,0,0,0, - 41,1,218,9,95,111,112,116,105,109,105,122,101,99,3,0, - 0,0,0,0,0,0,1,0,0,0,4,0,0,0,8,0, - 0,0,67,0,0,0,115,22,0,0,0,116,0,106,1,116, - 2,124,1,124,2,100,1,100,2,124,3,100,3,141,6,83, - 0,41,5,122,130,82,101,116,117,114,110,32,116,104,101,32, - 99,111,100,101,32,111,98,106,101,99,116,32,99,111,109,112, - 105,108,101,100,32,102,114,111,109,32,115,111,117,114,99,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,39, - 100,97,116,97,39,32,97,114,103,117,109,101,110,116,32,99, - 97,110,32,98,101,32,97,110,121,32,111,98,106,101,99,116, - 32,116,121,112,101,32,116,104,97,116,32,99,111,109,112,105, - 108,101,40,41,32,115,117,112,112,111,114,116,115,46,10,32, - 32,32,32,32,32,32,32,114,243,0,0,0,84,41,2,218, - 12,100,111,110,116,95,105,110,104,101,114,105,116,114,108,0, - 0,0,78,41,3,114,159,0,0,0,114,242,0,0,0,218, - 7,99,111,109,112,105,108,101,41,4,114,143,0,0,0,114, - 41,0,0,0,114,65,0,0,0,114,2,1,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,218,14,115, - 111,117,114,99,101,95,116,111,95,99,111,100,101,174,3,0, - 0,115,6,0,0,0,12,5,4,1,6,255,122,27,83,111, - 117,114,99,101,76,111,97,100,101,114,46,115,111,117,114,99, - 101,95,116,111,95,99,111,100,101,99,2,0,0,0,0,0, - 0,0,0,0,0,0,15,0,0,0,9,0,0,0,67,0, - 0,0,115,12,2,0,0,124,0,160,0,124,1,161,1,125, - 2,100,1,125,3,100,1,125,4,100,1,125,5,100,2,125, - 6,100,3,125,7,122,6,116,1,124,2,131,1,125,8,87, - 0,110,11,4,0,116,2,144,1,121,5,1,0,1,0,1, - 0,100,1,125,8,89,0,110,143,122,7,124,0,160,3,124, - 2,161,1,125,9,87,0,110,9,4,0,116,4,144,1,121, - 4,1,0,1,0,1,0,89,0,110,126,116,5,124,9,100, - 4,25,0,131,1,125,3,122,7,124,0,160,6,124,8,161, - 1,125,10,87,0,110,9,4,0,116,4,144,1,121,3,1, - 0,1,0,1,0,89,0,110,103,124,1,124,8,100,5,156, - 2,125,11,122,71,116,7,124,10,124,1,124,11,131,3,125, - 12,116,8,124,10,131,1,100,6,100,1,133,2,25,0,125, - 13,124,12,100,7,64,0,100,8,107,3,125,6,124,6,114, - 138,124,12,100,9,64,0,100,8,107,3,125,7,116,9,106, - 10,100,10,107,3,114,137,124,7,115,119,116,9,106,10,100, - 11,107,2,114,137,124,0,160,6,124,2,161,1,125,4,116, - 9,160,11,116,12,124,4,161,2,125,5,116,13,124,10,124, - 5,124,1,124,11,131,4,1,0,110,10,116,14,124,10,124, - 3,124,9,100,12,25,0,124,1,124,11,131,5,1,0,87, - 0,110,11,4,0,116,15,116,16,102,2,144,1,121,2,1, - 0,1,0,1,0,89,0,110,15,116,17,160,18,100,13,124, - 8,124,2,161,3,1,0,116,19,124,13,124,1,124,8,124, - 2,100,14,141,4,83,0,124,4,100,1,117,0,114,185,124, - 0,160,6,124,2,161,1,125,4,124,0,160,20,124,4,124, - 2,161,2,125,14,116,17,160,18,100,15,124,2,161,2,1, - 0,116,21,106,22,115,255,124,8,100,1,117,1,114,255,124, - 3,100,1,117,1,114,255,124,6,114,226,124,5,100,1,117, - 0,114,219,116,9,160,11,124,4,161,1,125,5,116,23,124, - 14,124,5,124,7,131,3,125,10,110,8,116,24,124,14,124, - 3,116,25,124,4,131,1,131,3,125,10,122,10,124,0,160, - 26,124,2,124,8,124,10,161,3,1,0,87,0,124,14,83, - 0,4,0,116,2,144,1,121,1,1,0,1,0,1,0,89, - 0,124,14,83,0,124,14,83,0,119,0,119,0,119,0,119, - 0,119,0,41,16,122,190,67,111,110,99,114,101,116,101,32, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, - 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, - 103,101,116,95,99,111,100,101,46,10,10,32,32,32,32,32, - 32,32,32,82,101,97,100,105,110,103,32,111,102,32,98,121, - 116,101,99,111,100,101,32,114,101,113,117,105,114,101,115,32, - 112,97,116,104,95,115,116,97,116,115,32,116,111,32,98,101, - 32,105,109,112,108,101,109,101,110,116,101,100,46,32,84,111, - 32,119,114,105,116,101,10,32,32,32,32,32,32,32,32,98, - 121,116,101,99,111,100,101,44,32,115,101,116,95,100,97,116, - 97,32,109,117,115,116,32,97,108,115,111,32,98,101,32,105, - 109,112,108,101,109,101,110,116,101,100,46,10,10,32,32,32, - 32,32,32,32,32,78,70,84,114,193,0,0,0,114,183,0, - 0,0,114,169,0,0,0,114,3,0,0,0,114,0,0,0, - 0,114,44,0,0,0,90,5,110,101,118,101,114,90,6,97, - 108,119,97,121,115,218,4,115,105,122,101,122,13,123,125,32, - 109,97,116,99,104,101,115,32,123,125,41,3,114,141,0,0, - 0,114,132,0,0,0,114,134,0,0,0,122,19,99,111,100, - 101,32,111,98,106,101,99,116,32,102,114,111,109,32,123,125, - 41,27,114,203,0,0,0,114,121,0,0,0,114,107,0,0, - 0,114,252,0,0,0,114,76,0,0,0,114,33,0,0,0, - 114,255,0,0,0,114,176,0,0,0,218,10,109,101,109,111, - 114,121,118,105,101,119,114,187,0,0,0,90,21,99,104,101, - 99,107,95,104,97,115,104,95,98,97,115,101,100,95,112,121, - 99,115,114,181,0,0,0,218,17,95,82,65,87,95,77,65, - 71,73,67,95,78,85,77,66,69,82,114,182,0,0,0,114, - 180,0,0,0,114,142,0,0,0,114,174,0,0,0,114,159, - 0,0,0,114,173,0,0,0,114,189,0,0,0,114,5,1, - 0,0,114,15,0,0,0,218,19,100,111,110,116,95,119,114, - 105,116,101,95,98,121,116,101,99,111,100,101,114,195,0,0, - 0,114,194,0,0,0,114,4,0,0,0,114,254,0,0,0, - 41,15,114,143,0,0,0,114,163,0,0,0,114,134,0,0, - 0,114,178,0,0,0,114,198,0,0,0,114,181,0,0,0, - 90,10,104,97,115,104,95,98,97,115,101,100,90,12,99,104, - 101,99,107,95,115,111,117,114,99,101,114,132,0,0,0,218, - 2,115,116,114,41,0,0,0,114,175,0,0,0,114,16,0, - 0,0,90,10,98,121,116,101,115,95,100,97,116,97,90,11, - 99,111,100,101,95,111,98,106,101,99,116,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,241,0,0,0,182, - 3,0,0,115,168,0,0,0,10,7,4,1,4,1,4,1, - 4,1,4,1,2,1,12,1,14,1,8,1,2,2,14,1, - 14,1,4,1,12,2,2,1,14,1,14,1,4,1,2,3, - 2,1,6,254,2,4,12,1,16,1,12,1,4,1,12,1, - 10,1,2,1,2,255,8,2,2,254,10,3,4,1,2,1, - 2,1,4,254,8,4,2,1,4,255,2,128,2,3,2,1, - 2,1,6,1,2,1,2,1,4,251,4,128,18,7,4,1, - 8,2,2,1,4,255,6,2,2,1,2,1,6,254,8,3, - 10,1,12,1,12,1,14,1,6,1,2,255,4,2,8,1, - 10,1,14,1,6,2,6,1,4,255,2,2,16,1,4,3, - 14,254,2,1,8,1,2,254,2,233,2,225,2,250,2,251, - 122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,78,41,10,114,150,0,0,0,114, - 149,0,0,0,114,151,0,0,0,114,251,0,0,0,114,252, - 0,0,0,114,254,0,0,0,114,253,0,0,0,114,1,1, - 0,0,114,5,1,0,0,114,241,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,249,0,0,0,123,3,0,0,115,16,0,0,0,8,0, - 8,2,8,8,8,14,8,10,8,7,14,10,12,8,114,249, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,4,0,0,0,0,0,0,0,115,92,0,0, + 101,115,46,10,32,32,32,32,32,32,32,32,78,114,7,0, + 0,0,41,3,114,143,0,0,0,114,65,0,0,0,114,41, + 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,253,0,0,0,157,3,0,0,114,240,0,0,0, + 122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,115, + 101,116,95,100,97,116,97,99,2,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,10,0,0,0,67,0,0,0, + 115,70,0,0,0,124,0,160,0,124,1,161,1,125,2,122, + 10,124,0,160,1,124,2,161,1,125,3,87,0,116,4,124, + 3,131,1,83,0,4,0,116,2,121,34,1,0,125,4,1, + 0,122,7,116,3,100,1,124,1,100,2,141,2,124,4,130, + 2,100,3,125,4,126,4,119,1,119,0,41,4,122,52,67, + 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, + 116,97,116,105,111,110,32,111,102,32,73,110,115,112,101,99, + 116,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, + 99,101,46,122,39,115,111,117,114,99,101,32,110,111,116,32, + 97,118,97,105,108,97,98,108,101,32,116,104,114,111,117,103, + 104,32,103,101,116,95,100,97,116,97,40,41,114,140,0,0, + 0,78,41,5,114,203,0,0,0,218,8,103,101,116,95,100, + 97,116,97,114,76,0,0,0,114,142,0,0,0,114,200,0, + 0,0,41,5,114,143,0,0,0,114,163,0,0,0,114,65, + 0,0,0,114,198,0,0,0,218,3,101,120,99,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,218,10,103,101, + 116,95,115,111,117,114,99,101,164,3,0,0,115,24,0,0, + 0,10,2,2,1,12,1,8,4,14,253,4,1,2,1,4, + 255,2,1,2,255,8,128,2,255,122,23,83,111,117,114,99, + 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, + 99,101,114,130,0,0,0,41,1,218,9,95,111,112,116,105, + 109,105,122,101,99,3,0,0,0,0,0,0,0,1,0,0, + 0,4,0,0,0,8,0,0,0,67,0,0,0,115,22,0, + 0,0,116,0,106,1,116,2,124,1,124,2,100,1,100,2, + 124,3,100,3,141,6,83,0,41,4,122,130,82,101,116,117, + 114,110,32,116,104,101,32,99,111,100,101,32,111,98,106,101, + 99,116,32,99,111,109,112,105,108,101,100,32,102,114,111,109, + 32,115,111,117,114,99,101,46,10,10,32,32,32,32,32,32, + 32,32,84,104,101,32,39,100,97,116,97,39,32,97,114,103, + 117,109,101,110,116,32,99,97,110,32,98,101,32,97,110,121, + 32,111,98,106,101,99,116,32,116,121,112,101,32,116,104,97, + 116,32,99,111,109,112,105,108,101,40,41,32,115,117,112,112, + 111,114,116,115,46,10,32,32,32,32,32,32,32,32,114,243, + 0,0,0,84,41,2,218,12,100,111,110,116,95,105,110,104, + 101,114,105,116,114,108,0,0,0,41,3,114,159,0,0,0, + 114,242,0,0,0,218,7,99,111,109,112,105,108,101,41,4, + 114,143,0,0,0,114,41,0,0,0,114,65,0,0,0,114, + 2,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,14,115,111,117,114,99,101,95,116,111,95,99, + 111,100,101,174,3,0,0,115,6,0,0,0,12,5,4,1, + 6,255,122,27,83,111,117,114,99,101,76,111,97,100,101,114, + 46,115,111,117,114,99,101,95,116,111,95,99,111,100,101,99, + 2,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0, + 9,0,0,0,67,0,0,0,115,2,2,0,0,124,0,160, + 0,124,1,161,1,125,2,100,1,125,3,100,1,125,4,100, + 1,125,5,100,2,125,6,100,3,125,7,122,6,116,1,124, + 2,131,1,125,8,87,0,110,11,4,0,116,2,121,32,1, + 0,1,0,1,0,100,1,125,8,89,0,110,144,119,0,122, + 7,124,0,160,3,124,2,161,1,125,9,87,0,110,9,4, + 0,116,4,121,49,1,0,1,0,1,0,89,0,110,127,119, + 0,116,5,124,9,100,4,25,0,131,1,125,3,122,7,124, + 0,160,6,124,8,161,1,125,10,87,0,110,9,4,0,116, + 4,121,72,1,0,1,0,1,0,89,0,110,104,119,0,124, + 1,124,8,100,5,156,2,125,11,122,71,116,7,124,10,124, + 1,124,11,131,3,125,12,116,8,124,10,131,1,100,6,100, + 1,133,2,25,0,125,13,124,12,100,7,64,0,100,8,107, + 3,125,6,124,6,114,138,124,12,100,9,64,0,100,8,107, + 3,125,7,116,9,106,10,100,10,107,3,114,137,124,7,115, + 119,116,9,106,10,100,11,107,2,114,137,124,0,160,6,124, + 2,161,1,125,4,116,9,160,11,116,12,124,4,161,2,125, + 5,116,13,124,10,124,5,124,1,124,11,131,4,1,0,110, + 10,116,14,124,10,124,3,124,9,100,12,25,0,124,1,124, + 11,131,5,1,0,87,0,110,11,4,0,116,15,116,16,102, + 2,121,160,1,0,1,0,1,0,89,0,110,16,119,0,116, + 17,160,18,100,13,124,8,124,2,161,3,1,0,116,19,124, + 13,124,1,124,8,124,2,100,14,141,4,83,0,124,4,100, + 1,117,0,114,185,124,0,160,6,124,2,161,1,125,4,124, + 0,160,20,124,4,124,2,161,2,125,14,116,17,160,18,100, + 15,124,2,161,2,1,0,116,21,106,22,115,255,124,8,100, + 1,117,1,114,255,124,3,100,1,117,1,114,255,124,6,114, + 226,124,5,100,1,117,0,114,219,116,9,160,11,124,4,161, + 1,125,5,116,23,124,14,124,5,124,7,131,3,125,10,110, + 8,116,24,124,14,124,3,116,25,124,4,131,1,131,3,125, + 10,122,10,124,0,160,26,124,2,124,8,124,10,161,3,1, + 0,87,0,124,14,83,0,4,0,116,2,121,254,1,0,1, + 0,1,0,89,0,124,14,83,0,119,0,124,14,83,0,41, + 16,122,190,67,111,110,99,114,101,116,101,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,111,102,32,73,110, + 115,112,101,99,116,76,111,97,100,101,114,46,103,101,116,95, + 99,111,100,101,46,10,10,32,32,32,32,32,32,32,32,82, + 101,97,100,105,110,103,32,111,102,32,98,121,116,101,99,111, + 100,101,32,114,101,113,117,105,114,101,115,32,112,97,116,104, + 95,115,116,97,116,115,32,116,111,32,98,101,32,105,109,112, + 108,101,109,101,110,116,101,100,46,32,84,111,32,119,114,105, + 116,101,10,32,32,32,32,32,32,32,32,98,121,116,101,99, + 111,100,101,44,32,115,101,116,95,100,97,116,97,32,109,117, + 115,116,32,97,108,115,111,32,98,101,32,105,109,112,108,101, + 109,101,110,116,101,100,46,10,10,32,32,32,32,32,32,32, + 32,78,70,84,114,193,0,0,0,114,183,0,0,0,114,169, + 0,0,0,114,3,0,0,0,114,0,0,0,0,114,44,0, + 0,0,90,5,110,101,118,101,114,90,6,97,108,119,97,121, + 115,218,4,115,105,122,101,122,13,123,125,32,109,97,116,99, + 104,101,115,32,123,125,41,3,114,141,0,0,0,114,132,0, + 0,0,114,134,0,0,0,122,19,99,111,100,101,32,111,98, + 106,101,99,116,32,102,114,111,109,32,123,125,41,27,114,203, + 0,0,0,114,121,0,0,0,114,107,0,0,0,114,252,0, + 0,0,114,76,0,0,0,114,33,0,0,0,114,255,0,0, + 0,114,176,0,0,0,218,10,109,101,109,111,114,121,118,105, + 101,119,114,187,0,0,0,90,21,99,104,101,99,107,95,104, + 97,115,104,95,98,97,115,101,100,95,112,121,99,115,114,181, + 0,0,0,218,17,95,82,65,87,95,77,65,71,73,67,95, + 78,85,77,66,69,82,114,182,0,0,0,114,180,0,0,0, + 114,142,0,0,0,114,174,0,0,0,114,159,0,0,0,114, + 173,0,0,0,114,189,0,0,0,114,5,1,0,0,114,15, + 0,0,0,218,19,100,111,110,116,95,119,114,105,116,101,95, + 98,121,116,101,99,111,100,101,114,195,0,0,0,114,194,0, + 0,0,114,4,0,0,0,114,254,0,0,0,41,15,114,143, + 0,0,0,114,163,0,0,0,114,134,0,0,0,114,178,0, + 0,0,114,198,0,0,0,114,181,0,0,0,90,10,104,97, + 115,104,95,98,97,115,101,100,90,12,99,104,101,99,107,95, + 115,111,117,114,99,101,114,132,0,0,0,218,2,115,116,114, + 41,0,0,0,114,175,0,0,0,114,16,0,0,0,90,10, + 98,121,116,101,115,95,100,97,116,97,90,11,99,111,100,101, + 95,111,98,106,101,99,116,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,241,0,0,0,182,3,0,0,115, + 170,0,0,0,10,7,4,1,4,1,4,1,4,1,4,1, + 2,1,12,1,12,1,8,1,2,255,2,3,14,1,12,1, + 4,1,2,255,12,3,2,1,14,1,12,1,4,1,2,255, + 2,4,2,1,6,254,2,4,12,1,16,1,12,1,4,1, + 12,1,10,1,2,1,2,255,8,2,2,254,10,3,4,1, + 2,1,2,1,4,254,8,4,2,1,4,255,2,128,2,3, + 2,1,2,1,6,1,2,1,2,1,4,251,4,128,16,7, + 4,1,2,255,8,3,2,1,4,255,6,2,2,1,2,1, + 6,254,8,3,10,1,12,1,12,1,14,1,6,1,2,255, + 4,2,8,1,10,1,14,1,6,2,6,1,4,255,2,2, + 16,1,4,3,12,254,2,1,4,1,2,254,4,2,122,21, + 83,111,117,114,99,101,76,111,97,100,101,114,46,103,101,116, + 95,99,111,100,101,78,41,10,114,150,0,0,0,114,149,0, + 0,0,114,151,0,0,0,114,251,0,0,0,114,252,0,0, + 0,114,254,0,0,0,114,253,0,0,0,114,1,1,0,0, + 114,5,1,0,0,114,241,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,249, + 0,0,0,123,3,0,0,115,16,0,0,0,8,0,8,2, + 8,8,8,14,8,10,8,7,14,10,12,8,114,249,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,4,0,0,0,0,0,0,0,115,92,0,0,0,101, + 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, + 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, + 0,90,6,101,7,135,0,102,1,100,8,100,9,132,8,131, + 1,90,8,101,7,100,10,100,11,132,0,131,1,90,9,100, + 12,100,13,132,0,90,10,101,7,100,14,100,15,132,0,131, + 1,90,11,135,0,4,0,90,12,83,0,41,16,218,10,70, + 105,108,101,76,111,97,100,101,114,122,103,66,97,115,101,32, + 102,105,108,101,32,108,111,97,100,101,114,32,99,108,97,115, + 115,32,119,104,105,99,104,32,105,109,112,108,101,109,101,110, + 116,115,32,116,104,101,32,108,111,97,100,101,114,32,112,114, + 111,116,111,99,111,108,32,109,101,116,104,111,100,115,32,116, + 104,97,116,10,32,32,32,32,114,101,113,117,105,114,101,32, + 102,105,108,101,32,115,121,115,116,101,109,32,117,115,97,103, + 101,46,99,3,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, + 124,1,124,0,95,0,124,2,124,0,95,1,100,1,83,0, + 41,2,122,75,67,97,99,104,101,32,116,104,101,32,109,111, + 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, + 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, + 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, + 114,183,0,0,0,41,3,114,143,0,0,0,114,163,0,0, + 0,114,65,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,236,0,0,0,16,4,0,0,115,4, + 0,0,0,6,3,10,1,122,19,70,105,108,101,76,111,97, + 100,101,114,46,95,95,105,110,105,116,95,95,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,243,24,0,0,0,124,0,106,0,124,1, + 106,0,107,2,111,11,124,0,106,1,124,1,106,1,107,2, + 83,0,114,69,0,0,0,169,2,218,9,95,95,99,108,97, + 115,115,95,95,114,156,0,0,0,169,2,114,143,0,0,0, + 90,5,111,116,104,101,114,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,218,6,95,95,101,113,95,95,22,4, + 0,0,243,6,0,0,0,12,1,10,1,2,255,122,17,70, + 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,243,20,0,0,0,116,0, + 124,0,106,1,131,1,116,0,124,0,106,2,131,1,65,0, + 83,0,114,69,0,0,0,169,3,218,4,104,97,115,104,114, + 141,0,0,0,114,65,0,0,0,169,1,114,143,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, + 8,95,95,104,97,115,104,95,95,26,4,0,0,243,2,0, + 0,0,20,1,122,19,70,105,108,101,76,111,97,100,101,114, + 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, + 0,0,115,16,0,0,0,116,0,116,1,124,0,131,2,160, + 2,124,1,161,1,83,0,41,1,122,100,76,111,97,100,32, + 97,32,109,111,100,117,108,101,32,102,114,111,109,32,97,32, + 102,105,108,101,46,10,10,32,32,32,32,32,32,32,32,84, + 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, + 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,101, + 120,101,99,95,109,111,100,117,108,101,40,41,32,105,110,115, + 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,41, + 3,218,5,115,117,112,101,114,114,11,1,0,0,114,248,0, + 0,0,114,247,0,0,0,169,1,114,14,1,0,0,114,7, + 0,0,0,114,8,0,0,0,114,248,0,0,0,29,4,0, + 0,115,2,0,0,0,16,10,122,22,70,105,108,101,76,111, + 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,243,6,0,0,0,124,0, + 106,0,83,0,169,1,122,58,82,101,116,117,114,110,32,116, + 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, + 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, + 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, + 114,46,114,71,0,0,0,114,247,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,203,0,0,0, + 41,4,0,0,243,2,0,0,0,6,3,122,23,70,105,108, + 101,76,111,97,100,101,114,46,103,101,116,95,102,105,108,101, + 110,97,109,101,99,2,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,8,0,0,0,67,0,0,0,115,128,0, + 0,0,116,0,124,0,116,1,116,2,102,2,131,2,114,36, + 116,3,160,4,116,5,124,1,131,1,161,1,143,12,125,2, + 124,2,160,6,161,0,87,0,2,0,100,1,4,0,4,0, + 131,3,1,0,83,0,49,0,115,29,119,1,1,0,1,0, + 1,0,89,0,1,0,100,1,83,0,116,3,160,7,124,1, + 100,2,161,2,143,12,125,2,124,2,160,6,161,0,87,0, + 2,0,100,1,4,0,4,0,131,3,1,0,83,0,49,0, + 115,57,119,1,1,0,1,0,1,0,89,0,1,0,100,1, + 83,0,41,3,122,39,82,101,116,117,114,110,32,116,104,101, + 32,100,97,116,97,32,102,114,111,109,32,112,97,116,104,32, + 97,115,32,114,97,119,32,98,121,116,101,115,46,78,218,1, + 114,41,8,114,185,0,0,0,114,249,0,0,0,218,19,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,114,91,0,0,0,90,9,111,112,101,110,95,99,111, + 100,101,114,109,0,0,0,90,4,114,101,97,100,114,92,0, + 0,0,41,3,114,143,0,0,0,114,65,0,0,0,114,94, + 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,255,0,0,0,46,4,0,0,115,14,0,0,0, + 14,2,16,1,6,1,36,255,14,3,6,1,36,255,122,19, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,100, + 97,116,97,99,2,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,2,0,0,0,67,0,0,0,115,20,0,0, + 0,100,1,100,2,108,0,109,1,125,2,1,0,124,2,124, + 0,131,1,83,0,41,3,78,114,0,0,0,0,41,1,218, + 10,70,105,108,101,82,101,97,100,101,114,41,2,218,17,105, + 109,112,111,114,116,108,105,98,46,114,101,97,100,101,114,115, + 114,31,1,0,0,41,3,114,143,0,0,0,114,244,0,0, + 0,114,31,1,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,218,19,103,101,116,95,114,101,115,111,117, + 114,99,101,95,114,101,97,100,101,114,55,4,0,0,115,4, + 0,0,0,12,2,8,1,122,30,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,114,101,115,111,117,114,99,101, + 95,114,101,97,100,101,114,41,13,114,150,0,0,0,114,149, + 0,0,0,114,151,0,0,0,114,152,0,0,0,114,236,0, + 0,0,114,16,1,0,0,114,22,1,0,0,114,160,0,0, + 0,114,248,0,0,0,114,203,0,0,0,114,255,0,0,0, + 114,33,1,0,0,90,13,95,95,99,108,97,115,115,99,101, + 108,108,95,95,114,7,0,0,0,114,7,0,0,0,114,25, + 1,0,0,114,8,0,0,0,114,11,1,0,0,11,4,0, + 0,115,24,0,0,0,8,0,4,2,8,3,8,6,8,4, + 2,3,14,1,2,11,10,1,8,4,2,9,18,1,114,11, + 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,64,0,0,0,115,46,0,0, 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, - 7,132,0,90,6,101,7,135,0,102,1,100,8,100,9,132, - 8,131,1,90,8,101,7,100,10,100,11,132,0,131,1,90, - 9,100,12,100,13,132,0,90,10,101,7,100,14,100,15,132, - 0,131,1,90,11,135,0,4,0,90,12,83,0,41,16,218, - 10,70,105,108,101,76,111,97,100,101,114,122,103,66,97,115, - 101,32,102,105,108,101,32,108,111,97,100,101,114,32,99,108, - 97,115,115,32,119,104,105,99,104,32,105,109,112,108,101,109, - 101,110,116,115,32,116,104,101,32,108,111,97,100,101,114,32, - 112,114,111,116,111,99,111,108,32,109,101,116,104,111,100,115, - 32,116,104,97,116,10,32,32,32,32,114,101,113,117,105,114, - 101,32,102,105,108,101,32,115,121,115,116,101,109,32,117,115, - 97,103,101,46,99,3,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,2,0,0,0,67,0,0,0,115,16,0, - 0,0,124,1,124,0,95,0,124,2,124,0,95,1,100,1, - 83,0,41,2,122,75,67,97,99,104,101,32,116,104,101,32, - 109,111,100,117,108,101,32,110,97,109,101,32,97,110,100,32, - 116,104,101,32,112,97,116,104,32,116,111,32,116,104,101,32, - 102,105,108,101,32,102,111,117,110,100,32,98,121,32,116,104, - 101,10,32,32,32,32,32,32,32,32,102,105,110,100,101,114, - 46,78,114,183,0,0,0,41,3,114,143,0,0,0,114,163, - 0,0,0,114,65,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,236,0,0,0,16,4,0,0, - 115,4,0,0,0,6,3,10,1,122,19,70,105,108,101,76, - 111,97,100,101,114,46,95,95,105,110,105,116,95,95,99,2, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2, - 0,0,0,67,0,0,0,243,24,0,0,0,124,0,106,0, - 124,1,106,0,107,2,111,11,124,0,106,1,124,1,106,1, - 107,2,83,0,114,69,0,0,0,169,2,218,9,95,95,99, - 108,97,115,115,95,95,114,156,0,0,0,169,2,114,143,0, - 0,0,90,5,111,116,104,101,114,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,6,95,95,101,113,95,95, - 22,4,0,0,243,6,0,0,0,12,1,10,1,2,255,122, - 17,70,105,108,101,76,111,97,100,101,114,46,95,95,101,113, - 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,243,20,0,0,0, - 116,0,124,0,106,1,131,1,116,0,124,0,106,2,131,1, - 65,0,83,0,114,69,0,0,0,169,3,218,4,104,97,115, - 104,114,141,0,0,0,114,65,0,0,0,169,1,114,143,0, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,8,95,95,104,97,115,104,95,95,26,4,0,0,243, - 2,0,0,0,20,1,122,19,70,105,108,101,76,111,97,100, - 101,114,46,95,95,104,97,115,104,95,95,99,2,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 3,0,0,0,115,16,0,0,0,116,0,116,1,124,0,131, - 2,160,2,124,1,161,1,83,0,41,2,122,100,76,111,97, - 100,32,97,32,109,111,100,117,108,101,32,102,114,111,109,32, - 97,32,102,105,108,101,46,10,10,32,32,32,32,32,32,32, - 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, - 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, - 32,101,120,101,99,95,109,111,100,117,108,101,40,41,32,105, - 110,115,116,101,97,100,46,10,10,32,32,32,32,32,32,32, - 32,78,41,3,218,5,115,117,112,101,114,114,11,1,0,0, - 114,248,0,0,0,114,247,0,0,0,169,1,114,14,1,0, - 0,114,7,0,0,0,114,8,0,0,0,114,248,0,0,0, - 29,4,0,0,115,2,0,0,0,16,10,122,22,70,105,108, - 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,243,6,0,0, - 0,124,0,106,0,83,0,169,2,122,58,82,101,116,117,114, - 110,32,116,104,101,32,112,97,116,104,32,116,111,32,116,104, - 101,32,115,111,117,114,99,101,32,102,105,108,101,32,97,115, - 32,102,111,117,110,100,32,98,121,32,116,104,101,32,102,105, - 110,100,101,114,46,78,114,71,0,0,0,114,247,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 203,0,0,0,41,4,0,0,243,2,0,0,0,6,3,122, - 23,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, - 102,105,108,101,110,97,109,101,99,2,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,128,0,0,0,116,0,124,0,116,1,116,2,102,2, - 131,2,114,36,116,3,160,4,116,5,124,1,131,1,161,1, - 143,12,125,2,124,2,160,6,161,0,87,0,2,0,100,1, - 4,0,4,0,131,3,1,0,83,0,49,0,115,29,119,1, - 1,0,1,0,1,0,89,0,1,0,100,1,83,0,116,3, - 160,7,124,1,100,2,161,2,143,12,125,2,124,2,160,6, - 161,0,87,0,2,0,100,1,4,0,4,0,131,3,1,0, - 83,0,49,0,115,57,119,1,1,0,1,0,1,0,89,0, - 1,0,100,1,83,0,41,3,122,39,82,101,116,117,114,110, - 32,116,104,101,32,100,97,116,97,32,102,114,111,109,32,112, - 97,116,104,32,97,115,32,114,97,119,32,98,121,116,101,115, - 46,78,218,1,114,41,8,114,185,0,0,0,114,249,0,0, - 0,218,19,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,114,91,0,0,0,90,9,111,112,101, - 110,95,99,111,100,101,114,109,0,0,0,90,4,114,101,97, - 100,114,92,0,0,0,41,3,114,143,0,0,0,114,65,0, - 0,0,114,94,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,255,0,0,0,46,4,0,0,115, - 22,0,0,0,14,2,16,1,6,1,14,255,2,1,20,255, - 14,3,6,1,14,255,2,1,20,255,122,19,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,99, - 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 2,0,0,0,67,0,0,0,115,20,0,0,0,100,1,100, - 2,108,0,109,1,125,2,1,0,124,2,124,0,131,1,83, - 0,41,3,78,114,0,0,0,0,41,1,218,10,70,105,108, - 101,82,101,97,100,101,114,41,2,218,17,105,109,112,111,114, - 116,108,105,98,46,114,101,97,100,101,114,115,114,31,1,0, - 0,41,3,114,143,0,0,0,114,244,0,0,0,114,31,1, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,19,103,101,116,95,114,101,115,111,117,114,99,101,95, - 114,101,97,100,101,114,55,4,0,0,115,4,0,0,0,12, - 2,8,1,122,30,70,105,108,101,76,111,97,100,101,114,46, - 103,101,116,95,114,101,115,111,117,114,99,101,95,114,101,97, - 100,101,114,41,13,114,150,0,0,0,114,149,0,0,0,114, - 151,0,0,0,114,152,0,0,0,114,236,0,0,0,114,16, - 1,0,0,114,22,1,0,0,114,160,0,0,0,114,248,0, - 0,0,114,203,0,0,0,114,255,0,0,0,114,33,1,0, - 0,90,13,95,95,99,108,97,115,115,99,101,108,108,95,95, - 114,7,0,0,0,114,7,0,0,0,114,25,1,0,0,114, - 8,0,0,0,114,11,1,0,0,11,4,0,0,115,24,0, - 0,0,8,0,4,2,8,3,8,6,8,4,2,3,14,1, - 2,11,10,1,8,4,2,9,18,1,114,11,1,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,64,0,0,0,115,46,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, - 4,100,4,100,5,132,0,90,5,100,6,100,7,156,1,100, - 8,100,9,132,2,90,6,100,10,83,0,41,11,218,16,83, - 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,122, - 62,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,32,111,102,32,83,111,117,114, - 99,101,76,111,97,100,101,114,32,117,115,105,110,103,32,116, - 104,101,32,102,105,108,101,32,115,121,115,116,101,109,46,99, - 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 3,0,0,0,67,0,0,0,115,22,0,0,0,116,0,124, - 1,131,1,125,2,124,2,106,1,124,2,106,2,100,1,156, - 2,83,0,41,3,122,33,82,101,116,117,114,110,32,116,104, - 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,116, - 104,101,32,112,97,116,104,46,41,2,114,193,0,0,0,114, - 6,1,0,0,78,41,3,114,75,0,0,0,218,8,115,116, - 95,109,116,105,109,101,90,7,115,116,95,115,105,122,101,41, - 3,114,143,0,0,0,114,65,0,0,0,114,10,1,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 252,0,0,0,65,4,0,0,115,4,0,0,0,8,2,14, - 1,122,27,83,111,117,114,99,101,70,105,108,101,76,111,97, - 100,101,114,46,112,97,116,104,95,115,116,97,116,115,99,4, - 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,24,0,0,0,116,0,124,1, - 131,1,125,4,124,0,106,1,124,2,124,3,124,4,100,1, - 141,3,83,0,41,2,78,169,1,218,5,95,109,111,100,101, - 41,2,114,139,0,0,0,114,253,0,0,0,41,5,114,143, - 0,0,0,114,134,0,0,0,114,132,0,0,0,114,41,0, - 0,0,114,78,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,254,0,0,0,70,4,0,0,115, - 4,0,0,0,8,2,16,1,122,32,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,95,99,97,99,104, - 101,95,98,121,116,101,99,111,100,101,114,87,0,0,0,114, - 36,1,0,0,99,3,0,0,0,0,0,0,0,1,0,0, - 0,9,0,0,0,11,0,0,0,67,0,0,0,115,254,0, - 0,0,116,0,124,1,131,1,92,2,125,4,125,5,103,0, - 125,6,124,4,114,31,116,1,124,4,131,1,115,31,116,0, - 124,4,131,1,92,2,125,4,125,7,124,6,160,2,124,7, - 161,1,1,0,124,4,114,31,116,1,124,4,131,1,114,14, - 116,3,124,6,131,1,68,0,93,48,125,7,116,4,124,4, - 124,7,131,2,125,4,122,7,116,5,160,6,124,4,161,1, - 1,0,87,0,113,35,4,0,116,7,121,58,1,0,1,0, - 1,0,89,0,113,35,4,0,116,8,121,126,1,0,125,8, - 1,0,122,15,116,9,160,10,100,1,124,4,124,8,161,3, - 1,0,87,0,89,0,100,2,125,8,126,8,1,0,100,2, - 83,0,100,2,125,8,126,8,119,1,122,15,116,11,124,1, - 124,2,124,3,131,3,1,0,116,9,160,10,100,3,124,1, - 161,2,1,0,87,0,100,2,83,0,4,0,116,8,121,125, - 1,0,125,8,1,0,122,14,116,9,160,10,100,1,124,1, - 124,8,161,3,1,0,87,0,89,0,100,2,125,8,126,8, - 100,2,83,0,100,2,125,8,126,8,119,1,119,0,119,0, - 41,4,122,27,87,114,105,116,101,32,98,121,116,101,115,32, - 100,97,116,97,32,116,111,32,97,32,102,105,108,101,46,122, - 27,99,111,117,108,100,32,110,111,116,32,99,114,101,97,116, - 101,32,123,33,114,125,58,32,123,33,114,125,78,122,12,99, - 114,101,97,116,101,100,32,123,33,114,125,41,12,114,74,0, - 0,0,114,83,0,0,0,114,61,0,0,0,218,8,114,101, - 118,101,114,115,101,100,114,67,0,0,0,114,18,0,0,0, - 90,5,109,107,100,105,114,218,15,70,105,108,101,69,120,105, - 115,116,115,69,114,114,111,114,114,76,0,0,0,114,159,0, - 0,0,114,173,0,0,0,114,95,0,0,0,41,9,114,143, - 0,0,0,114,65,0,0,0,114,41,0,0,0,114,37,1, - 0,0,218,6,112,97,114,101,110,116,114,120,0,0,0,114, - 63,0,0,0,114,68,0,0,0,114,0,1,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,114,253,0, - 0,0,75,4,0,0,115,56,0,0,0,12,2,4,1,12, - 2,12,1,10,1,12,254,12,4,10,1,2,1,14,1,12, - 1,4,2,14,1,6,3,4,1,4,255,16,2,8,128,2, - 1,12,1,18,1,14,1,8,2,2,1,18,255,8,128,2, - 254,2,247,122,25,83,111,117,114,99,101,70,105,108,101,76, - 111,97,100,101,114,46,115,101,116,95,100,97,116,97,78,41, - 7,114,150,0,0,0,114,149,0,0,0,114,151,0,0,0, - 114,152,0,0,0,114,252,0,0,0,114,254,0,0,0,114, - 253,0,0,0,114,7,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,34,1,0,0,61,4,0, - 0,115,10,0,0,0,8,0,4,2,8,2,8,5,18,5, - 114,34,1,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,32, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, - 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, - 6,83,0,41,7,218,20,83,111,117,114,99,101,108,101,115, - 115,70,105,108,101,76,111,97,100,101,114,122,45,76,111,97, - 100,101,114,32,119,104,105,99,104,32,104,97,110,100,108,101, - 115,32,115,111,117,114,99,101,108,101,115,115,32,102,105,108, - 101,32,105,109,112,111,114,116,115,46,99,2,0,0,0,0, - 0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,67, - 0,0,0,115,68,0,0,0,124,0,160,0,124,1,161,1, - 125,2,124,0,160,1,124,2,161,1,125,3,124,1,124,2, - 100,1,156,2,125,4,116,2,124,3,124,1,124,4,131,3, - 1,0,116,3,116,4,124,3,131,1,100,2,100,0,133,2, - 25,0,124,1,124,2,100,3,141,3,83,0,41,4,78,114, - 183,0,0,0,114,169,0,0,0,41,2,114,141,0,0,0, - 114,132,0,0,0,41,5,114,203,0,0,0,114,255,0,0, - 0,114,176,0,0,0,114,189,0,0,0,114,7,1,0,0, - 41,5,114,143,0,0,0,114,163,0,0,0,114,65,0,0, - 0,114,41,0,0,0,114,175,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,241,0,0,0,110, - 4,0,0,115,22,0,0,0,10,1,10,1,2,4,2,1, - 6,254,12,4,2,1,14,1,2,1,2,1,6,253,122,29, - 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,99,111,100,101,99,2,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,114,23,0,0,0,41,2,122,39,82, - 101,116,117,114,110,32,78,111,110,101,32,97,115,32,116,104, - 101,114,101,32,105,115,32,110,111,32,115,111,117,114,99,101, - 32,99,111,100,101,46,78,114,7,0,0,0,114,247,0,0, + 7,156,1,100,8,100,9,132,2,90,6,100,10,83,0,41, + 11,218,16,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,122,62,67,111,110,99,114,101,116,101,32,105,109, + 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, + 83,111,117,114,99,101,76,111,97,100,101,114,32,117,115,105, + 110,103,32,116,104,101,32,102,105,108,101,32,115,121,115,116, + 101,109,46,99,2,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,3,0,0,0,67,0,0,0,115,22,0,0, + 0,116,0,124,1,131,1,125,2,124,2,106,1,124,2,106, + 2,100,1,156,2,83,0,41,2,122,33,82,101,116,117,114, + 110,32,116,104,101,32,109,101,116,97,100,97,116,97,32,102, + 111,114,32,116,104,101,32,112,97,116,104,46,41,2,114,193, + 0,0,0,114,6,1,0,0,41,3,114,75,0,0,0,218, + 8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,105, + 122,101,41,3,114,143,0,0,0,114,65,0,0,0,114,10, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,252,0,0,0,65,4,0,0,115,4,0,0,0, + 8,2,14,1,122,27,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, + 115,99,4,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,0,5,0,0,0,67,0,0,0,115,24,0,0,0,116, + 0,124,1,131,1,125,4,124,0,106,1,124,2,124,3,124, + 4,100,1,141,3,83,0,41,2,78,169,1,218,5,95,109, + 111,100,101,41,2,114,139,0,0,0,114,253,0,0,0,41, + 5,114,143,0,0,0,114,134,0,0,0,114,132,0,0,0, + 114,41,0,0,0,114,78,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,114,254,0,0,0,70,4, + 0,0,115,4,0,0,0,8,2,16,1,122,32,83,111,117, + 114,99,101,70,105,108,101,76,111,97,100,101,114,46,95,99, + 97,99,104,101,95,98,121,116,101,99,111,100,101,114,87,0, + 0,0,114,36,1,0,0,99,3,0,0,0,0,0,0,0, + 1,0,0,0,9,0,0,0,11,0,0,0,67,0,0,0, + 115,254,0,0,0,116,0,124,1,131,1,92,2,125,4,125, + 5,103,0,125,6,124,4,114,31,116,1,124,4,131,1,115, + 31,116,0,124,4,131,1,92,2,125,4,125,7,124,6,160, + 2,124,7,161,1,1,0,124,4,114,31,116,1,124,4,131, + 1,114,14,116,3,124,6,131,1,68,0,93,49,125,7,116, + 4,124,4,124,7,131,2,125,4,122,7,116,5,160,6,124, + 4,161,1,1,0,87,0,113,35,4,0,116,7,121,58,1, + 0,1,0,1,0,89,0,113,35,4,0,116,8,121,84,1, + 0,125,8,1,0,122,15,116,9,160,10,100,1,124,4,124, + 8,161,3,1,0,87,0,89,0,100,2,125,8,126,8,1, + 0,100,2,83,0,100,2,125,8,126,8,119,1,119,0,122, + 15,116,11,124,1,124,2,124,3,131,3,1,0,116,9,160, + 10,100,3,124,1,161,2,1,0,87,0,100,2,83,0,4, + 0,116,8,121,126,1,0,125,8,1,0,122,14,116,9,160, + 10,100,1,124,1,124,8,161,3,1,0,87,0,89,0,100, + 2,125,8,126,8,100,2,83,0,100,2,125,8,126,8,119, + 1,119,0,41,4,122,27,87,114,105,116,101,32,98,121,116, + 101,115,32,100,97,116,97,32,116,111,32,97,32,102,105,108, + 101,46,122,27,99,111,117,108,100,32,110,111,116,32,99,114, + 101,97,116,101,32,123,33,114,125,58,32,123,33,114,125,78, + 122,12,99,114,101,97,116,101,100,32,123,33,114,125,41,12, + 114,74,0,0,0,114,83,0,0,0,114,61,0,0,0,218, + 8,114,101,118,101,114,115,101,100,114,67,0,0,0,114,18, + 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, + 69,120,105,115,116,115,69,114,114,111,114,114,76,0,0,0, + 114,159,0,0,0,114,173,0,0,0,114,95,0,0,0,41, + 9,114,143,0,0,0,114,65,0,0,0,114,41,0,0,0, + 114,37,1,0,0,218,6,112,97,114,101,110,116,114,120,0, + 0,0,114,63,0,0,0,114,68,0,0,0,114,0,1,0, 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,1,1,0,0,126,4,0,0,114,24,0,0,0,122,31, - 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,78, - 41,6,114,150,0,0,0,114,149,0,0,0,114,151,0,0, - 0,114,152,0,0,0,114,241,0,0,0,114,1,1,0,0, - 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,41,1,0,0,106,4,0,0,115,8,0, - 0,0,8,0,4,2,8,2,12,16,114,41,1,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,64,0,0,0,115,92,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, - 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, - 6,100,8,100,9,132,0,90,7,100,10,100,11,132,0,90, - 8,100,12,100,13,132,0,90,9,100,14,100,15,132,0,90, - 10,100,16,100,17,132,0,90,11,101,12,100,18,100,19,132, - 0,131,1,90,13,100,20,83,0,41,21,114,30,1,0,0, - 122,93,76,111,97,100,101,114,32,102,111,114,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,115,46,10, - 10,32,32,32,32,84,104,101,32,99,111,110,115,116,114,117, - 99,116,111,114,32,105,115,32,100,101,115,105,103,110,101,100, - 32,116,111,32,119,111,114,107,32,119,105,116,104,32,70,105, - 108,101,70,105,110,100,101,114,46,10,10,32,32,32,32,99, - 3,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 2,0,0,0,67,0,0,0,115,16,0,0,0,124,1,124, - 0,95,0,124,2,124,0,95,1,100,0,83,0,114,69,0, - 0,0,114,183,0,0,0,41,3,114,143,0,0,0,114,141, - 0,0,0,114,65,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,236,0,0,0,139,4,0,0, - 115,4,0,0,0,6,1,10,1,122,28,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,95, - 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 114,12,1,0,0,114,69,0,0,0,114,13,1,0,0,114, - 15,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,16,1,0,0,143,4,0,0,114,17,1,0, - 0,122,26,69,120,116,101,110,115,105,111,110,70,105,108,101, - 76,111,97,100,101,114,46,95,95,101,113,95,95,99,1,0, - 0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,114,18,1,0,0,114,69,0,0,0, - 114,19,1,0,0,114,21,1,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,22,1,0,0,147,4, - 0,0,114,23,1,0,0,122,28,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,104, - 97,115,104,95,95,99,2,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,5,0,0,0,67,0,0,0,115,36, - 0,0,0,116,0,160,1,116,2,106,3,124,1,161,2,125, - 2,116,0,160,4,100,1,124,1,106,5,124,0,106,6,161, - 3,1,0,124,2,83,0,41,3,122,38,67,114,101,97,116, - 101,32,97,110,32,117,110,105,116,105,97,108,105,122,101,100, - 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,122,38,101,120,116,101,110,115,105,111,110,32,109,111,100, - 117,108,101,32,123,33,114,125,32,108,111,97,100,101,100,32, - 102,114,111,109,32,123,33,114,125,78,41,7,114,159,0,0, - 0,114,242,0,0,0,114,187,0,0,0,90,14,99,114,101, - 97,116,101,95,100,121,110,97,109,105,99,114,173,0,0,0, - 114,141,0,0,0,114,65,0,0,0,41,3,114,143,0,0, - 0,114,210,0,0,0,114,244,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,239,0,0,0,150, - 4,0,0,115,14,0,0,0,4,2,6,1,4,255,6,2, - 8,1,4,255,4,2,122,33,69,120,116,101,110,115,105,111, - 110,70,105,108,101,76,111,97,100,101,114,46,99,114,101,97, - 116,101,95,109,111,100,117,108,101,99,2,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,5,0,0,0,67,0, - 0,0,115,36,0,0,0,116,0,160,1,116,2,106,3,124, - 1,161,2,1,0,116,0,160,4,100,1,124,0,106,5,124, - 0,106,6,161,3,1,0,100,2,83,0,41,3,122,30,73, - 110,105,116,105,97,108,105,122,101,32,97,110,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,122,40,101, - 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, - 123,33,114,125,32,101,120,101,99,117,116,101,100,32,102,114, - 111,109,32,123,33,114,125,78,41,7,114,159,0,0,0,114, - 242,0,0,0,114,187,0,0,0,90,12,101,120,101,99,95, - 100,121,110,97,109,105,99,114,173,0,0,0,114,141,0,0, - 0,114,65,0,0,0,169,2,114,143,0,0,0,114,244,0, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,245,0,0,0,158,4,0,0,115,8,0,0,0,14, - 2,6,1,8,1,8,255,122,31,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,101,120,101, - 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,4,0,0,0,3,0,0, - 0,115,36,0,0,0,116,0,124,0,106,1,131,1,100,1, - 25,0,137,0,116,2,135,0,102,1,100,2,100,3,132,8, - 116,3,68,0,131,1,131,1,83,0,41,5,122,49,82,101, - 116,117,114,110,32,84,114,117,101,32,105,102,32,116,104,101, - 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,32,105,115,32,97,32,112,97,99,107,97,103,101,46,114, - 3,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,51,0,0,0,115,28,0, - 0,0,129,0,124,0,93,9,125,1,136,0,100,0,124,1, - 23,0,107,2,86,0,1,0,113,2,100,1,83,0,41,2, - 114,236,0,0,0,78,114,7,0,0,0,169,2,114,5,0, - 0,0,218,6,115,117,102,102,105,120,169,1,90,9,102,105, - 108,101,95,110,97,109,101,114,7,0,0,0,114,8,0,0, - 0,114,9,0,0,0,167,4,0,0,115,6,0,0,0,6, - 128,2,1,20,255,122,49,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,105,115,95,112,97, - 99,107,97,103,101,46,60,108,111,99,97,108,115,62,46,60, - 103,101,110,101,120,112,114,62,78,41,4,114,74,0,0,0, - 114,65,0,0,0,218,3,97,110,121,114,232,0,0,0,114, - 247,0,0,0,114,7,0,0,0,114,45,1,0,0,114,8, - 0,0,0,114,206,0,0,0,164,4,0,0,115,8,0,0, - 0,14,2,12,1,2,1,8,255,122,30,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,105, - 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,114,23,0,0,0,41,2,122,63,82,101,116,117,114, - 110,32,78,111,110,101,32,97,115,32,97,110,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,32,99,97, - 110,110,111,116,32,99,114,101,97,116,101,32,97,32,99,111, - 100,101,32,111,98,106,101,99,116,46,78,114,7,0,0,0, - 114,247,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,241,0,0,0,170,4,0,0,114,24,0, - 0,0,122,28,69,120,116,101,110,115,105,111,110,70,105,108, + 114,253,0,0,0,75,4,0,0,115,56,0,0,0,12,2, + 4,1,12,2,12,1,10,1,12,254,12,4,10,1,2,1, + 14,1,12,1,4,2,14,1,6,3,4,1,4,255,16,2, + 8,128,2,251,2,6,12,1,18,1,14,1,8,2,2,1, + 18,255,8,128,2,254,122,25,83,111,117,114,99,101,70,105, + 108,101,76,111,97,100,101,114,46,115,101,116,95,100,97,116, + 97,78,41,7,114,150,0,0,0,114,149,0,0,0,114,151, + 0,0,0,114,152,0,0,0,114,252,0,0,0,114,254,0, + 0,0,114,253,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,34,1,0,0, + 61,4,0,0,115,10,0,0,0,8,0,4,2,8,2,8, + 5,18,5,114,34,1,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, + 0,115,32,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, + 90,5,100,6,83,0,41,7,218,20,83,111,117,114,99,101, + 108,101,115,115,70,105,108,101,76,111,97,100,101,114,122,45, + 76,111,97,100,101,114,32,119,104,105,99,104,32,104,97,110, + 100,108,101,115,32,115,111,117,114,99,101,108,101,115,115,32, + 102,105,108,101,32,105,109,112,111,114,116,115,46,99,2,0, + 0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0, + 0,0,67,0,0,0,115,68,0,0,0,124,0,160,0,124, + 1,161,1,125,2,124,0,160,1,124,2,161,1,125,3,124, + 1,124,2,100,1,156,2,125,4,116,2,124,3,124,1,124, + 4,131,3,1,0,116,3,116,4,124,3,131,1,100,2,100, + 0,133,2,25,0,124,1,124,2,100,3,141,3,83,0,41, + 4,78,114,183,0,0,0,114,169,0,0,0,41,2,114,141, + 0,0,0,114,132,0,0,0,41,5,114,203,0,0,0,114, + 255,0,0,0,114,176,0,0,0,114,189,0,0,0,114,7, + 1,0,0,41,5,114,143,0,0,0,114,163,0,0,0,114, + 65,0,0,0,114,41,0,0,0,114,175,0,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,241,0, + 0,0,110,4,0,0,115,22,0,0,0,10,1,10,1,2, + 4,2,1,6,254,12,4,2,1,14,1,2,1,2,1,6, + 253,122,29,83,111,117,114,99,101,108,101,115,115,70,105,108, 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, 0,1,0,0,0,67,0,0,0,114,23,0,0,0,41,2, - 122,53,82,101,116,117,114,110,32,78,111,110,101,32,97,115, - 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,115,32,104,97,118,101,32,110,111,32,115,111,117,114,99, - 101,32,99,111,100,101,46,78,114,7,0,0,0,114,247,0, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,1,1,0,0,174,4,0,0,114,24,0,0,0,122, - 30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, - 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,114,26,1,0,0,114,27,1, - 0,0,114,71,0,0,0,114,247,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,203,0,0,0, - 178,4,0,0,114,28,1,0,0,122,32,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,102,105,108,101,110,97,109,101,78,41,14,114,150, - 0,0,0,114,149,0,0,0,114,151,0,0,0,114,152,0, - 0,0,114,236,0,0,0,114,16,1,0,0,114,22,1,0, - 0,114,239,0,0,0,114,245,0,0,0,114,206,0,0,0, - 114,241,0,0,0,114,1,1,0,0,114,160,0,0,0,114, - 203,0,0,0,114,7,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,30,1,0,0,131,4,0, - 0,115,24,0,0,0,8,0,4,2,8,6,8,4,8,4, - 8,3,8,8,8,6,8,6,8,4,2,4,14,1,114,30, - 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,64,0,0,0,115,104,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, - 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, - 7,132,0,90,6,100,8,100,9,132,0,90,7,100,10,100, - 11,132,0,90,8,100,12,100,13,132,0,90,9,100,14,100, - 15,132,0,90,10,100,16,100,17,132,0,90,11,100,18,100, - 19,132,0,90,12,100,20,100,21,132,0,90,13,100,22,100, - 23,132,0,90,14,100,24,83,0,41,25,218,14,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,97,38,1,0,0, - 82,101,112,114,101,115,101,110,116,115,32,97,32,110,97,109, - 101,115,112,97,99,101,32,112,97,99,107,97,103,101,39,115, - 32,112,97,116,104,46,32,32,73,116,32,117,115,101,115,32, - 116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,10, - 32,32,32,32,116,111,32,102,105,110,100,32,105,116,115,32, - 112,97,114,101,110,116,32,109,111,100,117,108,101,44,32,97, - 110,100,32,102,114,111,109,32,116,104,101,114,101,32,105,116, - 32,108,111,111,107,115,32,117,112,32,116,104,101,32,112,97, - 114,101,110,116,39,115,10,32,32,32,32,95,95,112,97,116, - 104,95,95,46,32,32,87,104,101,110,32,116,104,105,115,32, - 99,104,97,110,103,101,115,44,32,116,104,101,32,109,111,100, - 117,108,101,39,115,32,111,119,110,32,112,97,116,104,32,105, - 115,32,114,101,99,111,109,112,117,116,101,100,44,10,32,32, - 32,32,117,115,105,110,103,32,112,97,116,104,95,102,105,110, - 100,101,114,46,32,32,70,111,114,32,116,111,112,45,108,101, - 118,101,108,32,109,111,100,117,108,101,115,44,32,116,104,101, - 32,112,97,114,101,110,116,32,109,111,100,117,108,101,39,115, - 32,112,97,116,104,10,32,32,32,32,105,115,32,115,121,115, - 46,112,97,116,104,46,99,4,0,0,0,0,0,0,0,0, - 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, - 36,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, - 116,2,124,0,160,3,161,0,131,1,124,0,95,4,124,3, - 124,0,95,5,100,0,83,0,114,69,0,0,0,41,6,218, - 5,95,110,97,109,101,218,5,95,112,97,116,104,114,136,0, - 0,0,218,16,95,103,101,116,95,112,97,114,101,110,116,95, - 112,97,116,104,218,17,95,108,97,115,116,95,112,97,114,101, - 110,116,95,112,97,116,104,218,12,95,112,97,116,104,95,102, - 105,110,100,101,114,169,4,114,143,0,0,0,114,141,0,0, - 0,114,65,0,0,0,90,11,112,97,116,104,95,102,105,110, - 100,101,114,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,236,0,0,0,191,4,0,0,115,8,0,0,0, - 6,1,6,1,14,1,10,1,122,23,95,78,97,109,101,115, - 112,97,99,101,80,97,116,104,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,0,0,0,0,4,0, - 0,0,3,0,0,0,67,0,0,0,115,38,0,0,0,124, - 0,106,0,160,1,100,1,161,1,92,3,125,1,125,2,125, - 3,124,2,100,2,107,2,114,15,100,3,83,0,124,1,100, - 4,102,2,83,0,41,6,122,62,82,101,116,117,114,110,115, - 32,97,32,116,117,112,108,101,32,111,102,32,40,112,97,114, - 101,110,116,45,109,111,100,117,108,101,45,110,97,109,101,44, - 32,112,97,114,101,110,116,45,112,97,116,104,45,97,116,116, - 114,45,110,97,109,101,41,114,97,0,0,0,114,10,0,0, - 0,41,2,114,15,0,0,0,114,65,0,0,0,90,8,95, - 95,112,97,116,104,95,95,78,41,2,114,48,1,0,0,114, - 104,0,0,0,41,4,114,143,0,0,0,114,40,1,0,0, - 218,3,100,111,116,90,2,109,101,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,23,95,102,105,110,100,95, - 112,97,114,101,110,116,95,112,97,116,104,95,110,97,109,101, - 115,197,4,0,0,115,8,0,0,0,18,2,8,1,4,2, - 8,3,122,38,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,102,105,110,100,95,112,97,114,101,110,116,95, - 112,97,116,104,95,110,97,109,101,115,99,1,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,67, - 0,0,0,115,28,0,0,0,124,0,160,0,161,0,92,2, - 125,1,125,2,116,1,116,2,106,3,124,1,25,0,124,2, - 131,2,83,0,114,69,0,0,0,41,4,114,55,1,0,0, - 114,155,0,0,0,114,15,0,0,0,218,7,109,111,100,117, - 108,101,115,41,3,114,143,0,0,0,90,18,112,97,114,101, - 110,116,95,109,111,100,117,108,101,95,110,97,109,101,90,14, - 112,97,116,104,95,97,116,116,114,95,110,97,109,101,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,114,50,1, - 0,0,207,4,0,0,115,4,0,0,0,12,1,16,1,122, - 31,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, - 95,103,101,116,95,112,97,114,101,110,116,95,112,97,116,104, - 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, - 0,4,0,0,0,67,0,0,0,115,80,0,0,0,116,0, - 124,0,160,1,161,0,131,1,125,1,124,1,124,0,106,2, - 107,3,114,37,124,0,160,3,124,0,106,4,124,1,161,2, - 125,2,124,2,100,0,117,1,114,34,124,2,106,5,100,0, - 117,0,114,34,124,2,106,6,114,34,124,2,106,6,124,0, - 95,7,124,1,124,0,95,2,124,0,106,7,83,0,114,69, - 0,0,0,41,8,114,136,0,0,0,114,50,1,0,0,114, - 51,1,0,0,114,52,1,0,0,114,48,1,0,0,114,164, - 0,0,0,114,202,0,0,0,114,49,1,0,0,41,3,114, - 143,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116, - 104,114,210,0,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,12,95,114,101,99,97,108,99,117,108, - 97,116,101,211,4,0,0,115,16,0,0,0,12,2,10,1, - 14,1,18,3,6,1,8,1,6,1,6,1,122,27,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,46,95,114,101, - 99,97,108,99,117,108,97,116,101,99,1,0,0,0,0,0, - 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, - 0,0,243,12,0,0,0,116,0,124,0,160,1,161,0,131, - 1,83,0,114,69,0,0,0,41,2,218,4,105,116,101,114, - 114,57,1,0,0,114,21,1,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,218,8,95,95,105,116,101, - 114,95,95,224,4,0,0,243,2,0,0,0,12,1,122,23, - 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, - 95,105,116,101,114,95,95,99,2,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,12,0,0,0,124,0,160,0,161,0,124,1,25,0,83, - 0,114,69,0,0,0,169,1,114,57,1,0,0,41,2,114, - 143,0,0,0,218,5,105,110,100,101,120,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,218,11,95,95,103,101, - 116,105,116,101,109,95,95,227,4,0,0,114,61,1,0,0, - 122,26,95,78,97,109,101,115,112,97,99,101,80,97,116,104, - 46,95,95,103,101,116,105,116,101,109,95,95,99,3,0,0, + 122,39,82,101,116,117,114,110,32,78,111,110,101,32,97,115, + 32,116,104,101,114,101,32,105,115,32,110,111,32,115,111,117, + 114,99,101,32,99,111,100,101,46,78,114,7,0,0,0,114, + 247,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,1,1,0,0,126,4,0,0,114,24,0,0, + 0,122,31,83,111,117,114,99,101,108,101,115,115,70,105,108, + 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, + 99,101,78,41,6,114,150,0,0,0,114,149,0,0,0,114, + 151,0,0,0,114,152,0,0,0,114,241,0,0,0,114,1, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,41,1,0,0,106,4,0,0, + 115,8,0,0,0,8,0,4,2,8,2,12,16,114,41,1, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,64,0,0,0,115,92,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, + 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, + 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, + 132,0,90,8,100,12,100,13,132,0,90,9,100,14,100,15, + 132,0,90,10,100,16,100,17,132,0,90,11,101,12,100,18, + 100,19,132,0,131,1,90,13,100,20,83,0,41,21,114,30, + 1,0,0,122,93,76,111,97,100,101,114,32,102,111,114,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 115,46,10,10,32,32,32,32,84,104,101,32,99,111,110,115, + 116,114,117,99,116,111,114,32,105,115,32,100,101,115,105,103, + 110,101,100,32,116,111,32,119,111,114,107,32,119,105,116,104, + 32,70,105,108,101,70,105,110,100,101,114,46,10,10,32,32, + 32,32,99,3,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, + 124,1,124,0,95,0,124,2,124,0,95,1,100,0,83,0, + 114,69,0,0,0,114,183,0,0,0,41,3,114,143,0,0, + 0,114,141,0,0,0,114,65,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,236,0,0,0,139, + 4,0,0,115,4,0,0,0,6,1,10,1,122,28,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, + 0,0,0,114,12,1,0,0,114,69,0,0,0,114,13,1, + 0,0,114,15,1,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,16,1,0,0,143,4,0,0,114, + 17,1,0,0,122,26,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, + 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,114,18,1,0,0,114,69, + 0,0,0,114,19,1,0,0,114,21,1,0,0,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,22,1,0, + 0,147,4,0,0,114,23,1,0,0,122,28,69,120,116,101, + 110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,46, + 95,95,104,97,115,104,95,95,99,2,0,0,0,0,0,0, + 0,0,0,0,0,3,0,0,0,5,0,0,0,67,0,0, + 0,115,36,0,0,0,116,0,160,1,116,2,106,3,124,1, + 161,2,125,2,116,0,160,4,100,1,124,1,106,5,124,0, + 106,6,161,3,1,0,124,2,83,0,41,2,122,38,67,114, + 101,97,116,101,32,97,110,32,117,110,105,116,105,97,108,105, + 122,101,100,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,122,38,101,120,116,101,110,115,105,111,110,32, + 109,111,100,117,108,101,32,123,33,114,125,32,108,111,97,100, + 101,100,32,102,114,111,109,32,123,33,114,125,41,7,114,159, + 0,0,0,114,242,0,0,0,114,187,0,0,0,90,14,99, + 114,101,97,116,101,95,100,121,110,97,109,105,99,114,173,0, + 0,0,114,141,0,0,0,114,65,0,0,0,41,3,114,143, + 0,0,0,114,210,0,0,0,114,244,0,0,0,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,239,0,0, + 0,150,4,0,0,115,14,0,0,0,4,2,6,1,4,255, + 6,2,8,1,4,255,4,2,122,33,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,99,114, + 101,97,116,101,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0, + 67,0,0,0,115,36,0,0,0,116,0,160,1,116,2,106, + 3,124,1,161,2,1,0,116,0,160,4,100,1,124,0,106, + 5,124,0,106,6,161,3,1,0,100,2,83,0,41,3,122, + 30,73,110,105,116,105,97,108,105,122,101,32,97,110,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,122, + 40,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,32,123,33,114,125,32,101,120,101,99,117,116,101,100,32, + 102,114,111,109,32,123,33,114,125,78,41,7,114,159,0,0, + 0,114,242,0,0,0,114,187,0,0,0,90,12,101,120,101, + 99,95,100,121,110,97,109,105,99,114,173,0,0,0,114,141, + 0,0,0,114,65,0,0,0,169,2,114,143,0,0,0,114, + 244,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,245,0,0,0,158,4,0,0,115,8,0,0, + 0,14,2,6,1,8,1,8,255,122,31,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,101, + 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,3, + 0,0,0,115,36,0,0,0,116,0,124,0,106,1,131,1, + 100,1,25,0,137,0,116,2,135,0,102,1,100,2,100,3, + 132,8,116,3,68,0,131,1,131,1,83,0,41,4,122,49, + 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, + 104,101,32,101,120,116,101,110,115,105,111,110,32,109,111,100, + 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, + 46,114,3,0,0,0,99,1,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,51,0,0,0,115, + 28,0,0,0,129,0,124,0,93,9,125,1,136,0,100,0, + 124,1,23,0,107,2,86,0,1,0,113,2,100,1,83,0, + 41,2,114,236,0,0,0,78,114,7,0,0,0,169,2,114, + 5,0,0,0,218,6,115,117,102,102,105,120,169,1,90,9, + 102,105,108,101,95,110,97,109,101,114,7,0,0,0,114,8, + 0,0,0,114,9,0,0,0,167,4,0,0,115,8,0,0, + 0,2,128,4,0,2,1,20,255,122,49,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,105, + 115,95,112,97,99,107,97,103,101,46,60,108,111,99,97,108, + 115,62,46,60,103,101,110,101,120,112,114,62,41,4,114,74, + 0,0,0,114,65,0,0,0,218,3,97,110,121,114,232,0, + 0,0,114,247,0,0,0,114,7,0,0,0,114,45,1,0, + 0,114,8,0,0,0,114,206,0,0,0,164,4,0,0,115, + 8,0,0,0,14,2,12,1,2,1,8,255,122,30,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,114,23,0,0,0,41,2,122,63,82,101, + 116,117,114,110,32,78,111,110,101,32,97,115,32,97,110,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 32,99,97,110,110,111,116,32,99,114,101,97,116,101,32,97, + 32,99,111,100,101,32,111,98,106,101,99,116,46,78,114,7, + 0,0,0,114,247,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,241,0,0,0,170,4,0,0, + 114,24,0,0,0,122,28,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, + 111,100,101,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,114,23,0,0, + 0,41,2,122,53,82,101,116,117,114,110,32,78,111,110,101, + 32,97,115,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,115,32,104,97,118,101,32,110,111,32,115,111, + 117,114,99,101,32,99,111,100,101,46,78,114,7,0,0,0, + 114,247,0,0,0,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,114,1,1,0,0,174,4,0,0,114,24,0, + 0,0,122,30,69,120,116,101,110,115,105,111,110,70,105,108, + 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, + 99,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,67,0,0,0,114,26,1,0,0, + 114,27,1,0,0,114,71,0,0,0,114,247,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,203, + 0,0,0,178,4,0,0,114,28,1,0,0,122,32,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,103,101,116,95,102,105,108,101,110,97,109,101,78,41, + 14,114,150,0,0,0,114,149,0,0,0,114,151,0,0,0, + 114,152,0,0,0,114,236,0,0,0,114,16,1,0,0,114, + 22,1,0,0,114,239,0,0,0,114,245,0,0,0,114,206, + 0,0,0,114,241,0,0,0,114,1,1,0,0,114,160,0, + 0,0,114,203,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,30,1,0,0, + 131,4,0,0,115,24,0,0,0,8,0,4,2,8,6,8, + 4,8,4,8,3,8,8,8,6,8,6,8,4,2,4,14, + 1,114,30,1,0,0,99,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, + 104,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, + 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, + 100,6,100,7,132,0,90,6,100,8,100,9,132,0,90,7, + 100,10,100,11,132,0,90,8,100,12,100,13,132,0,90,9, + 100,14,100,15,132,0,90,10,100,16,100,17,132,0,90,11, + 100,18,100,19,132,0,90,12,100,20,100,21,132,0,90,13, + 100,22,100,23,132,0,90,14,100,24,83,0,41,25,218,14, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,97,38, + 1,0,0,82,101,112,114,101,115,101,110,116,115,32,97,32, + 110,97,109,101,115,112,97,99,101,32,112,97,99,107,97,103, + 101,39,115,32,112,97,116,104,46,32,32,73,116,32,117,115, + 101,115,32,116,104,101,32,109,111,100,117,108,101,32,110,97, + 109,101,10,32,32,32,32,116,111,32,102,105,110,100,32,105, + 116,115,32,112,97,114,101,110,116,32,109,111,100,117,108,101, + 44,32,97,110,100,32,102,114,111,109,32,116,104,101,114,101, + 32,105,116,32,108,111,111,107,115,32,117,112,32,116,104,101, + 32,112,97,114,101,110,116,39,115,10,32,32,32,32,95,95, + 112,97,116,104,95,95,46,32,32,87,104,101,110,32,116,104, + 105,115,32,99,104,97,110,103,101,115,44,32,116,104,101,32, + 109,111,100,117,108,101,39,115,32,111,119,110,32,112,97,116, + 104,32,105,115,32,114,101,99,111,109,112,117,116,101,100,44, + 10,32,32,32,32,117,115,105,110,103,32,112,97,116,104,95, + 102,105,110,100,101,114,46,32,32,70,111,114,32,116,111,112, + 45,108,101,118,101,108,32,109,111,100,117,108,101,115,44,32, + 116,104,101,32,112,97,114,101,110,116,32,109,111,100,117,108, + 101,39,115,32,112,97,116,104,10,32,32,32,32,105,115,32, + 115,121,115,46,112,97,116,104,46,99,4,0,0,0,0,0, + 0,0,0,0,0,0,4,0,0,0,3,0,0,0,67,0, + 0,0,115,36,0,0,0,124,1,124,0,95,0,124,2,124, + 0,95,1,116,2,124,0,160,3,161,0,131,1,124,0,95, + 4,124,3,124,0,95,5,100,0,83,0,114,69,0,0,0, + 41,6,218,5,95,110,97,109,101,218,5,95,112,97,116,104, + 114,136,0,0,0,218,16,95,103,101,116,95,112,97,114,101, + 110,116,95,112,97,116,104,218,17,95,108,97,115,116,95,112, + 97,114,101,110,116,95,112,97,116,104,218,12,95,112,97,116, + 104,95,102,105,110,100,101,114,169,4,114,143,0,0,0,114, + 141,0,0,0,114,65,0,0,0,90,11,112,97,116,104,95, + 102,105,110,100,101,114,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,236,0,0,0,191,4,0,0,115,8, + 0,0,0,6,1,6,1,14,1,10,1,122,23,95,78,97, + 109,101,115,112,97,99,101,80,97,116,104,46,95,95,105,110, + 105,116,95,95,99,1,0,0,0,0,0,0,0,0,0,0, + 0,4,0,0,0,3,0,0,0,67,0,0,0,115,38,0, + 0,0,124,0,106,0,160,1,100,1,161,1,92,3,125,1, + 125,2,125,3,124,2,100,2,107,2,114,15,100,3,83,0, + 124,1,100,4,102,2,83,0,41,5,122,62,82,101,116,117, + 114,110,115,32,97,32,116,117,112,108,101,32,111,102,32,40, + 112,97,114,101,110,116,45,109,111,100,117,108,101,45,110,97, + 109,101,44,32,112,97,114,101,110,116,45,112,97,116,104,45, + 97,116,116,114,45,110,97,109,101,41,114,97,0,0,0,114, + 10,0,0,0,41,2,114,15,0,0,0,114,65,0,0,0, + 90,8,95,95,112,97,116,104,95,95,41,2,114,48,1,0, + 0,114,104,0,0,0,41,4,114,143,0,0,0,114,40,1, + 0,0,218,3,100,111,116,90,2,109,101,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,23,95,102,105,110, + 100,95,112,97,114,101,110,116,95,112,97,116,104,95,110,97, + 109,101,115,197,4,0,0,115,8,0,0,0,18,2,8,1, + 4,2,8,3,122,38,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,46,95,102,105,110,100,95,112,97,114,101,110, + 116,95,112,97,116,104,95,110,97,109,101,115,99,1,0,0, 0,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,67,0,0,0,115,14,0,0,0,124,2,124,0,106,0, - 124,1,60,0,100,0,83,0,114,69,0,0,0,41,1,114, - 49,1,0,0,41,3,114,143,0,0,0,114,63,1,0,0, - 114,65,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,11,95,95,115,101,116,105,116,101,109,95, - 95,230,4,0,0,115,2,0,0,0,14,1,122,26,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,115, - 101,116,105,116,101,109,95,95,99,1,0,0,0,0,0,0, - 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, - 0,114,58,1,0,0,114,69,0,0,0,41,2,114,4,0, - 0,0,114,57,1,0,0,114,21,1,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,218,7,95,95,108, - 101,110,95,95,233,4,0,0,114,61,1,0,0,122,22,95, + 0,67,0,0,0,115,28,0,0,0,124,0,160,0,161,0, + 92,2,125,1,125,2,116,1,116,2,106,3,124,1,25,0, + 124,2,131,2,83,0,114,69,0,0,0,41,4,114,55,1, + 0,0,114,155,0,0,0,114,15,0,0,0,218,7,109,111, + 100,117,108,101,115,41,3,114,143,0,0,0,90,18,112,97, + 114,101,110,116,95,109,111,100,117,108,101,95,110,97,109,101, + 90,14,112,97,116,104,95,97,116,116,114,95,110,97,109,101, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, + 50,1,0,0,207,4,0,0,115,4,0,0,0,12,1,16, + 1,122,31,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,103,101,116,95,112,97,114,101,110,116,95,112,97, + 116,104,99,1,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,4,0,0,0,67,0,0,0,115,80,0,0,0, + 116,0,124,0,160,1,161,0,131,1,125,1,124,1,124,0, + 106,2,107,3,114,37,124,0,160,3,124,0,106,4,124,1, + 161,2,125,2,124,2,100,0,117,1,114,34,124,2,106,5, + 100,0,117,0,114,34,124,2,106,6,114,34,124,2,106,6, + 124,0,95,7,124,1,124,0,95,2,124,0,106,7,83,0, + 114,69,0,0,0,41,8,114,136,0,0,0,114,50,1,0, + 0,114,51,1,0,0,114,52,1,0,0,114,48,1,0,0, + 114,164,0,0,0,114,202,0,0,0,114,49,1,0,0,41, + 3,114,143,0,0,0,90,11,112,97,114,101,110,116,95,112, + 97,116,104,114,210,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,218,12,95,114,101,99,97,108,99, + 117,108,97,116,101,211,4,0,0,115,16,0,0,0,12,2, + 10,1,14,1,18,3,6,1,8,1,6,1,6,1,122,27, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, + 114,101,99,97,108,99,117,108,97,116,101,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,243,12,0,0,0,116,0,124,0,160,1,161, + 0,131,1,83,0,114,69,0,0,0,41,2,218,4,105,116, + 101,114,114,57,1,0,0,114,21,1,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,8,95,95,105, + 116,101,114,95,95,224,4,0,0,243,2,0,0,0,12,1, + 122,23,95,78,97,109,101,115,112,97,99,101,80,97,116,104, + 46,95,95,105,116,101,114,95,95,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0, + 0,0,115,12,0,0,0,124,0,160,0,161,0,124,1,25, + 0,83,0,114,69,0,0,0,169,1,114,57,1,0,0,41, + 2,114,143,0,0,0,218,5,105,110,100,101,120,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,218,11,95,95, + 103,101,116,105,116,101,109,95,95,227,4,0,0,114,61,1, + 0,0,122,26,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,95,103,101,116,105,116,101,109,95,95,99,3, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,14,0,0,0,124,2,124,0, + 106,0,124,1,60,0,100,0,83,0,114,69,0,0,0,41, + 1,114,49,1,0,0,41,3,114,143,0,0,0,114,63,1, + 0,0,114,65,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,218,11,95,95,115,101,116,105,116,101, + 109,95,95,230,4,0,0,115,2,0,0,0,14,1,122,26, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95, + 95,115,101,116,105,116,101,109,95,95,99,1,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,114,58,1,0,0,114,69,0,0,0,41,2,114, + 4,0,0,0,114,57,1,0,0,114,21,1,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,7,95, + 95,108,101,110,95,95,233,4,0,0,114,61,1,0,0,122, + 22,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, + 95,95,108,101,110,95,95,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 243,12,0,0,0,100,1,160,0,124,0,106,1,161,1,83, + 0,41,2,78,122,20,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,40,123,33,114,125,41,41,2,114,89,0,0, + 0,114,49,1,0,0,114,21,1,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,8,95,95,114,101, + 112,114,95,95,236,4,0,0,114,61,1,0,0,122,23,95, 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,95, - 108,101,110,95,95,99,1,0,0,0,0,0,0,0,0,0, - 0,0,1,0,0,0,3,0,0,0,67,0,0,0,243,12, - 0,0,0,100,1,160,0,124,0,106,1,161,1,83,0,41, - 2,78,122,20,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,40,123,33,114,125,41,41,2,114,89,0,0,0,114, - 49,1,0,0,114,21,1,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,8,95,95,114,101,112,114, - 95,95,236,4,0,0,114,61,1,0,0,122,23,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,95,114,101, - 112,114,95,95,99,2,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,67,0,0,0,115,12,0, - 0,0,124,1,124,0,160,0,161,0,118,0,83,0,114,69, - 0,0,0,114,62,1,0,0,169,2,114,143,0,0,0,218, - 4,105,116,101,109,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,12,95,95,99,111,110,116,97,105,110,115, - 95,95,239,4,0,0,114,61,1,0,0,122,27,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,95,99,111, - 110,116,97,105,110,115,95,95,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,16,0,0,0,124,0,106,0,160,1,124,1,161,1, - 1,0,100,0,83,0,114,69,0,0,0,41,2,114,49,1, - 0,0,114,61,0,0,0,114,69,1,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,61,0,0,0, - 242,4,0,0,243,2,0,0,0,16,1,122,21,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,97,112,112,101, - 110,100,78,41,15,114,150,0,0,0,114,149,0,0,0,114, - 151,0,0,0,114,152,0,0,0,114,236,0,0,0,114,55, - 1,0,0,114,50,1,0,0,114,57,1,0,0,114,60,1, - 0,0,114,64,1,0,0,114,65,1,0,0,114,66,1,0, - 0,114,68,1,0,0,114,71,1,0,0,114,61,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,47,1,0,0,184,4,0,0,115,26,0, - 0,0,8,0,4,1,8,6,8,6,8,10,8,4,8,13, - 8,3,8,3,8,3,8,3,8,3,12,3,114,47,1,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,64,0,0,0,115,88,0,0,0,101, - 0,90,1,100,0,90,2,100,1,100,2,132,0,90,3,101, - 4,100,3,100,4,132,0,131,1,90,5,100,5,100,6,132, - 0,90,6,100,7,100,8,132,0,90,7,100,9,100,10,132, - 0,90,8,100,11,100,12,132,0,90,9,100,13,100,14,132, - 0,90,10,100,15,100,16,132,0,90,11,100,17,100,18,132, - 0,90,12,100,19,83,0,41,20,218,16,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,99,4,0,0,0, - 0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,18,0,0,0,116,0,124,1,124,2,124, - 3,131,3,124,0,95,1,100,0,83,0,114,69,0,0,0, - 41,2,114,47,1,0,0,114,49,1,0,0,114,53,1,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,236,0,0,0,248,4,0,0,115,2,0,0,0,18,1, - 122,25,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,95,95,105,110,105,116,95,95,99,1,0,0,0, - 0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0, - 67,0,0,0,115,24,0,0,0,116,0,160,1,100,1,116, - 2,161,2,1,0,100,2,160,3,124,0,106,4,161,1,83, - 0,41,4,122,115,82,101,116,117,114,110,32,114,101,112,114, - 32,102,111,114,32,116,104,101,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,84,104,101,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,84,104,101,32,105,109,112,111,114,116,32, - 109,97,99,104,105,110,101,114,121,32,100,111,101,115,32,116, - 104,101,32,106,111,98,32,105,116,115,101,108,102,46,10,10, - 32,32,32,32,32,32,32,32,122,82,95,78,97,109,101,115, + 114,101,112,114,95,95,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, + 12,0,0,0,124,1,124,0,160,0,161,0,118,0,83,0, + 114,69,0,0,0,114,62,1,0,0,169,2,114,143,0,0, + 0,218,4,105,116,101,109,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,218,12,95,95,99,111,110,116,97,105, + 110,115,95,95,239,4,0,0,114,61,1,0,0,122,27,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,95, + 99,111,110,116,97,105,110,115,95,95,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,16,0,0,0,124,0,106,0,160,1,124,1, + 161,1,1,0,100,0,83,0,114,69,0,0,0,41,2,114, + 49,1,0,0,114,61,0,0,0,114,69,1,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,61,0, + 0,0,242,4,0,0,243,2,0,0,0,16,1,122,21,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,46,97,112, + 112,101,110,100,78,41,15,114,150,0,0,0,114,149,0,0, + 0,114,151,0,0,0,114,152,0,0,0,114,236,0,0,0, + 114,55,1,0,0,114,50,1,0,0,114,57,1,0,0,114, + 60,1,0,0,114,64,1,0,0,114,65,1,0,0,114,66, + 1,0,0,114,68,1,0,0,114,71,1,0,0,114,61,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,47,1,0,0,184,4,0,0,115, + 26,0,0,0,8,0,4,1,8,6,8,6,8,10,8,4, + 8,13,8,3,8,3,8,3,8,3,8,3,12,3,114,47, + 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,64,0,0,0,115,88,0,0, + 0,101,0,90,1,100,0,90,2,100,1,100,2,132,0,90, + 3,101,4,100,3,100,4,132,0,131,1,90,5,100,5,100, + 6,132,0,90,6,100,7,100,8,132,0,90,7,100,9,100, + 10,132,0,90,8,100,11,100,12,132,0,90,9,100,13,100, + 14,132,0,90,10,100,15,100,16,132,0,90,11,100,17,100, + 18,132,0,90,12,100,19,83,0,41,20,218,16,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,99,4,0, + 0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0, + 0,0,67,0,0,0,115,18,0,0,0,116,0,124,1,124, + 2,124,3,131,3,124,0,95,1,100,0,83,0,114,69,0, + 0,0,41,2,114,47,1,0,0,114,49,1,0,0,114,53, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,236,0,0,0,248,4,0,0,115,2,0,0,0, + 18,1,122,25,95,78,97,109,101,115,112,97,99,101,76,111, + 97,100,101,114,46,95,95,105,110,105,116,95,95,99,1,0, + 0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0, + 0,0,67,0,0,0,115,24,0,0,0,116,0,160,1,100, + 1,116,2,161,2,1,0,100,2,160,3,124,0,106,4,161, + 1,83,0,41,3,122,115,82,101,116,117,114,110,32,114,101, + 112,114,32,102,111,114,32,116,104,101,32,109,111,100,117,108, + 101,46,10,10,32,32,32,32,32,32,32,32,84,104,101,32, + 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, + 97,116,101,100,46,32,32,84,104,101,32,105,109,112,111,114, + 116,32,109,97,99,104,105,110,101,114,121,32,100,111,101,115, + 32,116,104,101,32,106,111,98,32,105,116,115,101,108,102,46, + 10,10,32,32,32,32,32,32,32,32,122,82,95,78,97,109, + 101,115,112,97,99,101,76,111,97,100,101,114,46,109,111,100, + 117,108,101,95,114,101,112,114,40,41,32,105,115,32,100,101, + 112,114,101,99,97,116,101,100,32,97,110,100,32,115,108,97, + 116,101,100,32,102,111,114,32,114,101,109,111,118,97,108,32, + 105,110,32,80,121,116,104,111,110,32,51,46,49,50,122,25, + 60,109,111,100,117,108,101,32,123,33,114,125,32,40,110,97, + 109,101,115,112,97,99,101,41,62,41,5,114,99,0,0,0, + 114,100,0,0,0,114,101,0,0,0,114,89,0,0,0,114, + 150,0,0,0,41,1,114,244,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,11,109,111,100,117, + 108,101,95,114,101,112,114,251,4,0,0,115,8,0,0,0, + 6,7,2,1,4,255,12,2,122,28,95,78,97,109,101,115, 112,97,99,101,76,111,97,100,101,114,46,109,111,100,117,108, - 101,95,114,101,112,114,40,41,32,105,115,32,100,101,112,114, - 101,99,97,116,101,100,32,97,110,100,32,115,108,97,116,101, - 100,32,102,111,114,32,114,101,109,111,118,97,108,32,105,110, - 32,80,121,116,104,111,110,32,51,46,49,50,122,25,60,109, - 111,100,117,108,101,32,123,33,114,125,32,40,110,97,109,101, - 115,112,97,99,101,41,62,78,41,5,114,99,0,0,0,114, - 100,0,0,0,114,101,0,0,0,114,89,0,0,0,114,150, - 0,0,0,41,1,114,244,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,218,11,109,111,100,117,108, - 101,95,114,101,112,114,251,4,0,0,115,8,0,0,0,6, - 7,2,1,4,255,12,2,122,28,95,78,97,109,101,115,112, - 97,99,101,76,111,97,100,101,114,46,109,111,100,117,108,101, - 95,114,101,112,114,99,2,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,114,23, - 0,0,0,41,2,78,84,114,7,0,0,0,114,247,0,0, + 101,95,114,101,112,114,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,114, + 23,0,0,0,41,2,78,84,114,7,0,0,0,114,247,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,114,206,0,0,0,6,5,0,0,243,2,0,0,0,4, + 1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,105,115,95,112,97,99,107,97,103,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,114,23,0,0,0,41,2,78,114, + 10,0,0,0,114,7,0,0,0,114,247,0,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,1,1, + 0,0,9,5,0,0,114,75,1,0,0,122,27,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,46,103,101, + 116,95,115,111,117,114,99,101,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,6,0,0,0,67,0,0, + 0,115,16,0,0,0,116,0,100,1,100,2,100,3,100,4, + 100,5,141,4,83,0,41,6,78,114,10,0,0,0,122,8, + 60,115,116,114,105,110,103,62,114,243,0,0,0,84,41,1, + 114,3,1,0,0,41,1,114,4,1,0,0,114,247,0,0, 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,206,0,0,0,6,5,0,0,243,2,0,0,0,4,1, - 122,27,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,114,23,0,0,0,41,2,78,114,10, - 0,0,0,114,7,0,0,0,114,247,0,0,0,114,7,0, - 0,0,114,7,0,0,0,114,8,0,0,0,114,1,1,0, - 0,9,5,0,0,114,75,1,0,0,122,27,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,46,103,101,116, - 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,6,0,0,0,67,0,0,0, - 115,16,0,0,0,116,0,100,1,100,2,100,3,100,4,100, - 5,141,4,83,0,41,6,78,114,10,0,0,0,122,8,60, - 115,116,114,105,110,103,62,114,243,0,0,0,84,41,1,114, - 3,1,0,0,41,1,114,4,1,0,0,114,247,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 241,0,0,0,12,5,0,0,114,72,1,0,0,122,25,95, - 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, - 103,101,116,95,99,111,100,101,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,114,23,0,0,0,114,237,0,0,0,114,7,0,0,0, - 114,238,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,239,0,0,0,15,5,0,0,114,240,0, - 0,0,122,30,95,78,97,109,101,115,112,97,99,101,76,111, - 97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, - 100,0,83,0,114,69,0,0,0,114,7,0,0,0,114,42, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,245,0,0,0,18,5,0,0,114,75,1,0,0, - 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,4, - 0,0,0,67,0,0,0,115,26,0,0,0,116,0,160,1, - 100,1,124,0,106,2,161,2,1,0,116,0,160,3,124,0, - 124,1,161,2,83,0,41,3,122,98,76,111,97,100,32,97, - 32,110,97,109,101,115,112,97,99,101,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,122,38,110,97, - 109,101,115,112,97,99,101,32,109,111,100,117,108,101,32,108, - 111,97,100,101,100,32,119,105,116,104,32,112,97,116,104,32, - 123,33,114,125,78,41,4,114,159,0,0,0,114,173,0,0, + 114,241,0,0,0,12,5,0,0,114,72,1,0,0,122,25, + 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, + 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,114,23,0,0,0,114,237,0,0,0,114,7,0,0, + 0,114,238,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,239,0,0,0,15,5,0,0,114,240, + 0,0,0,122,30,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,46,99,114,101,97,116,101,95,109,111,100, + 117,108,101,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,0,83,0,114,69,0,0,0,114,7,0,0,0,114, + 42,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,245,0,0,0,18,5,0,0,114,75,1,0, + 0,122,28,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,99, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 4,0,0,0,67,0,0,0,115,26,0,0,0,116,0,160, + 1,100,1,124,0,106,2,161,2,1,0,116,0,160,3,124, + 0,124,1,161,2,83,0,41,2,122,98,76,111,97,100,32, + 97,32,110,97,109,101,115,112,97,99,101,32,109,111,100,117, + 108,101,46,10,10,32,32,32,32,32,32,32,32,84,104,105, + 115,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,32,85,115,101,32,101,120,101, + 99,95,109,111,100,117,108,101,40,41,32,105,110,115,116,101, + 97,100,46,10,10,32,32,32,32,32,32,32,32,122,38,110, + 97,109,101,115,112,97,99,101,32,109,111,100,117,108,101,32, + 108,111,97,100,101,100,32,119,105,116,104,32,112,97,116,104, + 32,123,33,114,125,41,4,114,159,0,0,0,114,173,0,0, 0,114,49,1,0,0,114,246,0,0,0,114,247,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, 248,0,0,0,21,5,0,0,115,8,0,0,0,6,7,4, @@ -2161,10 +2159,10 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,0,0,0,0,0,0,2,0,0,0,9,0,0, 0,67,0,0,0,115,76,0,0,0,116,0,106,1,100,1, 117,1,114,14,116,0,106,1,115,14,116,2,160,3,100,2, - 116,4,161,2,1,0,116,0,106,1,68,0,93,17,125,1, + 116,4,161,2,1,0,116,0,106,1,68,0,93,18,125,1, 122,7,124,1,124,0,131,1,87,0,2,0,1,0,83,0, - 4,0,116,5,121,37,1,0,1,0,1,0,89,0,113,17, - 100,1,83,0,119,0,41,3,122,46,83,101,97,114,99,104, + 4,0,116,5,121,35,1,0,1,0,1,0,89,0,113,17, + 119,0,100,1,83,0,41,3,122,46,83,101,97,114,99,104, 32,115,121,115,46,112,97,116,104,95,104,111,111,107,115,32, 102,111,114,32,97,32,102,105,110,100,101,114,32,102,111,114, 32,39,112,97,116,104,39,46,78,122,23,115,121,115,46,112, @@ -2175,17 +2173,17 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 90,4,104,111,111,107,114,7,0,0,0,114,7,0,0,0, 114,8,0,0,0,218,11,95,112,97,116,104,95,104,111,111, 107,115,54,5,0,0,115,18,0,0,0,16,3,12,1,10, - 1,2,1,14,1,12,1,4,1,4,2,2,253,122,22,80, + 1,2,1,14,1,12,1,4,1,2,255,4,3,122,22,80, 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, 104,111,111,107,115,99,2,0,0,0,0,0,0,0,0,0, 0,0,3,0,0,0,8,0,0,0,67,0,0,0,115,100, - 0,0,0,124,1,100,1,107,2,114,20,122,6,116,0,160, - 1,161,0,125,1,87,0,110,9,4,0,116,2,121,49,1, - 0,1,0,1,0,89,0,100,2,83,0,122,8,116,3,106, - 4,124,1,25,0,125,2,87,0,124,2,83,0,4,0,116, - 5,121,48,1,0,1,0,1,0,124,0,160,6,124,1,161, - 1,125,2,124,2,116,3,106,4,124,1,60,0,89,0,124, - 2,83,0,119,0,119,0,41,3,122,210,71,101,116,32,116, + 0,0,0,124,1,100,1,107,2,114,21,122,6,116,0,160, + 1,161,0,125,1,87,0,110,10,4,0,116,2,121,20,1, + 0,1,0,1,0,89,0,100,2,83,0,119,0,122,8,116, + 3,106,4,124,1,25,0,125,2,87,0,124,2,83,0,4, + 0,116,5,121,49,1,0,1,0,1,0,124,0,160,6,124, + 1,161,1,125,2,124,2,116,3,106,4,124,1,60,0,89, + 0,124,2,83,0,119,0,41,3,122,210,71,101,116,32,116, 104,101,32,102,105,110,100,101,114,32,102,111,114,32,116,104, 101,32,112,97,116,104,32,101,110,116,114,121,32,102,114,111, 109,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, @@ -2207,8 +2205,8 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,7,0,0,0,114,8,0,0,0,218,20,95,112,97, 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, 101,67,5,0,0,115,28,0,0,0,8,8,2,1,12,1, - 12,1,6,3,2,1,12,1,4,4,12,253,10,1,12,1, - 4,1,2,253,2,250,122,31,80,97,116,104,70,105,110,100, + 12,1,6,3,2,253,2,4,12,1,4,4,12,253,10,1, + 12,1,4,1,2,253,122,31,80,97,116,104,70,105,110,100, 101,114,46,95,112,97,116,104,95,105,109,112,111,114,116,101, 114,95,99,97,99,104,101,99,3,0,0,0,0,0,0,0, 0,0,0,0,7,0,0,0,4,0,0,0,67,0,0,0, @@ -2329,7 +2327,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, 4,0,0,0,79,0,0,0,115,28,0,0,0,100,1,100, 2,108,0,109,1,125,2,1,0,124,2,106,2,124,0,105, - 0,124,1,164,1,142,1,83,0,41,4,97,32,1,0,0, + 0,124,1,164,1,142,1,83,0,41,3,97,32,1,0,0, 10,32,32,32,32,32,32,32,32,70,105,110,100,32,100,105, 115,116,114,105,98,117,116,105,111,110,115,46,10,10,32,32, 32,32,32,32,32,32,82,101,116,117,114,110,32,97,110,32, @@ -2349,340 +2347,340 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 111,114,105,101,115,32,96,96,99,111,110,116,101,120,116,46, 112,97,116,104,96,96,46,10,32,32,32,32,32,32,32,32, 114,0,0,0,0,41,1,218,18,77,101,116,97,100,97,116, - 97,80,97,116,104,70,105,110,100,101,114,78,41,3,90,18, - 105,109,112,111,114,116,108,105,98,46,109,101,116,97,100,97, - 116,97,114,92,1,0,0,218,18,102,105,110,100,95,100,105, - 115,116,114,105,98,117,116,105,111,110,115,41,3,114,144,0, - 0,0,114,145,0,0,0,114,92,1,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,93,1,0,0, - 182,5,0,0,115,4,0,0,0,12,10,16,1,122,29,80, - 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,100, - 105,115,116,114,105,98,117,116,105,111,110,115,114,69,0,0, - 0,114,230,0,0,0,41,14,114,150,0,0,0,114,149,0, - 0,0,114,151,0,0,0,114,152,0,0,0,114,233,0,0, - 0,114,78,1,0,0,114,84,1,0,0,114,234,0,0,0, - 114,87,1,0,0,114,88,1,0,0,114,91,1,0,0,114, - 226,0,0,0,114,229,0,0,0,114,93,1,0,0,114,7, - 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,77,1,0,0,40,5,0,0,115,36,0,0,0, - 8,0,4,2,2,2,10,1,2,9,10,1,2,12,10,1, - 2,21,10,1,2,20,12,1,2,31,12,1,2,23,12,1, - 2,15,14,1,114,77,1,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,3,0,0,0,64,0, - 0,0,115,90,0,0,0,101,0,90,1,100,0,90,2,100, - 1,90,3,100,2,100,3,132,0,90,4,100,4,100,5,132, - 0,90,5,101,6,90,7,100,6,100,7,132,0,90,8,100, - 8,100,9,132,0,90,9,100,19,100,11,100,12,132,1,90, - 10,100,13,100,14,132,0,90,11,101,12,100,15,100,16,132, - 0,131,1,90,13,100,17,100,18,132,0,90,14,100,10,83, - 0,41,20,218,10,70,105,108,101,70,105,110,100,101,114,122, - 172,70,105,108,101,45,98,97,115,101,100,32,102,105,110,100, - 101,114,46,10,10,32,32,32,32,73,110,116,101,114,97,99, - 116,105,111,110,115,32,119,105,116,104,32,116,104,101,32,102, - 105,108,101,32,115,121,115,116,101,109,32,97,114,101,32,99, - 97,99,104,101,100,32,102,111,114,32,112,101,114,102,111,114, - 109,97,110,99,101,44,32,98,101,105,110,103,10,32,32,32, - 32,114,101,102,114,101,115,104,101,100,32,119,104,101,110,32, - 116,104,101,32,100,105,114,101,99,116,111,114,121,32,116,104, - 101,32,102,105,110,100,101,114,32,105,115,32,104,97,110,100, - 108,105,110,103,32,104,97,115,32,98,101,101,110,32,109,111, - 100,105,102,105,101,100,46,10,10,32,32,32,32,99,2,0, - 0,0,0,0,0,0,0,0,0,0,5,0,0,0,6,0, - 0,0,7,0,0,0,115,112,0,0,0,103,0,125,3,124, - 2,68,0,93,16,92,2,137,0,125,4,124,3,160,0,135, - 0,102,1,100,1,100,2,132,8,124,4,68,0,131,1,161, - 1,1,0,113,4,124,3,124,0,95,1,124,1,112,27,100, - 3,124,0,95,2,116,3,124,0,106,2,131,1,115,43,116, - 4,116,5,160,6,161,0,124,0,106,2,131,2,124,0,95, - 2,100,4,124,0,95,7,116,8,131,0,124,0,95,9,116, - 8,131,0,124,0,95,10,100,5,83,0,41,6,122,154,73, - 110,105,116,105,97,108,105,122,101,32,119,105,116,104,32,116, - 104,101,32,112,97,116,104,32,116,111,32,115,101,97,114,99, - 104,32,111,110,32,97,110,100,32,97,32,118,97,114,105,97, - 98,108,101,32,110,117,109,98,101,114,32,111,102,10,32,32, - 32,32,32,32,32,32,50,45,116,117,112,108,101,115,32,99, - 111,110,116,97,105,110,105,110,103,32,116,104,101,32,108,111, - 97,100,101,114,32,97,110,100,32,116,104,101,32,102,105,108, - 101,32,115,117,102,102,105,120,101,115,32,116,104,101,32,108, - 111,97,100,101,114,10,32,32,32,32,32,32,32,32,114,101, - 99,111,103,110,105,122,101,115,46,99,1,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,51,0, - 0,0,115,24,0,0,0,129,0,124,0,93,7,125,1,124, - 1,136,0,102,2,86,0,1,0,113,2,100,0,83,0,114, - 69,0,0,0,114,7,0,0,0,114,43,1,0,0,169,1, - 114,164,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 9,0,0,0,211,5,0,0,115,4,0,0,0,6,128,18, - 0,122,38,70,105,108,101,70,105,110,100,101,114,46,95,95, - 105,110,105,116,95,95,46,60,108,111,99,97,108,115,62,46, - 60,103,101,110,101,120,112,114,62,114,97,0,0,0,114,130, - 0,0,0,78,41,11,114,191,0,0,0,218,8,95,108,111, - 97,100,101,114,115,114,65,0,0,0,114,86,0,0,0,114, - 67,0,0,0,114,18,0,0,0,114,82,0,0,0,218,11, - 95,112,97,116,104,95,109,116,105,109,101,218,3,115,101,116, - 218,11,95,112,97,116,104,95,99,97,99,104,101,218,19,95, - 114,101,108,97,120,101,100,95,112,97,116,104,95,99,97,99, - 104,101,41,5,114,143,0,0,0,114,65,0,0,0,218,14, - 108,111,97,100,101,114,95,100,101,116,97,105,108,115,90,7, - 108,111,97,100,101,114,115,114,212,0,0,0,114,7,0,0, - 0,114,95,1,0,0,114,8,0,0,0,114,236,0,0,0, - 205,5,0,0,115,20,0,0,0,4,4,12,1,26,1,6, - 1,10,2,10,1,18,1,6,1,8,1,12,1,122,19,70, - 105,108,101,70,105,110,100,101,114,46,95,95,105,110,105,116, - 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,2,0,0,0,67,0,0,0,115,10,0,0,0, - 100,1,124,0,95,0,100,2,83,0,41,3,122,31,73,110, - 118,97,108,105,100,97,116,101,32,116,104,101,32,100,105,114, - 101,99,116,111,114,121,32,109,116,105,109,101,46,114,130,0, - 0,0,78,41,1,114,97,1,0,0,114,21,1,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,78, - 1,0,0,221,5,0,0,114,81,0,0,0,122,28,70,105, - 108,101,70,105,110,100,101,114,46,105,110,118,97,108,105,100, - 97,116,101,95,99,97,99,104,101,115,99,2,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,67, - 0,0,0,115,54,0,0,0,116,0,160,1,100,1,116,2, - 161,2,1,0,124,0,160,3,124,1,161,1,125,2,124,2, - 100,2,117,0,114,19,100,2,103,0,102,2,83,0,124,2, - 106,4,124,2,106,5,112,25,103,0,102,2,83,0,41,3, - 122,197,84,114,121,32,116,111,32,102,105,110,100,32,97,32, - 108,111,97,100,101,114,32,102,111,114,32,116,104,101,32,115, - 112,101,99,105,102,105,101,100,32,109,111,100,117,108,101,44, - 32,111,114,32,116,104,101,32,110,97,109,101,115,112,97,99, - 101,10,32,32,32,32,32,32,32,32,112,97,99,107,97,103, - 101,32,112,111,114,116,105,111,110,115,46,32,82,101,116,117, - 114,110,115,32,40,108,111,97,100,101,114,44,32,108,105,115, - 116,45,111,102,45,112,111,114,116,105,111,110,115,41,46,10, - 10,32,32,32,32,32,32,32,32,84,104,105,115,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,85,115,101,32,102,105,110,100,95,115,112, - 101,99,40,41,32,105,110,115,116,101,97,100,46,10,10,32, - 32,32,32,32,32,32,32,122,101,70,105,108,101,70,105,110, - 100,101,114,46,102,105,110,100,95,108,111,97,100,101,114,40, - 41,32,105,115,32,100,101,112,114,101,99,97,116,101,100,32, - 97,110,100,32,115,108,97,116,101,100,32,102,111,114,32,114, - 101,109,111,118,97,108,32,105,110,32,80,121,116,104,111,110, - 32,51,46,49,50,59,32,117,115,101,32,102,105,110,100,95, - 115,112,101,99,40,41,32,105,110,115,116,101,97,100,78,41, - 6,114,99,0,0,0,114,100,0,0,0,114,101,0,0,0, - 114,226,0,0,0,114,164,0,0,0,114,202,0,0,0,41, - 3,114,143,0,0,0,114,163,0,0,0,114,210,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 161,0,0,0,227,5,0,0,115,14,0,0,0,6,7,2, - 2,4,254,10,3,8,1,8,1,16,1,122,22,70,105,108, - 101,70,105,110,100,101,114,46,102,105,110,100,95,108,111,97, - 100,101,114,99,6,0,0,0,0,0,0,0,0,0,0,0, - 7,0,0,0,6,0,0,0,67,0,0,0,115,26,0,0, - 0,124,1,124,2,124,3,131,2,125,6,116,0,124,2,124, - 3,124,6,124,4,100,1,141,4,83,0,41,2,78,114,201, - 0,0,0,41,1,114,213,0,0,0,41,7,114,143,0,0, - 0,114,211,0,0,0,114,163,0,0,0,114,65,0,0,0, - 90,4,115,109,115,108,114,225,0,0,0,114,164,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 91,1,0,0,242,5,0,0,115,8,0,0,0,10,1,8, - 1,2,1,6,255,122,20,70,105,108,101,70,105,110,100,101, - 114,46,95,103,101,116,95,115,112,101,99,78,99,3,0,0, - 0,0,0,0,0,0,0,0,0,14,0,0,0,9,0,0, - 0,67,0,0,0,115,120,1,0,0,100,1,125,3,124,1, - 160,0,100,2,161,1,100,3,25,0,125,4,122,12,116,1, - 124,0,106,2,112,17,116,3,160,4,161,0,131,1,106,5, - 125,5,87,0,110,9,4,0,116,6,121,187,1,0,1,0, - 1,0,100,4,125,5,89,0,124,5,124,0,106,7,107,3, - 114,43,124,0,160,8,161,0,1,0,124,5,124,0,95,7, - 116,9,131,0,114,54,124,0,106,10,125,6,124,4,160,11, - 161,0,125,7,110,5,124,0,106,12,125,6,124,4,125,7, - 124,7,124,6,118,0,114,106,116,13,124,0,106,2,124,4, - 131,2,125,8,124,0,106,14,68,0,93,29,92,2,125,9, - 125,10,100,5,124,9,23,0,125,11,116,13,124,8,124,11, - 131,2,125,12,116,15,124,12,131,1,114,101,124,0,160,16, - 124,10,124,1,124,12,124,8,103,1,124,2,161,5,2,0, - 1,0,83,0,113,72,116,17,124,8,131,1,125,3,124,0, - 106,14,68,0,93,54,92,2,125,9,125,10,122,10,116,13, - 124,0,106,2,124,4,124,9,23,0,131,2,125,12,87,0, - 110,10,4,0,116,18,121,186,1,0,1,0,1,0,89,0, - 1,0,100,6,83,0,116,19,106,20,100,7,124,12,100,3, - 100,8,141,3,1,0,124,7,124,9,23,0,124,6,118,0, - 114,163,116,15,124,12,131,1,114,163,124,0,160,16,124,10, - 124,1,124,12,100,6,124,2,161,5,2,0,1,0,83,0, - 113,109,124,3,114,184,116,19,160,20,100,9,124,8,161,2, - 1,0,116,19,160,21,124,1,100,6,161,2,125,13,124,8, - 103,1,124,13,95,22,124,13,83,0,100,6,83,0,119,0, - 119,0,41,10,122,111,84,114,121,32,116,111,32,102,105,110, - 100,32,97,32,115,112,101,99,32,102,111,114,32,116,104,101, - 32,115,112,101,99,105,102,105,101,100,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,82,101,116,117, - 114,110,115,32,116,104,101,32,109,97,116,99,104,105,110,103, - 32,115,112,101,99,44,32,111,114,32,78,111,110,101,32,105, - 102,32,110,111,116,32,102,111,117,110,100,46,10,32,32,32, - 32,32,32,32,32,70,114,97,0,0,0,114,44,0,0,0, - 114,130,0,0,0,114,236,0,0,0,78,122,9,116,114,121, - 105,110,103,32,123,125,41,1,90,9,118,101,114,98,111,115, - 105,116,121,122,25,112,111,115,115,105,98,108,101,32,110,97, - 109,101,115,112,97,99,101,32,102,111,114,32,123,125,41,23, - 114,104,0,0,0,114,75,0,0,0,114,65,0,0,0,114, - 18,0,0,0,114,82,0,0,0,114,35,1,0,0,114,76, - 0,0,0,114,97,1,0,0,218,11,95,102,105,108,108,95, - 99,97,99,104,101,114,21,0,0,0,114,100,1,0,0,114, - 131,0,0,0,114,99,1,0,0,114,67,0,0,0,114,96, - 1,0,0,114,80,0,0,0,114,91,1,0,0,114,83,0, - 0,0,114,111,0,0,0,114,159,0,0,0,114,173,0,0, - 0,114,207,0,0,0,114,202,0,0,0,41,14,114,143,0, - 0,0,114,163,0,0,0,114,225,0,0,0,90,12,105,115, - 95,110,97,109,101,115,112,97,99,101,90,11,116,97,105,108, - 95,109,111,100,117,108,101,114,193,0,0,0,90,5,99,97, - 99,104,101,90,12,99,97,99,104,101,95,109,111,100,117,108, - 101,90,9,98,97,115,101,95,112,97,116,104,114,44,1,0, - 0,114,211,0,0,0,90,13,105,110,105,116,95,102,105,108, - 101,110,97,109,101,90,9,102,117,108,108,95,112,97,116,104, - 114,210,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,226,0,0,0,247,5,0,0,115,86,0, - 0,0,4,5,14,1,2,1,24,1,12,1,6,1,10,1, - 8,1,6,1,6,2,6,1,10,1,6,2,4,1,8,2, - 12,1,14,1,8,1,10,1,8,1,24,1,2,255,8,5, - 14,2,2,1,20,1,12,1,8,1,16,1,12,1,8,1, - 10,1,4,1,8,255,2,128,4,2,12,1,12,1,8,1, - 4,1,4,1,2,244,2,228,122,20,70,105,108,101,70,105, - 110,100,101,114,46,102,105,110,100,95,115,112,101,99,99,1, - 0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,10, - 0,0,0,67,0,0,0,115,190,0,0,0,124,0,106,0, - 125,1,122,11,116,1,160,2,124,1,112,11,116,1,160,3, - 161,0,161,1,125,2,87,0,110,12,4,0,116,4,116,5, - 116,6,102,3,121,94,1,0,1,0,1,0,103,0,125,2, - 89,0,116,7,106,8,160,9,100,1,161,1,115,39,116,10, - 124,2,131,1,124,0,95,11,110,37,116,10,131,0,125,3, - 124,2,68,0,93,28,125,4,124,4,160,12,100,2,161,1, - 92,3,125,5,125,6,125,7,124,6,114,65,100,3,160,13, - 124,5,124,7,160,14,161,0,161,2,125,8,110,2,124,5, - 125,8,124,3,160,15,124,8,161,1,1,0,113,44,124,3, - 124,0,95,11,116,7,106,8,160,9,116,16,161,1,114,92, - 100,4,100,5,132,0,124,2,68,0,131,1,124,0,95,17, - 100,6,83,0,100,6,83,0,119,0,41,7,122,68,70,105, - 108,108,32,116,104,101,32,99,97,99,104,101,32,111,102,32, - 112,111,116,101,110,116,105,97,108,32,109,111,100,117,108,101, - 115,32,97,110,100,32,112,97,99,107,97,103,101,115,32,102, - 111,114,32,116,104,105,115,32,100,105,114,101,99,116,111,114, - 121,46,114,14,0,0,0,114,97,0,0,0,114,88,0,0, - 0,99,1,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,4,0,0,0,83,0,0,0,115,20,0,0,0,104, - 0,124,0,93,6,125,1,124,1,160,0,161,0,146,2,113, - 2,83,0,114,7,0,0,0,41,1,114,131,0,0,0,41, - 2,114,5,0,0,0,90,2,102,110,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,13,0,0,0,71,6, - 0,0,115,2,0,0,0,20,0,122,41,70,105,108,101,70, - 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, - 101,46,60,108,111,99,97,108,115,62,46,60,115,101,116,99, - 111,109,112,62,78,41,18,114,65,0,0,0,114,18,0,0, - 0,90,7,108,105,115,116,100,105,114,114,82,0,0,0,114, - 85,1,0,0,218,15,80,101,114,109,105,115,115,105,111,110, - 69,114,114,111,114,218,18,78,111,116,65,68,105,114,101,99, - 116,111,114,121,69,114,114,111,114,114,15,0,0,0,114,25, - 0,0,0,114,26,0,0,0,114,98,1,0,0,114,99,1, - 0,0,114,126,0,0,0,114,89,0,0,0,114,131,0,0, - 0,218,3,97,100,100,114,27,0,0,0,114,100,1,0,0, - 41,9,114,143,0,0,0,114,65,0,0,0,90,8,99,111, - 110,116,101,110,116,115,90,21,108,111,119,101,114,95,115,117, - 102,102,105,120,95,99,111,110,116,101,110,116,115,114,70,1, - 0,0,114,141,0,0,0,114,54,1,0,0,114,44,1,0, - 0,90,8,110,101,119,95,110,97,109,101,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,102,1,0,0,42, - 6,0,0,115,38,0,0,0,6,2,2,1,22,1,18,1, - 6,3,12,3,12,1,6,7,8,1,16,1,4,1,18,1, - 4,2,12,1,6,1,12,1,20,1,4,255,2,233,122,22, - 70,105,108,101,70,105,110,100,101,114,46,95,102,105,108,108, - 95,99,97,99,104,101,99,1,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,3,0,0,0,7,0,0,0,115, - 18,0,0,0,135,0,135,1,102,2,100,1,100,2,132,8, - 125,2,124,2,83,0,41,4,97,20,1,0,0,65,32,99, - 108,97,115,115,32,109,101,116,104,111,100,32,119,104,105,99, - 104,32,114,101,116,117,114,110,115,32,97,32,99,108,111,115, - 117,114,101,32,116,111,32,117,115,101,32,111,110,32,115,121, - 115,46,112,97,116,104,95,104,111,111,107,10,32,32,32,32, - 32,32,32,32,119,104,105,99,104,32,119,105,108,108,32,114, - 101,116,117,114,110,32,97,110,32,105,110,115,116,97,110,99, - 101,32,117,115,105,110,103,32,116,104,101,32,115,112,101,99, - 105,102,105,101,100,32,108,111,97,100,101,114,115,32,97,110, - 100,32,116,104,101,32,112,97,116,104,10,32,32,32,32,32, - 32,32,32,99,97,108,108,101,100,32,111,110,32,116,104,101, - 32,99,108,111,115,117,114,101,46,10,10,32,32,32,32,32, - 32,32,32,73,102,32,116,104,101,32,112,97,116,104,32,99, - 97,108,108,101,100,32,111,110,32,116,104,101,32,99,108,111, - 115,117,114,101,32,105,115,32,110,111,116,32,97,32,100,105, - 114,101,99,116,111,114,121,44,32,73,109,112,111,114,116,69, - 114,114,111,114,32,105,115,10,32,32,32,32,32,32,32,32, - 114,97,105,115,101,100,46,10,10,32,32,32,32,32,32,32, - 32,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, - 0,0,4,0,0,0,19,0,0,0,115,36,0,0,0,116, - 0,124,0,131,1,115,10,116,1,100,1,124,0,100,2,141, - 2,130,1,136,0,124,0,103,1,136,1,162,1,82,0,142, - 0,83,0,41,4,122,45,80,97,116,104,32,104,111,111,107, - 32,102,111,114,32,105,109,112,111,114,116,108,105,98,46,109, - 97,99,104,105,110,101,114,121,46,70,105,108,101,70,105,110, - 100,101,114,46,122,30,111,110,108,121,32,100,105,114,101,99, - 116,111,114,105,101,115,32,97,114,101,32,115,117,112,112,111, - 114,116,101,100,114,71,0,0,0,78,41,2,114,83,0,0, - 0,114,142,0,0,0,114,71,0,0,0,169,2,114,221,0, - 0,0,114,101,1,0,0,114,7,0,0,0,114,8,0,0, - 0,218,24,112,97,116,104,95,104,111,111,107,95,102,111,114, - 95,70,105,108,101,70,105,110,100,101,114,83,6,0,0,115, - 6,0,0,0,8,2,12,1,16,1,122,54,70,105,108,101, - 70,105,110,100,101,114,46,112,97,116,104,95,104,111,111,107, - 46,60,108,111,99,97,108,115,62,46,112,97,116,104,95,104, - 111,111,107,95,102,111,114,95,70,105,108,101,70,105,110,100, - 101,114,78,114,7,0,0,0,41,3,114,221,0,0,0,114, - 101,1,0,0,114,107,1,0,0,114,7,0,0,0,114,106, - 1,0,0,114,8,0,0,0,218,9,112,97,116,104,95,104, - 111,111,107,73,6,0,0,115,4,0,0,0,14,10,4,6, - 122,20,70,105,108,101,70,105,110,100,101,114,46,112,97,116, - 104,95,104,111,111,107,99,1,0,0,0,0,0,0,0,0, - 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,114, - 67,1,0,0,41,2,78,122,16,70,105,108,101,70,105,110, - 100,101,114,40,123,33,114,125,41,41,2,114,89,0,0,0, - 114,65,0,0,0,114,21,1,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,68,1,0,0,91,6, - 0,0,114,61,1,0,0,122,19,70,105,108,101,70,105,110, - 100,101,114,46,95,95,114,101,112,114,95,95,114,69,0,0, - 0,41,15,114,150,0,0,0,114,149,0,0,0,114,151,0, - 0,0,114,152,0,0,0,114,236,0,0,0,114,78,1,0, - 0,114,167,0,0,0,114,229,0,0,0,114,161,0,0,0, - 114,91,1,0,0,114,226,0,0,0,114,102,1,0,0,114, - 234,0,0,0,114,108,1,0,0,114,68,1,0,0,114,7, - 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,94,1,0,0,196,5,0,0,115,24,0,0,0, - 8,0,4,2,8,7,8,16,4,4,8,2,8,15,10,5, - 8,51,2,31,10,1,12,17,114,94,1,0,0,99,4,0, - 0,0,0,0,0,0,0,0,0,0,6,0,0,0,8,0, - 0,0,67,0,0,0,115,144,0,0,0,124,0,160,0,100, - 1,161,1,125,4,124,0,160,0,100,2,161,1,125,5,124, - 4,115,33,124,5,114,18,124,5,106,1,125,4,110,15,124, - 2,124,3,107,2,114,28,116,2,124,1,124,2,131,2,125, - 4,110,5,116,3,124,1,124,2,131,2,125,4,124,5,115, - 42,116,4,124,1,124,2,124,4,100,3,141,3,125,5,122, - 19,124,5,124,0,100,2,60,0,124,4,124,0,100,1,60, - 0,124,2,124,0,100,4,60,0,124,3,124,0,100,5,60, - 0,87,0,100,0,83,0,4,0,116,5,121,71,1,0,1, - 0,1,0,89,0,100,0,83,0,119,0,41,6,78,218,10, - 95,95,108,111,97,100,101,114,95,95,218,8,95,95,115,112, - 101,99,95,95,114,95,1,0,0,90,8,95,95,102,105,108, - 101,95,95,90,10,95,95,99,97,99,104,101,100,95,95,41, - 6,218,3,103,101,116,114,164,0,0,0,114,41,1,0,0, - 114,34,1,0,0,114,213,0,0,0,218,9,69,120,99,101, - 112,116,105,111,110,41,6,90,2,110,115,114,141,0,0,0, - 90,8,112,97,116,104,110,97,109,101,90,9,99,112,97,116, - 104,110,97,109,101,114,164,0,0,0,114,210,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,14, - 95,102,105,120,95,117,112,95,109,111,100,117,108,101,97,6, - 0,0,115,36,0,0,0,10,2,10,1,4,1,4,1,8, - 1,8,1,12,1,10,2,4,1,14,1,2,1,8,1,8, - 1,8,1,14,1,12,1,6,2,2,254,114,113,1,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,67,0,0,0,115,38,0,0,0,116,0, - 116,1,160,2,161,0,102,2,125,0,116,3,116,4,102,2, - 125,1,116,5,116,6,102,2,125,2,124,0,124,1,124,2, - 103,3,83,0,41,2,122,95,82,101,116,117,114,110,115,32, - 97,32,108,105,115,116,32,111,102,32,102,105,108,101,45,98, - 97,115,101,100,32,109,111,100,117,108,101,32,108,111,97,100, - 101,114,115,46,10,10,32,32,32,32,69,97,99,104,32,105, - 116,101,109,32,105,115,32,97,32,116,117,112,108,101,32,40, - 108,111,97,100,101,114,44,32,115,117,102,102,105,120,101,115, - 41,46,10,32,32,32,32,78,41,7,114,30,1,0,0,114, + 97,80,97,116,104,70,105,110,100,101,114,41,3,90,18,105, + 109,112,111,114,116,108,105,98,46,109,101,116,97,100,97,116, + 97,114,92,1,0,0,218,18,102,105,110,100,95,100,105,115, + 116,114,105,98,117,116,105,111,110,115,41,3,114,144,0,0, + 0,114,145,0,0,0,114,92,1,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,93,1,0,0,182, + 5,0,0,115,4,0,0,0,12,10,16,1,122,29,80,97, + 116,104,70,105,110,100,101,114,46,102,105,110,100,95,100,105, + 115,116,114,105,98,117,116,105,111,110,115,114,69,0,0,0, + 114,230,0,0,0,41,14,114,150,0,0,0,114,149,0,0, + 0,114,151,0,0,0,114,152,0,0,0,114,233,0,0,0, + 114,78,1,0,0,114,84,1,0,0,114,234,0,0,0,114, + 87,1,0,0,114,88,1,0,0,114,91,1,0,0,114,226, + 0,0,0,114,229,0,0,0,114,93,1,0,0,114,7,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,114,77,1,0,0,40,5,0,0,115,36,0,0,0,8, + 0,4,2,2,2,10,1,2,9,10,1,2,12,10,1,2, + 21,10,1,2,20,12,1,2,31,12,1,2,23,12,1,2, + 15,14,1,114,77,1,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, + 0,115,90,0,0,0,101,0,90,1,100,0,90,2,100,1, + 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, + 90,5,101,6,90,7,100,6,100,7,132,0,90,8,100,8, + 100,9,132,0,90,9,100,19,100,11,100,12,132,1,90,10, + 100,13,100,14,132,0,90,11,101,12,100,15,100,16,132,0, + 131,1,90,13,100,17,100,18,132,0,90,14,100,10,83,0, + 41,20,218,10,70,105,108,101,70,105,110,100,101,114,122,172, + 70,105,108,101,45,98,97,115,101,100,32,102,105,110,100,101, + 114,46,10,10,32,32,32,32,73,110,116,101,114,97,99,116, + 105,111,110,115,32,119,105,116,104,32,116,104,101,32,102,105, + 108,101,32,115,121,115,116,101,109,32,97,114,101,32,99,97, + 99,104,101,100,32,102,111,114,32,112,101,114,102,111,114,109, + 97,110,99,101,44,32,98,101,105,110,103,10,32,32,32,32, + 114,101,102,114,101,115,104,101,100,32,119,104,101,110,32,116, + 104,101,32,100,105,114,101,99,116,111,114,121,32,116,104,101, + 32,102,105,110,100,101,114,32,105,115,32,104,97,110,100,108, + 105,110,103,32,104,97,115,32,98,101,101,110,32,109,111,100, + 105,102,105,101,100,46,10,10,32,32,32,32,99,2,0,0, + 0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0, + 0,7,0,0,0,115,112,0,0,0,103,0,125,3,124,2, + 68,0,93,16,92,2,137,0,125,4,124,3,160,0,135,0, + 102,1,100,1,100,2,132,8,124,4,68,0,131,1,161,1, + 1,0,113,4,124,3,124,0,95,1,124,1,112,27,100,3, + 124,0,95,2,116,3,124,0,106,2,131,1,115,43,116,4, + 116,5,160,6,161,0,124,0,106,2,131,2,124,0,95,2, + 100,4,124,0,95,7,116,8,131,0,124,0,95,9,116,8, + 131,0,124,0,95,10,100,5,83,0,41,6,122,154,73,110, + 105,116,105,97,108,105,122,101,32,119,105,116,104,32,116,104, + 101,32,112,97,116,104,32,116,111,32,115,101,97,114,99,104, + 32,111,110,32,97,110,100,32,97,32,118,97,114,105,97,98, + 108,101,32,110,117,109,98,101,114,32,111,102,10,32,32,32, + 32,32,32,32,32,50,45,116,117,112,108,101,115,32,99,111, + 110,116,97,105,110,105,110,103,32,116,104,101,32,108,111,97, + 100,101,114,32,97,110,100,32,116,104,101,32,102,105,108,101, + 32,115,117,102,102,105,120,101,115,32,116,104,101,32,108,111, + 97,100,101,114,10,32,32,32,32,32,32,32,32,114,101,99, + 111,103,110,105,122,101,115,46,99,1,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,51,0,0, + 0,115,24,0,0,0,129,0,124,0,93,7,125,1,124,1, + 136,0,102,2,86,0,1,0,113,2,100,0,83,0,114,69, + 0,0,0,114,7,0,0,0,114,43,1,0,0,169,1,114, + 164,0,0,0,114,7,0,0,0,114,8,0,0,0,114,9, + 0,0,0,211,5,0,0,115,4,0,0,0,2,128,22,0, + 122,38,70,105,108,101,70,105,110,100,101,114,46,95,95,105, + 110,105,116,95,95,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,114,97,0,0,0,114,130,0, + 0,0,78,41,11,114,191,0,0,0,218,8,95,108,111,97, + 100,101,114,115,114,65,0,0,0,114,86,0,0,0,114,67, + 0,0,0,114,18,0,0,0,114,82,0,0,0,218,11,95, + 112,97,116,104,95,109,116,105,109,101,218,3,115,101,116,218, + 11,95,112,97,116,104,95,99,97,99,104,101,218,19,95,114, + 101,108,97,120,101,100,95,112,97,116,104,95,99,97,99,104, + 101,41,5,114,143,0,0,0,114,65,0,0,0,218,14,108, + 111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108, + 111,97,100,101,114,115,114,212,0,0,0,114,7,0,0,0, + 114,95,1,0,0,114,8,0,0,0,114,236,0,0,0,205, + 5,0,0,115,20,0,0,0,4,4,12,1,26,1,6,1, + 10,2,10,1,18,1,6,1,8,1,12,1,122,19,70,105, + 108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95, + 95,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, + 0,0,2,0,0,0,67,0,0,0,115,10,0,0,0,100, + 1,124,0,95,0,100,2,83,0,41,3,122,31,73,110,118, + 97,108,105,100,97,116,101,32,116,104,101,32,100,105,114,101, + 99,116,111,114,121,32,109,116,105,109,101,46,114,130,0,0, + 0,78,41,1,114,97,1,0,0,114,21,1,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,78,1, + 0,0,221,5,0,0,114,81,0,0,0,122,28,70,105,108, + 101,70,105,110,100,101,114,46,105,110,118,97,108,105,100,97, + 116,101,95,99,97,99,104,101,115,99,2,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,4,0,0,0,67,0, + 0,0,115,54,0,0,0,116,0,160,1,100,1,116,2,161, + 2,1,0,124,0,160,3,124,1,161,1,125,2,124,2,100, + 2,117,0,114,19,100,2,103,0,102,2,83,0,124,2,106, + 4,124,2,106,5,112,25,103,0,102,2,83,0,41,3,122, + 197,84,114,121,32,116,111,32,102,105,110,100,32,97,32,108, + 111,97,100,101,114,32,102,111,114,32,116,104,101,32,115,112, + 101,99,105,102,105,101,100,32,109,111,100,117,108,101,44,32, + 111,114,32,116,104,101,32,110,97,109,101,115,112,97,99,101, + 10,32,32,32,32,32,32,32,32,112,97,99,107,97,103,101, + 32,112,111,114,116,105,111,110,115,46,32,82,101,116,117,114, + 110,115,32,40,108,111,97,100,101,114,44,32,108,105,115,116, + 45,111,102,45,112,111,114,116,105,111,110,115,41,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, + 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, + 32,32,32,32,32,32,122,101,70,105,108,101,70,105,110,100, + 101,114,46,102,105,110,100,95,108,111,97,100,101,114,40,41, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97, + 110,100,32,115,108,97,116,101,100,32,102,111,114,32,114,101, + 109,111,118,97,108,32,105,110,32,80,121,116,104,111,110,32, + 51,46,49,50,59,32,117,115,101,32,102,105,110,100,95,115, + 112,101,99,40,41,32,105,110,115,116,101,97,100,78,41,6, + 114,99,0,0,0,114,100,0,0,0,114,101,0,0,0,114, + 226,0,0,0,114,164,0,0,0,114,202,0,0,0,41,3, + 114,143,0,0,0,114,163,0,0,0,114,210,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,161, + 0,0,0,227,5,0,0,115,14,0,0,0,6,7,2,2, + 4,254,10,3,8,1,8,1,16,1,122,22,70,105,108,101, + 70,105,110,100,101,114,46,102,105,110,100,95,108,111,97,100, + 101,114,99,6,0,0,0,0,0,0,0,0,0,0,0,7, + 0,0,0,6,0,0,0,67,0,0,0,115,26,0,0,0, + 124,1,124,2,124,3,131,2,125,6,116,0,124,2,124,3, + 124,6,124,4,100,1,141,4,83,0,41,2,78,114,201,0, + 0,0,41,1,114,213,0,0,0,41,7,114,143,0,0,0, + 114,211,0,0,0,114,163,0,0,0,114,65,0,0,0,90, + 4,115,109,115,108,114,225,0,0,0,114,164,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,91, + 1,0,0,242,5,0,0,115,8,0,0,0,10,1,8,1, + 2,1,6,255,122,20,70,105,108,101,70,105,110,100,101,114, + 46,95,103,101,116,95,115,112,101,99,78,99,3,0,0,0, + 0,0,0,0,0,0,0,0,14,0,0,0,9,0,0,0, + 67,0,0,0,115,122,1,0,0,100,1,125,3,124,1,160, + 0,100,2,161,1,100,3,25,0,125,4,122,12,116,1,124, + 0,106,2,112,17,116,3,160,4,161,0,131,1,106,5,125, + 5,87,0,110,11,4,0,116,6,121,32,1,0,1,0,1, + 0,100,4,125,5,89,0,110,1,119,0,124,5,124,0,106, + 7,107,3,114,45,124,0,160,8,161,0,1,0,124,5,124, + 0,95,7,116,9,131,0,114,56,124,0,106,10,125,6,124, + 4,160,11,161,0,125,7,110,5,124,0,106,12,125,6,124, + 4,125,7,124,7,124,6,118,0,114,108,116,13,124,0,106, + 2,124,4,131,2,125,8,124,0,106,14,68,0,93,29,92, + 2,125,9,125,10,100,5,124,9,23,0,125,11,116,13,124, + 8,124,11,131,2,125,12,116,15,124,12,131,1,114,103,124, + 0,160,16,124,10,124,1,124,12,124,8,103,1,124,2,161, + 5,2,0,1,0,83,0,113,74,116,17,124,8,131,1,125, + 3,124,0,106,14,68,0,93,55,92,2,125,9,125,10,122, + 10,116,13,124,0,106,2,124,4,124,9,23,0,131,2,125, + 12,87,0,110,11,4,0,116,18,121,136,1,0,1,0,1, + 0,89,0,1,0,100,6,83,0,119,0,116,19,106,20,100, + 7,124,12,100,3,100,8,141,3,1,0,124,7,124,9,23, + 0,124,6,118,0,114,166,116,15,124,12,131,1,114,166,124, + 0,160,16,124,10,124,1,124,12,100,6,124,2,161,5,2, + 0,1,0,83,0,113,111,124,3,114,187,116,19,160,20,100, + 9,124,8,161,2,1,0,116,19,160,21,124,1,100,6,161, + 2,125,13,124,8,103,1,124,13,95,22,124,13,83,0,100, + 6,83,0,41,10,122,111,84,114,121,32,116,111,32,102,105, + 110,100,32,97,32,115,112,101,99,32,102,111,114,32,116,104, + 101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,117, + 108,101,46,10,10,32,32,32,32,32,32,32,32,82,101,116, + 117,114,110,115,32,116,104,101,32,109,97,116,99,104,105,110, + 103,32,115,112,101,99,44,32,111,114,32,78,111,110,101,32, + 105,102,32,110,111,116,32,102,111,117,110,100,46,10,32,32, + 32,32,32,32,32,32,70,114,97,0,0,0,114,44,0,0, + 0,114,130,0,0,0,114,236,0,0,0,78,122,9,116,114, + 121,105,110,103,32,123,125,41,1,90,9,118,101,114,98,111, + 115,105,116,121,122,25,112,111,115,115,105,98,108,101,32,110, + 97,109,101,115,112,97,99,101,32,102,111,114,32,123,125,41, + 23,114,104,0,0,0,114,75,0,0,0,114,65,0,0,0, + 114,18,0,0,0,114,82,0,0,0,114,35,1,0,0,114, + 76,0,0,0,114,97,1,0,0,218,11,95,102,105,108,108, + 95,99,97,99,104,101,114,21,0,0,0,114,100,1,0,0, + 114,131,0,0,0,114,99,1,0,0,114,67,0,0,0,114, + 96,1,0,0,114,80,0,0,0,114,91,1,0,0,114,83, + 0,0,0,114,111,0,0,0,114,159,0,0,0,114,173,0, + 0,0,114,207,0,0,0,114,202,0,0,0,41,14,114,143, + 0,0,0,114,163,0,0,0,114,225,0,0,0,90,12,105, + 115,95,110,97,109,101,115,112,97,99,101,90,11,116,97,105, + 108,95,109,111,100,117,108,101,114,193,0,0,0,90,5,99, + 97,99,104,101,90,12,99,97,99,104,101,95,109,111,100,117, + 108,101,90,9,98,97,115,101,95,112,97,116,104,114,44,1, + 0,0,114,211,0,0,0,90,13,105,110,105,116,95,102,105, + 108,101,110,97,109,101,90,9,102,117,108,108,95,112,97,116, + 104,114,210,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,226,0,0,0,247,5,0,0,115,86, + 0,0,0,4,5,14,1,2,1,24,1,12,1,8,1,2, + 255,10,2,8,1,6,1,6,2,6,1,10,1,6,2,4, + 1,8,2,12,1,14,1,8,1,10,1,8,1,24,1,2, + 255,8,5,14,2,2,1,20,1,12,1,8,1,2,255,16, + 2,12,1,8,1,10,1,4,1,8,255,2,128,4,2,12, + 1,12,1,8,1,4,1,4,1,122,20,70,105,108,101,70, + 105,110,100,101,114,46,102,105,110,100,95,115,112,101,99,99, + 1,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0, + 10,0,0,0,67,0,0,0,115,192,0,0,0,124,0,106, + 0,125,1,122,11,116,1,160,2,124,1,112,11,116,1,160, + 3,161,0,161,1,125,2,87,0,110,14,4,0,116,4,116, + 5,116,6,102,3,121,28,1,0,1,0,1,0,103,0,125, + 2,89,0,110,1,119,0,116,7,106,8,160,9,100,1,161, + 1,115,41,116,10,124,2,131,1,124,0,95,11,110,37,116, + 10,131,0,125,3,124,2,68,0,93,28,125,4,124,4,160, + 12,100,2,161,1,92,3,125,5,125,6,125,7,124,6,114, + 67,100,3,160,13,124,5,124,7,160,14,161,0,161,2,125, + 8,110,2,124,5,125,8,124,3,160,15,124,8,161,1,1, + 0,113,46,124,3,124,0,95,11,116,7,106,8,160,9,116, + 16,161,1,114,94,100,4,100,5,132,0,124,2,68,0,131, + 1,124,0,95,17,100,6,83,0,100,6,83,0,41,7,122, + 68,70,105,108,108,32,116,104,101,32,99,97,99,104,101,32, + 111,102,32,112,111,116,101,110,116,105,97,108,32,109,111,100, + 117,108,101,115,32,97,110,100,32,112,97,99,107,97,103,101, + 115,32,102,111,114,32,116,104,105,115,32,100,105,114,101,99, + 116,111,114,121,46,114,14,0,0,0,114,97,0,0,0,114, + 88,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,83,0,0,0,115,20,0, + 0,0,104,0,124,0,93,6,125,1,124,1,160,0,161,0, + 146,2,113,2,83,0,114,7,0,0,0,41,1,114,131,0, + 0,0,41,2,114,5,0,0,0,90,2,102,110,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,13,0,0, + 0,71,6,0,0,115,2,0,0,0,20,0,122,41,70,105, + 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99, + 97,99,104,101,46,60,108,111,99,97,108,115,62,46,60,115, + 101,116,99,111,109,112,62,78,41,18,114,65,0,0,0,114, + 18,0,0,0,90,7,108,105,115,116,100,105,114,114,82,0, + 0,0,114,85,1,0,0,218,15,80,101,114,109,105,115,115, + 105,111,110,69,114,114,111,114,218,18,78,111,116,65,68,105, + 114,101,99,116,111,114,121,69,114,114,111,114,114,15,0,0, + 0,114,25,0,0,0,114,26,0,0,0,114,98,1,0,0, + 114,99,1,0,0,114,126,0,0,0,114,89,0,0,0,114, + 131,0,0,0,218,3,97,100,100,114,27,0,0,0,114,100, + 1,0,0,41,9,114,143,0,0,0,114,65,0,0,0,90, + 8,99,111,110,116,101,110,116,115,90,21,108,111,119,101,114, + 95,115,117,102,102,105,120,95,99,111,110,116,101,110,116,115, + 114,70,1,0,0,114,141,0,0,0,114,54,1,0,0,114, + 44,1,0,0,90,8,110,101,119,95,110,97,109,101,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,102,1, + 0,0,42,6,0,0,115,38,0,0,0,6,2,2,1,22, + 1,18,1,8,3,2,253,12,6,12,1,6,7,8,1,16, + 1,4,1,18,1,4,2,12,1,6,1,12,1,20,1,4, + 255,122,22,70,105,108,101,70,105,110,100,101,114,46,95,102, + 105,108,108,95,99,97,99,104,101,99,1,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,7,0, + 0,0,115,18,0,0,0,135,0,135,1,102,2,100,1,100, + 2,132,8,125,2,124,2,83,0,41,3,97,20,1,0,0, + 65,32,99,108,97,115,115,32,109,101,116,104,111,100,32,119, + 104,105,99,104,32,114,101,116,117,114,110,115,32,97,32,99, + 108,111,115,117,114,101,32,116,111,32,117,115,101,32,111,110, + 32,115,121,115,46,112,97,116,104,95,104,111,111,107,10,32, + 32,32,32,32,32,32,32,119,104,105,99,104,32,119,105,108, + 108,32,114,101,116,117,114,110,32,97,110,32,105,110,115,116, + 97,110,99,101,32,117,115,105,110,103,32,116,104,101,32,115, + 112,101,99,105,102,105,101,100,32,108,111,97,100,101,114,115, + 32,97,110,100,32,116,104,101,32,112,97,116,104,10,32,32, + 32,32,32,32,32,32,99,97,108,108,101,100,32,111,110,32, + 116,104,101,32,99,108,111,115,117,114,101,46,10,10,32,32, + 32,32,32,32,32,32,73,102,32,116,104,101,32,112,97,116, + 104,32,99,97,108,108,101,100,32,111,110,32,116,104,101,32, + 99,108,111,115,117,114,101,32,105,115,32,110,111,116,32,97, + 32,100,105,114,101,99,116,111,114,121,44,32,73,109,112,111, + 114,116,69,114,114,111,114,32,105,115,10,32,32,32,32,32, + 32,32,32,114,97,105,115,101,100,46,10,10,32,32,32,32, + 32,32,32,32,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,4,0,0,0,19,0,0,0,115,36,0, + 0,0,116,0,124,0,131,1,115,10,116,1,100,1,124,0, + 100,2,141,2,130,1,136,0,124,0,103,1,136,1,162,1, + 82,0,142,0,83,0,41,3,122,45,80,97,116,104,32,104, + 111,111,107,32,102,111,114,32,105,109,112,111,114,116,108,105, + 98,46,109,97,99,104,105,110,101,114,121,46,70,105,108,101, + 70,105,110,100,101,114,46,122,30,111,110,108,121,32,100,105, + 114,101,99,116,111,114,105,101,115,32,97,114,101,32,115,117, + 112,112,111,114,116,101,100,114,71,0,0,0,41,2,114,83, + 0,0,0,114,142,0,0,0,114,71,0,0,0,169,2,114, + 221,0,0,0,114,101,1,0,0,114,7,0,0,0,114,8, + 0,0,0,218,24,112,97,116,104,95,104,111,111,107,95,102, + 111,114,95,70,105,108,101,70,105,110,100,101,114,83,6,0, + 0,115,6,0,0,0,8,2,12,1,16,1,122,54,70,105, + 108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,111, + 111,107,46,60,108,111,99,97,108,115,62,46,112,97,116,104, + 95,104,111,111,107,95,102,111,114,95,70,105,108,101,70,105, + 110,100,101,114,114,7,0,0,0,41,3,114,221,0,0,0, + 114,101,1,0,0,114,107,1,0,0,114,7,0,0,0,114, + 106,1,0,0,114,8,0,0,0,218,9,112,97,116,104,95, + 104,111,111,107,73,6,0,0,115,4,0,0,0,14,10,4, + 6,122,20,70,105,108,101,70,105,110,100,101,114,46,112,97, + 116,104,95,104,111,111,107,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 114,67,1,0,0,41,2,78,122,16,70,105,108,101,70,105, + 110,100,101,114,40,123,33,114,125,41,41,2,114,89,0,0, + 0,114,65,0,0,0,114,21,1,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,68,1,0,0,91, + 6,0,0,114,61,1,0,0,122,19,70,105,108,101,70,105, + 110,100,101,114,46,95,95,114,101,112,114,95,95,114,69,0, + 0,0,41,15,114,150,0,0,0,114,149,0,0,0,114,151, + 0,0,0,114,152,0,0,0,114,236,0,0,0,114,78,1, + 0,0,114,167,0,0,0,114,229,0,0,0,114,161,0,0, + 0,114,91,1,0,0,114,226,0,0,0,114,102,1,0,0, + 114,234,0,0,0,114,108,1,0,0,114,68,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,94,1,0,0,196,5,0,0,115,24,0,0, + 0,8,0,4,2,8,7,8,16,4,4,8,2,8,15,10, + 5,8,51,2,31,10,1,12,17,114,94,1,0,0,99,4, + 0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,8, + 0,0,0,67,0,0,0,115,144,0,0,0,124,0,160,0, + 100,1,161,1,125,4,124,0,160,0,100,2,161,1,125,5, + 124,4,115,33,124,5,114,18,124,5,106,1,125,4,110,15, + 124,2,124,3,107,2,114,28,116,2,124,1,124,2,131,2, + 125,4,110,5,116,3,124,1,124,2,131,2,125,4,124,5, + 115,42,116,4,124,1,124,2,124,4,100,3,141,3,125,5, + 122,19,124,5,124,0,100,2,60,0,124,4,124,0,100,1, + 60,0,124,2,124,0,100,4,60,0,124,3,124,0,100,5, + 60,0,87,0,100,0,83,0,4,0,116,5,121,71,1,0, + 1,0,1,0,89,0,100,0,83,0,119,0,41,6,78,218, + 10,95,95,108,111,97,100,101,114,95,95,218,8,95,95,115, + 112,101,99,95,95,114,95,1,0,0,90,8,95,95,102,105, + 108,101,95,95,90,10,95,95,99,97,99,104,101,100,95,95, + 41,6,218,3,103,101,116,114,164,0,0,0,114,41,1,0, + 0,114,34,1,0,0,114,213,0,0,0,218,9,69,120,99, + 101,112,116,105,111,110,41,6,90,2,110,115,114,141,0,0, + 0,90,8,112,97,116,104,110,97,109,101,90,9,99,112,97, + 116,104,110,97,109,101,114,164,0,0,0,114,210,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, + 14,95,102,105,120,95,117,112,95,109,111,100,117,108,101,97, + 6,0,0,115,36,0,0,0,10,2,10,1,4,1,4,1, + 8,1,8,1,12,1,10,2,4,1,14,1,2,1,8,1, + 8,1,8,1,14,1,12,1,6,2,2,254,114,113,1,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,3,0,0,0,67,0,0,0,115,38,0,0,0,116, + 0,116,1,160,2,161,0,102,2,125,0,116,3,116,4,102, + 2,125,1,116,5,116,6,102,2,125,2,124,0,124,1,124, + 2,103,3,83,0,41,1,122,95,82,101,116,117,114,110,115, + 32,97,32,108,105,115,116,32,111,102,32,102,105,108,101,45, + 98,97,115,101,100,32,109,111,100,117,108,101,32,108,111,97, + 100,101,114,115,46,10,10,32,32,32,32,69,97,99,104,32, + 105,116,101,109,32,105,115,32,97,32,116,117,112,108,101,32, + 40,108,111,97,100,101,114,44,32,115,117,102,102,105,120,101, + 115,41,46,10,32,32,32,32,41,7,114,30,1,0,0,114, 187,0,0,0,218,18,101,120,116,101,110,115,105,111,110,95, 115,117,102,102,105,120,101,115,114,34,1,0,0,114,127,0, 0,0,114,41,1,0,0,114,113,0,0,0,41,3,90,10, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index fa00ffc89ea268..07c9dd574040f6 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -118,212 +118,212 @@ const unsigned char _Py_M__zipimport[] = { 101,32,111,102,32,116,104,101,10,32,32,32,32,122,105,112, 102,105,108,101,32,116,97,114,103,101,116,101,100,46,10,32, 32,32,32,99,2,0,0,0,0,0,0,0,0,0,0,0, - 8,0,0,0,9,0,0,0,67,0,0,0,115,34,1,0, + 8,0,0,0,9,0,0,0,67,0,0,0,115,36,1,0, 0,116,0,124,1,116,1,131,2,115,14,100,1,100,0,108, 2,125,2,124,2,160,3,124,1,161,1,125,1,124,1,115, 22,116,4,100,2,124,1,100,3,141,2,130,1,116,5,114, 30,124,1,160,6,116,5,116,7,161,2,125,1,103,0,125, 3,9,0,122,7,116,8,160,9,124,1,161,1,125,4,87, - 0,110,34,4,0,116,10,116,11,102,2,121,144,1,0,1, + 0,110,35,4,0,116,10,116,11,102,2,121,75,1,0,1, 0,1,0,116,8,160,12,124,1,161,1,92,2,125,5,125, 6,124,5,124,1,107,2,114,66,116,4,100,5,124,1,100, 3,141,2,130,1,124,5,125,1,124,3,160,13,124,6,161, - 1,1,0,89,0,110,14,124,4,106,14,100,6,64,0,100, - 7,107,3,114,88,116,4,100,5,124,1,100,3,141,2,130, - 1,113,90,113,33,122,6,116,15,124,1,25,0,125,7,87, - 0,110,15,4,0,116,16,121,143,1,0,1,0,1,0,116, - 17,124,1,131,1,125,7,124,7,116,15,124,1,60,0,89, - 0,124,7,124,0,95,18,124,1,124,0,95,19,116,8,106, - 20,124,3,100,0,100,0,100,8,133,3,25,0,142,0,124, - 0,95,21,124,0,106,21,114,141,124,0,4,0,106,21,116, - 7,55,0,2,0,95,21,100,0,83,0,100,0,83,0,119, - 0,119,0,41,9,78,114,0,0,0,0,122,21,97,114,99, - 104,105,118,101,32,112,97,116,104,32,105,115,32,101,109,112, - 116,121,169,1,218,4,112,97,116,104,84,122,14,110,111,116, - 32,97,32,90,105,112,32,102,105,108,101,105,0,240,0,0, - 105,0,128,0,0,233,255,255,255,255,41,22,218,10,105,115, - 105,110,115,116,97,110,99,101,218,3,115,116,114,218,2,111, - 115,90,8,102,115,100,101,99,111,100,101,114,3,0,0,0, - 218,12,97,108,116,95,112,97,116,104,95,115,101,112,218,7, - 114,101,112,108,97,99,101,218,8,112,97,116,104,95,115,101, - 112,218,19,95,98,111,111,116,115,116,114,97,112,95,101,120, - 116,101,114,110,97,108,90,10,95,112,97,116,104,95,115,116, - 97,116,218,7,79,83,69,114,114,111,114,218,10,86,97,108, - 117,101,69,114,114,111,114,90,11,95,112,97,116,104,95,115, - 112,108,105,116,218,6,97,112,112,101,110,100,90,7,115,116, - 95,109,111,100,101,218,20,95,122,105,112,95,100,105,114,101, - 99,116,111,114,121,95,99,97,99,104,101,218,8,75,101,121, - 69,114,114,111,114,218,15,95,114,101,97,100,95,100,105,114, - 101,99,116,111,114,121,218,6,95,102,105,108,101,115,218,7, - 97,114,99,104,105,118,101,218,10,95,112,97,116,104,95,106, - 111,105,110,218,6,112,114,101,102,105,120,41,8,218,4,115, - 101,108,102,114,13,0,0,0,114,17,0,0,0,114,31,0, - 0,0,90,2,115,116,90,7,100,105,114,110,97,109,101,90, - 8,98,97,115,101,110,97,109,101,218,5,102,105,108,101,115, - 114,9,0,0,0,114,9,0,0,0,114,10,0,0,0,218, - 8,95,95,105,110,105,116,95,95,64,0,0,0,115,68,0, - 0,0,10,1,8,1,10,1,4,1,12,1,4,1,12,1, - 4,2,2,1,2,1,14,1,16,1,14,3,8,1,12,1, - 4,1,14,1,14,3,12,2,2,1,2,240,2,18,12,1, - 12,1,8,1,10,1,6,1,6,1,22,2,6,1,18,1, - 4,255,2,249,2,239,122,20,122,105,112,105,109,112,111,114, - 116,101,114,46,95,95,105,110,105,116,95,95,78,99,3,0, - 0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0, - 0,0,67,0,0,0,115,90,0,0,0,116,0,160,1,100, - 1,116,2,161,2,1,0,116,3,124,0,124,1,131,2,125, - 3,124,3,100,2,117,1,114,19,124,0,103,0,102,2,83, - 0,116,4,124,0,124,1,131,2,125,4,116,5,124,0,124, - 4,131,2,114,41,100,2,124,0,106,6,155,0,116,7,155, - 0,124,4,155,0,157,3,103,1,102,2,83,0,100,2,103, - 0,102,2,83,0,41,3,97,47,2,0,0,102,105,110,100, - 95,108,111,97,100,101,114,40,102,117,108,108,110,97,109,101, - 44,32,112,97,116,104,61,78,111,110,101,41,32,45,62,32, - 115,101,108,102,44,32,115,116,114,32,111,114,32,78,111,110, - 101,46,10,10,32,32,32,32,32,32,32,32,83,101,97,114, - 99,104,32,102,111,114,32,97,32,109,111,100,117,108,101,32, - 115,112,101,99,105,102,105,101,100,32,98,121,32,39,102,117, - 108,108,110,97,109,101,39,46,32,39,102,117,108,108,110,97, - 109,101,39,32,109,117,115,116,32,98,101,32,116,104,101,10, - 32,32,32,32,32,32,32,32,102,117,108,108,121,32,113,117, - 97,108,105,102,105,101,100,32,40,100,111,116,116,101,100,41, - 32,109,111,100,117,108,101,32,110,97,109,101,46,32,73,116, - 32,114,101,116,117,114,110,115,32,116,104,101,32,122,105,112, - 105,109,112,111,114,116,101,114,10,32,32,32,32,32,32,32, - 32,105,110,115,116,97,110,99,101,32,105,116,115,101,108,102, - 32,105,102,32,116,104,101,32,109,111,100,117,108,101,32,119, - 97,115,32,102,111,117,110,100,44,32,97,32,115,116,114,105, - 110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104, - 101,10,32,32,32,32,32,32,32,32,102,117,108,108,32,112, - 97,116,104,32,110,97,109,101,32,105,102,32,105,116,39,115, - 32,112,111,115,115,105,98,108,121,32,97,32,112,111,114,116, - 105,111,110,32,111,102,32,97,32,110,97,109,101,115,112,97, - 99,101,32,112,97,99,107,97,103,101,44,10,32,32,32,32, - 32,32,32,32,111,114,32,78,111,110,101,32,111,116,104,101, - 114,119,105,115,101,46,32,84,104,101,32,111,112,116,105,111, - 110,97,108,32,39,112,97,116,104,39,32,97,114,103,117,109, - 101,110,116,32,105,115,32,105,103,110,111,114,101,100,32,45, - 45,32,105,116,39,115,10,32,32,32,32,32,32,32,32,116, - 104,101,114,101,32,102,111,114,32,99,111,109,112,97,116,105, - 98,105,108,105,116,121,32,119,105,116,104,32,116,104,101,32, - 105,109,112,111,114,116,101,114,32,112,114,111,116,111,99,111, - 108,46,10,10,32,32,32,32,32,32,32,32,68,101,112,114, - 101,99,97,116,101,100,32,115,105,110,99,101,32,80,121,116, - 104,111,110,32,51,46,49,48,46,32,85,115,101,32,102,105, - 110,100,95,115,112,101,99,40,41,32,105,110,115,116,101,97, - 100,46,10,32,32,32,32,32,32,32,32,122,102,122,105,112, - 105,109,112,111,114,116,101,114,46,102,105,110,100,95,108,111, - 97,100,101,114,40,41,32,105,115,32,100,101,112,114,101,99, - 97,116,101,100,32,97,110,100,32,115,108,97,116,101,100,32, - 102,111,114,32,114,101,109,111,118,97,108,32,105,110,32,80, - 121,116,104,111,110,32,51,46,49,50,59,32,117,115,101,32, + 1,1,0,89,0,110,15,119,0,124,4,106,14,100,6,64, + 0,100,7,107,3,114,89,116,4,100,5,124,1,100,3,141, + 2,130,1,113,91,113,33,122,6,116,15,124,1,25,0,125, + 7,87,0,110,17,4,0,116,16,121,114,1,0,1,0,1, + 0,116,17,124,1,131,1,125,7,124,7,116,15,124,1,60, + 0,89,0,110,1,119,0,124,7,124,0,95,18,124,1,124, + 0,95,19,116,8,106,20,124,3,100,0,100,0,100,8,133, + 3,25,0,142,0,124,0,95,21,124,0,106,21,114,144,124, + 0,4,0,106,21,116,7,55,0,2,0,95,21,100,0,83, + 0,100,0,83,0,41,9,78,114,0,0,0,0,122,21,97, + 114,99,104,105,118,101,32,112,97,116,104,32,105,115,32,101, + 109,112,116,121,169,1,218,4,112,97,116,104,84,122,14,110, + 111,116,32,97,32,90,105,112,32,102,105,108,101,105,0,240, + 0,0,105,0,128,0,0,233,255,255,255,255,41,22,218,10, + 105,115,105,110,115,116,97,110,99,101,218,3,115,116,114,218, + 2,111,115,90,8,102,115,100,101,99,111,100,101,114,3,0, + 0,0,218,12,97,108,116,95,112,97,116,104,95,115,101,112, + 218,7,114,101,112,108,97,99,101,218,8,112,97,116,104,95, + 115,101,112,218,19,95,98,111,111,116,115,116,114,97,112,95, + 101,120,116,101,114,110,97,108,90,10,95,112,97,116,104,95, + 115,116,97,116,218,7,79,83,69,114,114,111,114,218,10,86, + 97,108,117,101,69,114,114,111,114,90,11,95,112,97,116,104, + 95,115,112,108,105,116,218,6,97,112,112,101,110,100,90,7, + 115,116,95,109,111,100,101,218,20,95,122,105,112,95,100,105, + 114,101,99,116,111,114,121,95,99,97,99,104,101,218,8,75, + 101,121,69,114,114,111,114,218,15,95,114,101,97,100,95,100, + 105,114,101,99,116,111,114,121,218,6,95,102,105,108,101,115, + 218,7,97,114,99,104,105,118,101,218,10,95,112,97,116,104, + 95,106,111,105,110,218,6,112,114,101,102,105,120,41,8,218, + 4,115,101,108,102,114,13,0,0,0,114,17,0,0,0,114, + 31,0,0,0,90,2,115,116,90,7,100,105,114,110,97,109, + 101,90,8,98,97,115,101,110,97,109,101,218,5,102,105,108, + 101,115,114,9,0,0,0,114,9,0,0,0,114,10,0,0, + 0,218,8,95,95,105,110,105,116,95,95,64,0,0,0,115, + 68,0,0,0,10,1,8,1,10,1,4,1,12,1,4,1, + 12,1,4,2,2,1,2,1,14,1,16,1,14,3,8,1, + 12,1,4,1,14,1,2,249,14,10,12,2,2,1,2,240, + 2,18,12,1,12,1,8,1,12,1,2,254,6,3,6,1, + 22,2,6,1,18,1,4,255,122,20,122,105,112,105,109,112, + 111,114,116,101,114,46,95,95,105,110,105,116,95,95,78,99, + 3,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 4,0,0,0,67,0,0,0,115,90,0,0,0,116,0,160, + 1,100,1,116,2,161,2,1,0,116,3,124,0,124,1,131, + 2,125,3,124,3,100,2,117,1,114,19,124,0,103,0,102, + 2,83,0,116,4,124,0,124,1,131,2,125,4,116,5,124, + 0,124,4,131,2,114,41,100,2,124,0,106,6,155,0,116, + 7,155,0,124,4,155,0,157,3,103,1,102,2,83,0,100, + 2,103,0,102,2,83,0,41,3,97,47,2,0,0,102,105, + 110,100,95,108,111,97,100,101,114,40,102,117,108,108,110,97, + 109,101,44,32,112,97,116,104,61,78,111,110,101,41,32,45, + 62,32,115,101,108,102,44,32,115,116,114,32,111,114,32,78, + 111,110,101,46,10,10,32,32,32,32,32,32,32,32,83,101, + 97,114,99,104,32,102,111,114,32,97,32,109,111,100,117,108, + 101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,39, + 102,117,108,108,110,97,109,101,39,46,32,39,102,117,108,108, + 110,97,109,101,39,32,109,117,115,116,32,98,101,32,116,104, + 101,10,32,32,32,32,32,32,32,32,102,117,108,108,121,32, + 113,117,97,108,105,102,105,101,100,32,40,100,111,116,116,101, + 100,41,32,109,111,100,117,108,101,32,110,97,109,101,46,32, + 73,116,32,114,101,116,117,114,110,115,32,116,104,101,32,122, + 105,112,105,109,112,111,114,116,101,114,10,32,32,32,32,32, + 32,32,32,105,110,115,116,97,110,99,101,32,105,116,115,101, + 108,102,32,105,102,32,116,104,101,32,109,111,100,117,108,101, + 32,119,97,115,32,102,111,117,110,100,44,32,97,32,115,116, + 114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32, + 116,104,101,10,32,32,32,32,32,32,32,32,102,117,108,108, + 32,112,97,116,104,32,110,97,109,101,32,105,102,32,105,116, + 39,115,32,112,111,115,115,105,98,108,121,32,97,32,112,111, + 114,116,105,111,110,32,111,102,32,97,32,110,97,109,101,115, + 112,97,99,101,32,112,97,99,107,97,103,101,44,10,32,32, + 32,32,32,32,32,32,111,114,32,78,111,110,101,32,111,116, + 104,101,114,119,105,115,101,46,32,84,104,101,32,111,112,116, + 105,111,110,97,108,32,39,112,97,116,104,39,32,97,114,103, + 117,109,101,110,116,32,105,115,32,105,103,110,111,114,101,100, + 32,45,45,32,105,116,39,115,10,32,32,32,32,32,32,32, + 32,116,104,101,114,101,32,102,111,114,32,99,111,109,112,97, + 116,105,98,105,108,105,116,121,32,119,105,116,104,32,116,104, + 101,32,105,109,112,111,114,116,101,114,32,112,114,111,116,111, + 99,111,108,46,10,10,32,32,32,32,32,32,32,32,68,101, + 112,114,101,99,97,116,101,100,32,115,105,110,99,101,32,80, + 121,116,104,111,110,32,51,46,49,48,46,32,85,115,101,32, 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, - 101,97,100,78,41,8,218,9,95,119,97,114,110,105,110,103, - 115,218,4,119,97,114,110,218,18,68,101,112,114,101,99,97, - 116,105,111,110,87,97,114,110,105,110,103,218,16,95,103,101, - 116,95,109,111,100,117,108,101,95,105,110,102,111,218,16,95, - 103,101,116,95,109,111,100,117,108,101,95,112,97,116,104,218, - 7,95,105,115,95,100,105,114,114,29,0,0,0,114,20,0, - 0,0,41,5,114,32,0,0,0,218,8,102,117,108,108,110, - 97,109,101,114,13,0,0,0,218,2,109,105,218,7,109,111, - 100,112,97,116,104,114,9,0,0,0,114,9,0,0,0,114, - 10,0,0,0,218,11,102,105,110,100,95,108,111,97,100,101, - 114,110,0,0,0,115,20,0,0,0,6,12,2,2,4,254, - 10,3,8,1,8,2,10,7,10,1,24,4,8,2,122,23, - 122,105,112,105,109,112,111,114,116,101,114,46,102,105,110,100, - 95,108,111,97,100,101,114,99,3,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,4,0,0,0,67,0,0,0, - 115,28,0,0,0,116,0,160,1,100,1,116,2,161,2,1, - 0,124,0,160,3,124,1,124,2,161,2,100,2,25,0,83, - 0,41,4,97,203,1,0,0,102,105,110,100,95,109,111,100, - 117,108,101,40,102,117,108,108,110,97,109,101,44,32,112,97, - 116,104,61,78,111,110,101,41,32,45,62,32,115,101,108,102, - 32,111,114,32,78,111,110,101,46,10,10,32,32,32,32,32, - 32,32,32,83,101,97,114,99,104,32,102,111,114,32,97,32, - 109,111,100,117,108,101,32,115,112,101,99,105,102,105,101,100, - 32,98,121,32,39,102,117,108,108,110,97,109,101,39,46,32, - 39,102,117,108,108,110,97,109,101,39,32,109,117,115,116,32, - 98,101,32,116,104,101,10,32,32,32,32,32,32,32,32,102, - 117,108,108,121,32,113,117,97,108,105,102,105,101,100,32,40, - 100,111,116,116,101,100,41,32,109,111,100,117,108,101,32,110, - 97,109,101,46,32,73,116,32,114,101,116,117,114,110,115,32, - 116,104,101,32,122,105,112,105,109,112,111,114,116,101,114,10, - 32,32,32,32,32,32,32,32,105,110,115,116,97,110,99,101, - 32,105,116,115,101,108,102,32,105,102,32,116,104,101,32,109, - 111,100,117,108,101,32,119,97,115,32,102,111,117,110,100,44, - 32,111,114,32,78,111,110,101,32,105,102,32,105,116,32,119, - 97,115,110,39,116,46,10,32,32,32,32,32,32,32,32,84, - 104,101,32,111,112,116,105,111,110,97,108,32,39,112,97,116, - 104,39,32,97,114,103,117,109,101,110,116,32,105,115,32,105, - 103,110,111,114,101,100,32,45,45,32,105,116,39,115,32,116, - 104,101,114,101,32,102,111,114,32,99,111,109,112,97,116,105, - 98,105,108,105,116,121,10,32,32,32,32,32,32,32,32,119, - 105,116,104,32,116,104,101,32,105,109,112,111,114,116,101,114, - 32,112,114,111,116,111,99,111,108,46,10,10,32,32,32,32, - 32,32,32,32,68,101,112,114,101,99,97,116,101,100,32,115, - 105,110,99,101,32,80,121,116,104,111,110,32,51,46,49,48, - 46,32,85,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,46,10,32,32,32,32,32, - 32,32,32,122,102,122,105,112,105,109,112,111,114,116,101,114, - 46,102,105,110,100,95,109,111,100,117,108,101,40,41,32,105, - 115,32,100,101,112,114,101,99,97,116,101,100,32,97,110,100, - 32,115,108,97,116,101,100,32,102,111,114,32,114,101,109,111, - 118,97,108,32,105,110,32,80,121,116,104,111,110,32,51,46, - 49,50,59,32,117,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,114,0,0,0,0, - 78,41,4,114,35,0,0,0,114,36,0,0,0,114,37,0, - 0,0,114,44,0,0,0,41,3,114,32,0,0,0,114,41, - 0,0,0,114,13,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,218,11,102,105,110,100,95,109,111, - 100,117,108,101,147,0,0,0,115,8,0,0,0,6,11,2, - 2,4,254,16,3,122,23,122,105,112,105,109,112,111,114,116, - 101,114,46,102,105,110,100,95,109,111,100,117,108,101,99,3, - 0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5, - 0,0,0,67,0,0,0,115,108,0,0,0,116,0,124,0, - 124,1,131,2,125,3,124,3,100,1,117,1,114,17,116,1, - 106,2,124,1,124,0,124,3,100,2,141,3,83,0,116,3, - 124,0,124,1,131,2,125,4,116,4,124,0,124,4,131,2, - 114,52,124,0,106,5,155,0,116,6,155,0,124,4,155,0, - 157,3,125,5,116,1,106,7,124,1,100,1,100,3,100,4, - 141,3,125,6,124,6,106,8,160,9,124,5,161,1,1,0, - 124,6,83,0,100,1,83,0,41,5,122,107,67,114,101,97, - 116,101,32,97,32,77,111,100,117,108,101,83,112,101,99,32, - 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101, - 100,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, - 32,32,32,82,101,116,117,114,110,115,32,78,111,110,101,32, - 105,102,32,116,104,101,32,109,111,100,117,108,101,32,99,97, - 110,110,111,116,32,98,101,32,102,111,117,110,100,46,10,32, - 32,32,32,32,32,32,32,78,41,1,218,10,105,115,95,112, - 97,99,107,97,103,101,84,41,3,218,4,110,97,109,101,90, - 6,108,111,97,100,101,114,114,46,0,0,0,41,10,114,38, - 0,0,0,218,10,95,98,111,111,116,115,116,114,97,112,90, - 16,115,112,101,99,95,102,114,111,109,95,108,111,97,100,101, - 114,114,39,0,0,0,114,40,0,0,0,114,29,0,0,0, - 114,20,0,0,0,90,10,77,111,100,117,108,101,83,112,101, - 99,90,26,115,117,98,109,111,100,117,108,101,95,115,101,97, - 114,99,104,95,108,111,99,97,116,105,111,110,115,114,24,0, - 0,0,41,7,114,32,0,0,0,114,41,0,0,0,90,6, - 116,97,114,103,101,116,90,11,109,111,100,117,108,101,95,105, - 110,102,111,114,43,0,0,0,114,13,0,0,0,90,4,115, - 112,101,99,114,9,0,0,0,114,9,0,0,0,114,10,0, - 0,0,218,9,102,105,110,100,95,115,112,101,99,163,0,0, - 0,115,24,0,0,0,10,5,8,1,16,1,10,7,10,1, - 18,4,8,1,2,1,6,255,12,2,4,1,4,2,122,21, - 122,105,112,105,109,112,111,114,116,101,114,46,102,105,110,100, - 95,115,112,101,99,99,2,0,0,0,0,0,0,0,0,0, - 0,0,5,0,0,0,3,0,0,0,67,0,0,0,115,20, - 0,0,0,116,0,124,0,124,1,131,2,92,3,125,2,125, - 3,125,4,124,2,83,0,41,2,122,166,103,101,116,95,99, - 111,100,101,40,102,117,108,108,110,97,109,101,41,32,45,62, - 32,99,111,100,101,32,111,98,106,101,99,116,46,10,10,32, - 32,32,32,32,32,32,32,82,101,116,117,114,110,32,116,104, - 101,32,99,111,100,101,32,111,98,106,101,99,116,32,102,111, - 114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, - 109,111,100,117,108,101,46,32,82,97,105,115,101,32,90,105, - 112,73,109,112,111,114,116,69,114,114,111,114,10,32,32,32, - 32,32,32,32,32,105,102,32,116,104,101,32,109,111,100,117, - 108,101,32,99,111,117,108,100,110,39,116,32,98,101,32,105, - 109,112,111,114,116,101,100,46,10,32,32,32,32,32,32,32, - 32,78,169,1,218,16,95,103,101,116,95,109,111,100,117,108, + 101,97,100,46,10,32,32,32,32,32,32,32,32,122,102,122, + 105,112,105,109,112,111,114,116,101,114,46,102,105,110,100,95, + 108,111,97,100,101,114,40,41,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,32,97,110,100,32,115,108,97,116,101, + 100,32,102,111,114,32,114,101,109,111,118,97,108,32,105,110, + 32,80,121,116,104,111,110,32,51,46,49,50,59,32,117,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,78,41,8,218,9,95,119,97,114,110,105, + 110,103,115,218,4,119,97,114,110,218,18,68,101,112,114,101, + 99,97,116,105,111,110,87,97,114,110,105,110,103,218,16,95, + 103,101,116,95,109,111,100,117,108,101,95,105,110,102,111,218, + 16,95,103,101,116,95,109,111,100,117,108,101,95,112,97,116, + 104,218,7,95,105,115,95,100,105,114,114,29,0,0,0,114, + 20,0,0,0,41,5,114,32,0,0,0,218,8,102,117,108, + 108,110,97,109,101,114,13,0,0,0,218,2,109,105,218,7, + 109,111,100,112,97,116,104,114,9,0,0,0,114,9,0,0, + 0,114,10,0,0,0,218,11,102,105,110,100,95,108,111,97, + 100,101,114,110,0,0,0,115,20,0,0,0,6,12,2,2, + 4,254,10,3,8,1,8,2,10,7,10,1,24,4,8,2, + 122,23,122,105,112,105,109,112,111,114,116,101,114,46,102,105, + 110,100,95,108,111,97,100,101,114,99,3,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,4,0,0,0,67,0, + 0,0,115,28,0,0,0,116,0,160,1,100,1,116,2,161, + 2,1,0,124,0,160,3,124,1,124,2,161,2,100,2,25, + 0,83,0,41,3,97,203,1,0,0,102,105,110,100,95,109, + 111,100,117,108,101,40,102,117,108,108,110,97,109,101,44,32, + 112,97,116,104,61,78,111,110,101,41,32,45,62,32,115,101, + 108,102,32,111,114,32,78,111,110,101,46,10,10,32,32,32, + 32,32,32,32,32,83,101,97,114,99,104,32,102,111,114,32, + 97,32,109,111,100,117,108,101,32,115,112,101,99,105,102,105, + 101,100,32,98,121,32,39,102,117,108,108,110,97,109,101,39, + 46,32,39,102,117,108,108,110,97,109,101,39,32,109,117,115, + 116,32,98,101,32,116,104,101,10,32,32,32,32,32,32,32, + 32,102,117,108,108,121,32,113,117,97,108,105,102,105,101,100, + 32,40,100,111,116,116,101,100,41,32,109,111,100,117,108,101, + 32,110,97,109,101,46,32,73,116,32,114,101,116,117,114,110, + 115,32,116,104,101,32,122,105,112,105,109,112,111,114,116,101, + 114,10,32,32,32,32,32,32,32,32,105,110,115,116,97,110, + 99,101,32,105,116,115,101,108,102,32,105,102,32,116,104,101, + 32,109,111,100,117,108,101,32,119,97,115,32,102,111,117,110, + 100,44,32,111,114,32,78,111,110,101,32,105,102,32,105,116, + 32,119,97,115,110,39,116,46,10,32,32,32,32,32,32,32, + 32,84,104,101,32,111,112,116,105,111,110,97,108,32,39,112, + 97,116,104,39,32,97,114,103,117,109,101,110,116,32,105,115, + 32,105,103,110,111,114,101,100,32,45,45,32,105,116,39,115, + 32,116,104,101,114,101,32,102,111,114,32,99,111,109,112,97, + 116,105,98,105,108,105,116,121,10,32,32,32,32,32,32,32, + 32,119,105,116,104,32,116,104,101,32,105,109,112,111,114,116, + 101,114,32,112,114,111,116,111,99,111,108,46,10,10,32,32, + 32,32,32,32,32,32,68,101,112,114,101,99,97,116,101,100, + 32,115,105,110,99,101,32,80,121,116,104,111,110,32,51,46, + 49,48,46,32,85,115,101,32,102,105,110,100,95,115,112,101, + 99,40,41,32,105,110,115,116,101,97,100,46,10,32,32,32, + 32,32,32,32,32,122,102,122,105,112,105,109,112,111,114,116, + 101,114,46,102,105,110,100,95,109,111,100,117,108,101,40,41, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97, + 110,100,32,115,108,97,116,101,100,32,102,111,114,32,114,101, + 109,111,118,97,108,32,105,110,32,80,121,116,104,111,110,32, + 51,46,49,50,59,32,117,115,101,32,102,105,110,100,95,115, + 112,101,99,40,41,32,105,110,115,116,101,97,100,114,0,0, + 0,0,41,4,114,35,0,0,0,114,36,0,0,0,114,37, + 0,0,0,114,44,0,0,0,41,3,114,32,0,0,0,114, + 41,0,0,0,114,13,0,0,0,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,218,11,102,105,110,100,95,109, + 111,100,117,108,101,147,0,0,0,115,8,0,0,0,6,11, + 2,2,4,254,16,3,122,23,122,105,112,105,109,112,111,114, + 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, + 3,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 5,0,0,0,67,0,0,0,115,108,0,0,0,116,0,124, + 0,124,1,131,2,125,3,124,3,100,1,117,1,114,17,116, + 1,106,2,124,1,124,0,124,3,100,2,141,3,83,0,116, + 3,124,0,124,1,131,2,125,4,116,4,124,0,124,4,131, + 2,114,52,124,0,106,5,155,0,116,6,155,0,124,4,155, + 0,157,3,125,5,116,1,106,7,124,1,100,1,100,3,100, + 4,141,3,125,6,124,6,106,8,160,9,124,5,161,1,1, + 0,124,6,83,0,100,1,83,0,41,5,122,107,67,114,101, + 97,116,101,32,97,32,77,111,100,117,108,101,83,112,101,99, + 32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105, + 101,100,32,109,111,100,117,108,101,46,10,10,32,32,32,32, + 32,32,32,32,82,101,116,117,114,110,115,32,78,111,110,101, + 32,105,102,32,116,104,101,32,109,111,100,117,108,101,32,99, + 97,110,110,111,116,32,98,101,32,102,111,117,110,100,46,10, + 32,32,32,32,32,32,32,32,78,41,1,218,10,105,115,95, + 112,97,99,107,97,103,101,84,41,3,218,4,110,97,109,101, + 90,6,108,111,97,100,101,114,114,46,0,0,0,41,10,114, + 38,0,0,0,218,10,95,98,111,111,116,115,116,114,97,112, + 90,16,115,112,101,99,95,102,114,111,109,95,108,111,97,100, + 101,114,114,39,0,0,0,114,40,0,0,0,114,29,0,0, + 0,114,20,0,0,0,90,10,77,111,100,117,108,101,83,112, + 101,99,90,26,115,117,98,109,111,100,117,108,101,95,115,101, + 97,114,99,104,95,108,111,99,97,116,105,111,110,115,114,24, + 0,0,0,41,7,114,32,0,0,0,114,41,0,0,0,90, + 6,116,97,114,103,101,116,90,11,109,111,100,117,108,101,95, + 105,110,102,111,114,43,0,0,0,114,13,0,0,0,90,4, + 115,112,101,99,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,218,9,102,105,110,100,95,115,112,101,99,163,0, + 0,0,115,24,0,0,0,10,5,8,1,16,1,10,7,10, + 1,18,4,8,1,2,1,6,255,12,2,4,1,4,2,122, + 21,122,105,112,105,109,112,111,114,116,101,114,46,102,105,110, + 100,95,115,112,101,99,99,2,0,0,0,0,0,0,0,0, + 0,0,0,5,0,0,0,3,0,0,0,67,0,0,0,115, + 20,0,0,0,116,0,124,0,124,1,131,2,92,3,125,2, + 125,3,125,4,124,2,83,0,41,1,122,166,103,101,116,95, + 99,111,100,101,40,102,117,108,108,110,97,109,101,41,32,45, + 62,32,99,111,100,101,32,111,98,106,101,99,116,46,10,10, + 32,32,32,32,32,32,32,32,82,101,116,117,114,110,32,116, + 104,101,32,99,111,100,101,32,111,98,106,101,99,116,32,102, + 111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,117,108,101,46,32,82,97,105,115,101,32,90, + 105,112,73,109,112,111,114,116,69,114,114,111,114,10,32,32, + 32,32,32,32,32,32,105,102,32,116,104,101,32,109,111,100, + 117,108,101,32,99,111,117,108,100,110,39,116,32,98,101,32, + 105,109,112,111,114,116,101,100,46,10,32,32,32,32,32,32, + 32,32,169,1,218,16,95,103,101,116,95,109,111,100,117,108, 101,95,99,111,100,101,169,5,114,32,0,0,0,114,41,0, 0,0,218,4,99,111,100,101,218,9,105,115,112,97,99,107, 97,103,101,114,43,0,0,0,114,9,0,0,0,114,9,0, @@ -336,10 +336,10 @@ const unsigned char _Py_M__zipimport[] = { 125,1,124,1,125,2,124,1,160,3,124,0,106,4,116,2, 23,0,161,1,114,29,124,1,116,5,124,0,106,4,116,2, 23,0,131,1,100,1,133,2,25,0,125,2,122,7,124,0, - 106,6,124,2,25,0,125,3,87,0,110,12,4,0,116,7, - 121,55,1,0,1,0,1,0,116,8,100,2,100,3,124,2, - 131,3,130,1,116,9,124,0,106,4,124,3,131,2,83,0, - 119,0,41,4,122,154,103,101,116,95,100,97,116,97,40,112, + 106,6,124,2,25,0,125,3,87,0,110,13,4,0,116,7, + 121,49,1,0,1,0,1,0,116,8,100,2,100,3,124,2, + 131,3,130,1,119,0,116,9,124,0,106,4,124,3,131,2, + 83,0,41,4,122,154,103,101,116,95,100,97,116,97,40,112, 97,116,104,110,97,109,101,41,32,45,62,32,115,116,114,105, 110,103,32,119,105,116,104,32,102,105,108,101,32,100,97,116, 97,46,10,10,32,32,32,32,32,32,32,32,82,101,116,117, @@ -358,12 +358,12 @@ const unsigned char _Py_M__zipimport[] = { 9,116,111,99,95,101,110,116,114,121,114,9,0,0,0,114, 9,0,0,0,114,10,0,0,0,218,8,103,101,116,95,100, 97,116,97,200,0,0,0,115,22,0,0,0,4,6,12,1, - 4,2,16,1,22,1,2,2,14,1,12,1,12,1,12,1, - 2,254,122,20,122,105,112,105,109,112,111,114,116,101,114,46, + 4,2,16,1,22,1,2,2,14,1,12,1,12,1,2,255, + 12,2,122,20,122,105,112,105,109,112,111,114,116,101,114,46, 103,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, 0,0,0,0,0,5,0,0,0,3,0,0,0,67,0,0, 0,115,20,0,0,0,116,0,124,0,124,1,131,2,92,3, - 125,2,125,3,125,4,124,4,83,0,41,2,122,165,103,101, + 125,2,125,3,125,4,124,4,83,0,41,1,122,165,103,101, 116,95,102,105,108,101,110,97,109,101,40,102,117,108,108,110, 97,109,101,41,32,45,62,32,102,105,108,101,110,97,109,101, 32,115,116,114,105,110,103,46,10,10,32,32,32,32,32,32, @@ -374,690 +374,690 @@ const unsigned char _Py_M__zipimport[] = { 116,69,114,114,111,114,10,32,32,32,32,32,32,32,32,105, 102,32,105,116,32,99,111,117,108,100,110,39,116,32,98,101, 32,105,109,112,111,114,116,101,100,46,10,32,32,32,32,32, - 32,32,32,78,114,50,0,0,0,114,52,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,218,12,103, - 101,116,95,102,105,108,101,110,97,109,101,221,0,0,0,115, - 4,0,0,0,16,8,4,1,122,24,122,105,112,105,109,112, - 111,114,116,101,114,46,103,101,116,95,102,105,108,101,110,97, - 109,101,99,2,0,0,0,0,0,0,0,0,0,0,0,6, - 0,0,0,8,0,0,0,67,0,0,0,115,126,0,0,0, - 116,0,124,0,124,1,131,2,125,2,124,2,100,1,117,0, - 114,18,116,1,100,2,124,1,155,2,157,2,124,1,100,3, - 141,2,130,1,116,2,124,0,124,1,131,2,125,3,124,2, - 114,32,116,3,160,4,124,3,100,4,161,2,125,4,110,5, - 124,3,155,0,100,5,157,2,125,4,122,7,124,0,106,5, - 124,4,25,0,125,5,87,0,110,9,4,0,116,6,121,62, - 1,0,1,0,1,0,89,0,100,1,83,0,116,7,124,0, - 106,8,124,5,131,2,160,9,161,0,83,0,119,0,41,6, - 122,253,103,101,116,95,115,111,117,114,99,101,40,102,117,108, - 108,110,97,109,101,41,32,45,62,32,115,111,117,114,99,101, - 32,115,116,114,105,110,103,46,10,10,32,32,32,32,32,32, - 32,32,82,101,116,117,114,110,32,116,104,101,32,115,111,117, - 114,99,101,32,99,111,100,101,32,102,111,114,32,116,104,101, - 32,115,112,101,99,105,102,105,101,100,32,109,111,100,117,108, - 101,46,32,82,97,105,115,101,32,90,105,112,73,109,112,111, - 114,116,69,114,114,111,114,10,32,32,32,32,32,32,32,32, - 105,102,32,116,104,101,32,109,111,100,117,108,101,32,99,111, - 117,108,100,110,39,116,32,98,101,32,102,111,117,110,100,44, - 32,114,101,116,117,114,110,32,78,111,110,101,32,105,102,32, - 116,104,101,32,97,114,99,104,105,118,101,32,100,111,101,115, - 10,32,32,32,32,32,32,32,32,99,111,110,116,97,105,110, - 32,116,104,101,32,109,111,100,117,108,101,44,32,98,117,116, - 32,104,97,115,32,110,111,32,115,111,117,114,99,101,32,102, - 111,114,32,105,116,46,10,32,32,32,32,32,32,32,32,78, - 250,18,99,97,110,39,116,32,102,105,110,100,32,109,111,100, - 117,108,101,32,169,1,114,47,0,0,0,250,11,95,95,105, - 110,105,116,95,95,46,112,121,250,3,46,112,121,41,10,114, - 38,0,0,0,114,3,0,0,0,114,39,0,0,0,114,21, - 0,0,0,114,30,0,0,0,114,28,0,0,0,114,26,0, - 0,0,114,59,0,0,0,114,29,0,0,0,218,6,100,101, - 99,111,100,101,41,6,114,32,0,0,0,114,41,0,0,0, - 114,42,0,0,0,114,13,0,0,0,218,8,102,117,108,108, - 112,97,116,104,114,61,0,0,0,114,9,0,0,0,114,9, - 0,0,0,114,10,0,0,0,218,10,103,101,116,95,115,111, - 117,114,99,101,233,0,0,0,115,26,0,0,0,10,7,8, - 1,18,1,10,2,4,1,14,1,10,2,2,2,14,1,12, - 1,6,2,16,1,2,253,122,22,122,105,112,105,109,112,111, - 114,116,101,114,46,103,101,116,95,115,111,117,114,99,101,99, - 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, - 4,0,0,0,67,0,0,0,115,40,0,0,0,116,0,124, - 0,124,1,131,2,125,2,124,2,100,1,117,0,114,18,116, - 1,100,2,124,1,155,2,157,2,124,1,100,3,141,2,130, - 1,124,2,83,0,41,4,122,171,105,115,95,112,97,99,107, - 97,103,101,40,102,117,108,108,110,97,109,101,41,32,45,62, - 32,98,111,111,108,46,10,10,32,32,32,32,32,32,32,32, - 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, - 104,101,32,109,111,100,117,108,101,32,115,112,101,99,105,102, - 105,101,100,32,98,121,32,102,117,108,108,110,97,109,101,32, - 105,115,32,97,32,112,97,99,107,97,103,101,46,10,32,32, - 32,32,32,32,32,32,82,97,105,115,101,32,90,105,112,73, - 109,112,111,114,116,69,114,114,111,114,32,105,102,32,116,104, - 101,32,109,111,100,117,108,101,32,99,111,117,108,100,110,39, - 116,32,98,101,32,102,111,117,110,100,46,10,32,32,32,32, - 32,32,32,32,78,114,64,0,0,0,114,65,0,0,0,41, - 2,114,38,0,0,0,114,3,0,0,0,41,3,114,32,0, - 0,0,114,41,0,0,0,114,42,0,0,0,114,9,0,0, - 0,114,9,0,0,0,114,10,0,0,0,114,46,0,0,0, - 3,1,0,0,115,8,0,0,0,10,6,8,1,18,1,4, - 1,122,22,122,105,112,105,109,112,111,114,116,101,114,46,105, - 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, - 0,0,0,0,0,0,9,0,0,0,8,0,0,0,67,0, - 0,0,115,252,0,0,0,100,1,125,2,116,0,160,1,124, - 2,116,2,161,2,1,0,116,3,124,0,124,1,131,2,92, - 3,125,3,125,4,125,5,116,4,106,5,160,6,124,1,161, - 1,125,6,124,6,100,2,117,0,115,31,116,7,124,6,116, - 8,131,2,115,40,116,8,124,1,131,1,125,6,124,6,116, - 4,106,5,124,1,60,0,124,0,124,6,95,9,122,42,124, - 4,114,62,116,10,124,0,124,1,131,2,125,7,116,11,160, - 12,124,0,106,13,124,7,161,2,125,8,124,8,103,1,124, - 6,95,14,116,15,124,6,100,3,131,2,115,70,116,16,124, - 6,95,16,116,11,160,17,124,6,106,18,124,1,124,5,161, - 3,1,0,116,19,124,3,124,6,106,18,131,2,1,0,87, - 0,110,8,1,0,1,0,1,0,116,4,106,5,124,1,61, - 0,130,0,122,7,116,4,106,5,124,1,25,0,125,6,87, - 0,110,14,4,0,116,20,121,125,1,0,1,0,1,0,116, - 21,100,4,124,1,155,2,100,5,157,3,131,1,130,1,116, - 22,160,23,100,6,124,1,124,5,161,3,1,0,124,6,83, - 0,119,0,41,7,97,64,1,0,0,108,111,97,100,95,109, - 111,100,117,108,101,40,102,117,108,108,110,97,109,101,41,32, - 45,62,32,109,111,100,117,108,101,46,10,10,32,32,32,32, - 32,32,32,32,76,111,97,100,32,116,104,101,32,109,111,100, - 117,108,101,32,115,112,101,99,105,102,105,101,100,32,98,121, - 32,39,102,117,108,108,110,97,109,101,39,46,32,39,102,117, - 108,108,110,97,109,101,39,32,109,117,115,116,32,98,101,32, - 116,104,101,10,32,32,32,32,32,32,32,32,102,117,108,108, - 121,32,113,117,97,108,105,102,105,101,100,32,40,100,111,116, - 116,101,100,41,32,109,111,100,117,108,101,32,110,97,109,101, - 46,32,73,116,32,114,101,116,117,114,110,115,32,116,104,101, - 32,105,109,112,111,114,116,101,100,10,32,32,32,32,32,32, - 32,32,109,111,100,117,108,101,44,32,111,114,32,114,97,105, - 115,101,115,32,90,105,112,73,109,112,111,114,116,69,114,114, - 111,114,32,105,102,32,105,116,32,99,111,117,108,100,32,110, - 111,116,32,98,101,32,105,109,112,111,114,116,101,100,46,10, - 10,32,32,32,32,32,32,32,32,68,101,112,114,101,99,97, - 116,101,100,32,115,105,110,99,101,32,80,121,116,104,111,110, - 32,51,46,49,48,46,32,85,115,101,32,101,120,101,99,95, - 109,111,100,117,108,101,40,41,32,105,110,115,116,101,97,100, - 46,10,32,32,32,32,32,32,32,32,122,114,122,105,112,105, - 109,112,111,114,116,46,122,105,112,105,109,112,111,114,116,101, - 114,46,108,111,97,100,95,109,111,100,117,108,101,40,41,32, - 105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,110, - 100,32,115,108,97,116,101,100,32,102,111,114,32,114,101,109, - 111,118,97,108,32,105,110,32,80,121,116,104,111,110,32,51, - 46,49,50,59,32,117,115,101,32,101,120,101,99,95,109,111, - 100,117,108,101,40,41,32,105,110,115,116,101,97,100,78,218, - 12,95,95,98,117,105,108,116,105,110,115,95,95,122,14,76, - 111,97,100,101,100,32,109,111,100,117,108,101,32,122,25,32, - 110,111,116,32,102,111,117,110,100,32,105,110,32,115,121,115, - 46,109,111,100,117,108,101,115,122,30,105,109,112,111,114,116, - 32,123,125,32,35,32,108,111,97,100,101,100,32,102,114,111, - 109,32,90,105,112,32,123,125,41,24,114,35,0,0,0,114, - 36,0,0,0,114,37,0,0,0,114,51,0,0,0,218,3, - 115,121,115,218,7,109,111,100,117,108,101,115,218,3,103,101, - 116,114,15,0,0,0,218,12,95,109,111,100,117,108,101,95, - 116,121,112,101,218,10,95,95,108,111,97,100,101,114,95,95, - 114,39,0,0,0,114,21,0,0,0,114,30,0,0,0,114, - 29,0,0,0,90,8,95,95,112,97,116,104,95,95,218,7, - 104,97,115,97,116,116,114,114,71,0,0,0,90,14,95,102, - 105,120,95,117,112,95,109,111,100,117,108,101,218,8,95,95, - 100,105,99,116,95,95,218,4,101,120,101,99,114,26,0,0, - 0,218,11,73,109,112,111,114,116,69,114,114,111,114,114,48, - 0,0,0,218,16,95,118,101,114,98,111,115,101,95,109,101, - 115,115,97,103,101,41,9,114,32,0,0,0,114,41,0,0, - 0,218,3,109,115,103,114,53,0,0,0,114,54,0,0,0, - 114,43,0,0,0,90,3,109,111,100,114,13,0,0,0,114, - 69,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, - 0,0,0,218,11,108,111,97,100,95,109,111,100,117,108,101, - 16,1,0,0,115,54,0,0,0,4,9,12,2,16,1,12, - 1,18,1,8,1,10,1,6,1,2,2,4,1,10,3,14, - 1,8,1,10,2,6,1,16,1,16,1,6,1,8,1,2, - 1,2,2,14,1,12,1,16,1,14,1,4,1,2,253,122, - 23,122,105,112,105,109,112,111,114,116,101,114,46,108,111,97, - 100,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,64,0,0,0,122,10,124,0,160,0,124,1,161,1, - 115,9,87,0,100,1,83,0,87,0,110,9,4,0,116,1, - 121,31,1,0,1,0,1,0,89,0,100,1,83,0,100,2, - 100,3,108,2,109,3,125,2,1,0,124,2,124,0,124,1, - 131,2,83,0,119,0,41,4,122,204,82,101,116,117,114,110, - 32,116,104,101,32,82,101,115,111,117,114,99,101,82,101,97, - 100,101,114,32,102,111,114,32,97,32,112,97,99,107,97,103, - 101,32,105,110,32,97,32,122,105,112,32,102,105,108,101,46, - 10,10,32,32,32,32,32,32,32,32,73,102,32,39,102,117, - 108,108,110,97,109,101,39,32,105,115,32,97,32,112,97,99, - 107,97,103,101,32,119,105,116,104,105,110,32,116,104,101,32, - 122,105,112,32,102,105,108,101,44,32,114,101,116,117,114,110, - 32,116,104,101,10,32,32,32,32,32,32,32,32,39,82,101, - 115,111,117,114,99,101,82,101,97,100,101,114,39,32,111,98, - 106,101,99,116,32,102,111,114,32,116,104,101,32,112,97,99, - 107,97,103,101,46,32,32,79,116,104,101,114,119,105,115,101, - 32,114,101,116,117,114,110,32,78,111,110,101,46,10,32,32, - 32,32,32,32,32,32,78,114,0,0,0,0,41,1,218,9, - 90,105,112,82,101,97,100,101,114,41,4,114,46,0,0,0, - 114,3,0,0,0,90,17,105,109,112,111,114,116,108,105,98, - 46,114,101,97,100,101,114,115,114,84,0,0,0,41,3,114, - 32,0,0,0,114,41,0,0,0,114,84,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,218,19,103, - 101,116,95,114,101,115,111,117,114,99,101,95,114,101,97,100, - 101,114,59,1,0,0,115,18,0,0,0,2,6,10,1,6, - 1,4,255,12,2,6,1,12,1,10,1,2,253,122,31,122, - 105,112,105,109,112,111,114,116,101,114,46,103,101,116,95,114, - 101,115,111,117,114,99,101,95,114,101,97,100,101,114,99,1, - 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8, - 0,0,0,67,0,0,0,115,72,0,0,0,122,15,116,0, - 124,0,106,1,131,1,124,0,95,2,124,0,106,2,116,3, - 124,0,106,1,60,0,87,0,100,1,83,0,4,0,116,4, - 121,35,1,0,1,0,1,0,116,3,160,5,124,0,106,1, - 100,1,161,2,1,0,100,1,124,0,95,2,89,0,100,1, - 83,0,119,0,41,2,122,41,82,101,108,111,97,100,32,116, - 104,101,32,102,105,108,101,32,100,97,116,97,32,111,102,32, - 116,104,101,32,97,114,99,104,105,118,101,32,112,97,116,104, - 46,78,41,6,114,27,0,0,0,114,29,0,0,0,114,28, - 0,0,0,114,25,0,0,0,114,3,0,0,0,218,3,112, - 111,112,169,1,114,32,0,0,0,114,9,0,0,0,114,9, - 0,0,0,114,10,0,0,0,218,17,105,110,118,97,108,105, - 100,97,116,101,95,99,97,99,104,101,115,74,1,0,0,115, - 14,0,0,0,2,2,12,1,18,1,12,1,14,1,12,1, - 2,254,122,29,122,105,112,105,109,112,111,114,116,101,114,46, - 105,110,118,97,108,105,100,97,116,101,95,99,97,99,104,101, - 115,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, - 0,0,5,0,0,0,67,0,0,0,115,24,0,0,0,100, - 1,124,0,106,0,155,0,116,1,155,0,124,0,106,2,155, - 0,100,2,157,5,83,0,41,3,78,122,21,60,122,105,112, - 105,109,112,111,114,116,101,114,32,111,98,106,101,99,116,32, - 34,122,2,34,62,41,3,114,29,0,0,0,114,20,0,0, - 0,114,31,0,0,0,114,87,0,0,0,114,9,0,0,0, - 114,9,0,0,0,114,10,0,0,0,218,8,95,95,114,101, - 112,114,95,95,84,1,0,0,115,2,0,0,0,24,1,122, - 20,122,105,112,105,109,112,111,114,116,101,114,46,95,95,114, - 101,112,114,95,95,169,1,78,41,17,114,6,0,0,0,114, - 7,0,0,0,114,8,0,0,0,218,7,95,95,100,111,99, - 95,95,114,34,0,0,0,114,44,0,0,0,114,45,0,0, - 0,114,49,0,0,0,114,55,0,0,0,114,62,0,0,0, - 114,63,0,0,0,114,70,0,0,0,114,46,0,0,0,114, - 83,0,0,0,114,85,0,0,0,114,88,0,0,0,114,89, - 0,0,0,114,9,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,114,4,0,0,0,46,0,0,0, - 115,30,0,0,0,8,0,4,1,8,17,10,46,10,37,10, - 16,8,27,8,10,8,21,8,12,8,26,8,13,8,43,8, - 15,12,10,122,12,95,95,105,110,105,116,95,95,46,112,121, - 99,84,114,66,0,0,0,70,41,3,122,4,46,112,121,99, - 84,70,41,3,114,67,0,0,0,70,70,99,2,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,20,0,0,0,124,0,106,0,124,1,160, - 1,100,1,161,1,100,2,25,0,23,0,83,0,41,3,78, - 218,1,46,233,2,0,0,0,41,2,114,31,0,0,0,218, - 10,114,112,97,114,116,105,116,105,111,110,41,2,114,32,0, - 0,0,114,41,0,0,0,114,9,0,0,0,114,9,0,0, - 0,114,10,0,0,0,114,39,0,0,0,102,1,0,0,115, - 2,0,0,0,20,1,114,39,0,0,0,99,2,0,0,0, - 0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0, - 67,0,0,0,115,18,0,0,0,124,1,116,0,23,0,125, - 2,124,2,124,0,106,1,118,0,83,0,114,90,0,0,0, - 41,2,114,20,0,0,0,114,28,0,0,0,41,3,114,32, - 0,0,0,114,13,0,0,0,90,7,100,105,114,112,97,116, - 104,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, - 114,40,0,0,0,106,1,0,0,115,4,0,0,0,8,4, - 10,2,114,40,0,0,0,99,2,0,0,0,0,0,0,0, - 0,0,0,0,7,0,0,0,4,0,0,0,67,0,0,0, - 115,56,0,0,0,116,0,124,0,124,1,131,2,125,2,116, - 1,68,0,93,18,92,3,125,3,125,4,125,5,124,2,124, - 3,23,0,125,6,124,6,124,0,106,2,118,0,114,25,124, - 5,2,0,1,0,83,0,113,7,100,0,83,0,114,90,0, - 0,0,41,3,114,39,0,0,0,218,16,95,122,105,112,95, - 115,101,97,114,99,104,111,114,100,101,114,114,28,0,0,0, - 41,7,114,32,0,0,0,114,41,0,0,0,114,13,0,0, - 0,218,6,115,117,102,102,105,120,218,10,105,115,98,121,116, - 101,99,111,100,101,114,54,0,0,0,114,69,0,0,0,114, - 9,0,0,0,114,9,0,0,0,114,10,0,0,0,114,38, - 0,0,0,115,1,0,0,115,14,0,0,0,10,1,14,1, - 8,1,10,1,8,1,2,255,4,2,114,38,0,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0, - 9,0,0,0,67,0,0,0,115,226,4,0,0,122,7,116, - 0,160,1,124,0,161,1,125,1,87,0,110,16,4,0,116, - 2,144,2,121,112,1,0,1,0,1,0,116,3,100,1,124, - 0,155,2,157,2,124,0,100,2,141,2,130,1,124,1,144, - 2,143,60,1,0,122,18,124,1,160,4,116,5,11,0,100, - 3,161,2,1,0,124,1,160,6,161,0,125,2,124,1,160, - 7,116,5,161,1,125,3,87,0,110,16,4,0,116,2,144, - 2,121,111,1,0,1,0,1,0,116,3,100,4,124,0,155, - 2,157,2,124,0,100,2,141,2,130,1,116,8,124,3,131, - 1,116,5,107,3,114,78,116,3,100,4,124,0,155,2,157, - 2,124,0,100,2,141,2,130,1,124,3,100,0,100,5,133, - 2,25,0,116,9,107,3,114,201,122,12,124,1,160,4,100, - 6,100,3,161,2,1,0,124,1,160,6,161,0,125,4,87, - 0,110,16,4,0,116,2,144,2,121,110,1,0,1,0,1, - 0,116,3,100,4,124,0,155,2,157,2,124,0,100,2,141, - 2,130,1,116,10,124,4,116,11,24,0,116,5,24,0,100, - 6,131,2,125,5,122,11,124,1,160,4,124,5,161,1,1, - 0,124,1,160,7,161,0,125,6,87,0,110,16,4,0,116, - 2,144,2,121,109,1,0,1,0,1,0,116,3,100,4,124, - 0,155,2,157,2,124,0,100,2,141,2,130,1,124,6,160, - 12,116,9,161,1,125,7,124,7,100,6,107,0,114,170,116, - 3,100,7,124,0,155,2,157,2,124,0,100,2,141,2,130, - 1,124,6,124,7,124,7,116,5,23,0,133,2,25,0,125, - 3,116,8,124,3,131,1,116,5,107,3,114,193,116,3,100, - 8,124,0,155,2,157,2,124,0,100,2,141,2,130,1,124, - 4,116,8,124,6,131,1,24,0,124,7,23,0,125,2,116, - 13,124,3,100,9,100,10,133,2,25,0,131,1,125,8,116, - 13,124,3,100,10,100,11,133,2,25,0,131,1,125,9,124, - 2,124,8,107,0,114,230,116,3,100,12,124,0,155,2,157, - 2,124,0,100,2,141,2,130,1,124,2,124,9,107,0,114, - 243,116,3,100,13,124,0,155,2,157,2,124,0,100,2,141, - 2,130,1,124,2,124,8,56,0,125,2,124,2,124,9,24, - 0,125,10,124,10,100,6,107,0,144,1,114,9,116,3,100, - 14,124,0,155,2,157,2,124,0,100,2,141,2,130,1,105, - 0,125,11,100,6,125,12,122,7,124,1,160,4,124,2,161, - 1,1,0,87,0,110,16,4,0,116,2,144,2,121,108,1, - 0,1,0,1,0,116,3,100,4,124,0,155,2,157,2,124, - 0,100,2,141,2,130,1,9,0,124,1,160,7,100,16,161, - 1,125,3,116,8,124,3,131,1,100,5,107,0,144,1,114, - 54,116,14,100,17,131,1,130,1,124,3,100,0,100,5,133, - 2,25,0,100,18,107,3,144,1,114,65,144,2,113,80,116, - 8,124,3,131,1,100,16,107,3,144,1,114,76,116,14,100, - 17,131,1,130,1,116,15,124,3,100,19,100,20,133,2,25, - 0,131,1,125,13,116,15,124,3,100,20,100,9,133,2,25, - 0,131,1,125,14,116,15,124,3,100,9,100,21,133,2,25, - 0,131,1,125,15,116,15,124,3,100,21,100,10,133,2,25, - 0,131,1,125,16,116,13,124,3,100,10,100,11,133,2,25, - 0,131,1,125,17,116,13,124,3,100,11,100,22,133,2,25, - 0,131,1,125,18,116,13,124,3,100,22,100,23,133,2,25, - 0,131,1,125,4,116,15,124,3,100,23,100,24,133,2,25, - 0,131,1,125,19,116,15,124,3,100,24,100,25,133,2,25, - 0,131,1,125,20,116,15,124,3,100,25,100,26,133,2,25, - 0,131,1,125,21,116,13,124,3,100,27,100,16,133,2,25, - 0,131,1,125,22,124,19,124,20,23,0,124,21,23,0,125, - 8,124,22,124,9,107,4,144,1,114,184,116,3,100,28,124, - 0,155,2,157,2,124,0,100,2,141,2,130,1,124,22,124, - 10,55,0,125,22,122,7,124,1,160,7,124,19,161,1,125, - 23,87,0,110,16,4,0,116,2,144,2,121,107,1,0,1, - 0,1,0,116,3,100,4,124,0,155,2,157,2,124,0,100, - 2,141,2,130,1,116,8,124,23,131,1,124,19,107,3,144, - 1,114,228,116,3,100,4,124,0,155,2,157,2,124,0,100, - 2,141,2,130,1,122,25,116,8,124,1,160,7,124,8,124, - 19,24,0,161,1,131,1,124,8,124,19,24,0,107,3,144, - 1,114,252,116,3,100,4,124,0,155,2,157,2,124,0,100, - 2,141,2,130,1,87,0,110,16,4,0,116,2,144,2,121, - 106,1,0,1,0,1,0,116,3,100,4,124,0,155,2,157, - 2,124,0,100,2,141,2,130,1,124,13,100,29,64,0,144, - 2,114,24,124,23,160,16,161,0,125,23,110,24,122,7,124, - 23,160,16,100,30,161,1,125,23,87,0,110,16,4,0,116, - 17,144,2,121,105,1,0,1,0,1,0,124,23,160,16,100, - 31,161,1,160,18,116,19,161,1,125,23,89,0,124,23,160, - 20,100,32,116,21,161,2,125,23,116,22,160,23,124,0,124, - 23,161,2,125,24,124,24,124,14,124,18,124,4,124,22,124, - 15,124,16,124,17,102,8,125,25,124,25,124,11,124,23,60, - 0,124,12,100,33,55,0,125,12,144,1,113,38,87,0,100, - 0,4,0,4,0,131,3,1,0,110,9,49,0,144,2,115, - 91,119,1,1,0,1,0,1,0,89,0,1,0,116,24,160, - 25,100,34,124,12,124,0,161,3,1,0,124,11,83,0,119, - 0,119,0,119,0,119,0,119,0,119,0,119,0,119,0,41, - 35,78,122,21,99,97,110,39,116,32,111,112,101,110,32,90, - 105,112,32,102,105,108,101,58,32,114,12,0,0,0,114,93, - 0,0,0,250,21,99,97,110,39,116,32,114,101,97,100,32, - 90,105,112,32,102,105,108,101,58,32,233,4,0,0,0,114, - 0,0,0,0,122,16,110,111,116,32,97,32,90,105,112,32, - 102,105,108,101,58,32,122,18,99,111,114,114,117,112,116,32, - 90,105,112,32,102,105,108,101,58,32,233,12,0,0,0,233, - 16,0,0,0,233,20,0,0,0,122,28,98,97,100,32,99, - 101,110,116,114,97,108,32,100,105,114,101,99,116,111,114,121, - 32,115,105,122,101,58,32,122,30,98,97,100,32,99,101,110, - 116,114,97,108,32,100,105,114,101,99,116,111,114,121,32,111, - 102,102,115,101,116,58,32,122,38,98,97,100,32,99,101,110, - 116,114,97,108,32,100,105,114,101,99,116,111,114,121,32,115, - 105,122,101,32,111,114,32,111,102,102,115,101,116,58,32,84, - 233,46,0,0,0,250,27,69,79,70,32,114,101,97,100,32, - 119,104,101,114,101,32,110,111,116,32,101,120,112,101,99,116, - 101,100,115,4,0,0,0,80,75,1,2,233,8,0,0,0, - 233,10,0,0,0,233,14,0,0,0,233,24,0,0,0,233, - 28,0,0,0,233,30,0,0,0,233,32,0,0,0,233,34, - 0,0,0,233,42,0,0,0,122,25,98,97,100,32,108,111, - 99,97,108,32,104,101,97,100,101,114,32,111,102,102,115,101, - 116,58,32,105,0,8,0,0,218,5,97,115,99,105,105,90, - 6,108,97,116,105,110,49,250,1,47,114,5,0,0,0,122, - 33,122,105,112,105,109,112,111,114,116,58,32,102,111,117,110, - 100,32,123,125,32,110,97,109,101,115,32,105,110,32,123,33, - 114,125,41,26,218,3,95,105,111,218,9,111,112,101,110,95, - 99,111,100,101,114,22,0,0,0,114,3,0,0,0,218,4, - 115,101,101,107,218,20,69,78,68,95,67,69,78,84,82,65, - 76,95,68,73,82,95,83,73,90,69,90,4,116,101,108,108, - 218,4,114,101,97,100,114,58,0,0,0,218,18,83,84,82, - 73,78,71,95,69,78,68,95,65,82,67,72,73,86,69,218, - 3,109,97,120,218,15,77,65,88,95,67,79,77,77,69,78, - 84,95,76,69,78,218,5,114,102,105,110,100,114,2,0,0, - 0,218,8,69,79,70,69,114,114,111,114,114,1,0,0,0, - 114,68,0,0,0,218,18,85,110,105,99,111,100,101,68,101, - 99,111,100,101,69,114,114,111,114,218,9,116,114,97,110,115, - 108,97,116,101,218,11,99,112,52,51,55,95,116,97,98,108, - 101,114,19,0,0,0,114,20,0,0,0,114,21,0,0,0, - 114,30,0,0,0,114,48,0,0,0,114,81,0,0,0,41, - 26,114,29,0,0,0,218,2,102,112,90,15,104,101,97,100, - 101,114,95,112,111,115,105,116,105,111,110,218,6,98,117,102, - 102,101,114,218,9,102,105,108,101,95,115,105,122,101,90,17, - 109,97,120,95,99,111,109,109,101,110,116,95,115,116,97,114, - 116,218,4,100,97,116,97,90,3,112,111,115,218,11,104,101, - 97,100,101,114,95,115,105,122,101,90,13,104,101,97,100,101, - 114,95,111,102,102,115,101,116,90,10,97,114,99,95,111,102, - 102,115,101,116,114,33,0,0,0,218,5,99,111,117,110,116, - 218,5,102,108,97,103,115,218,8,99,111,109,112,114,101,115, - 115,218,4,116,105,109,101,218,4,100,97,116,101,218,3,99, - 114,99,218,9,100,97,116,97,95,115,105,122,101,218,9,110, - 97,109,101,95,115,105,122,101,218,10,101,120,116,114,97,95, - 115,105,122,101,90,12,99,111,109,109,101,110,116,95,115,105, - 122,101,218,11,102,105,108,101,95,111,102,102,115,101,116,114, - 47,0,0,0,114,13,0,0,0,218,1,116,114,9,0,0, - 0,114,9,0,0,0,114,10,0,0,0,114,27,0,0,0, - 146,1,0,0,115,238,0,0,0,2,1,14,1,14,1,18, - 1,8,2,2,1,14,1,8,1,14,1,14,1,18,1,12, - 1,18,1,16,1,2,3,12,1,12,1,14,1,10,1,2, - 1,6,255,8,2,2,1,2,255,2,1,4,255,2,2,10, - 1,12,1,14,1,10,1,2,1,6,255,10,2,8,1,10, - 1,2,1,6,255,16,2,12,1,10,1,2,1,6,255,16, - 2,16,2,16,1,8,1,18,1,8,1,18,1,8,1,8, - 1,10,1,18,1,4,2,4,2,2,1,14,1,14,1,18, - 1,2,1,10,1,14,1,8,1,18,2,4,1,14,1,8, - 1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,16, - 1,16,1,16,1,16,1,12,1,10,1,18,1,8,1,2, - 2,14,1,14,1,18,1,14,1,18,1,2,4,28,1,18, - 1,4,255,14,2,18,1,10,2,10,2,2,3,14,1,14, - 1,18,1,12,2,12,1,20,1,8,1,8,1,4,202,2, - 6,30,196,14,109,4,1,2,247,2,246,2,246,2,227,2, - 227,2,248,2,246,2,248,114,27,0,0,0,117,190,1,0, - 0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, - 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, - 31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, - 47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62, - 63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78, - 79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94, - 95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110, - 111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126, - 127,195,135,195,188,195,169,195,162,195,164,195,160,195,165,195, - 167,195,170,195,171,195,168,195,175,195,174,195,172,195,132,195, - 133,195,137,195,166,195,134,195,180,195,182,195,178,195,187,195, - 185,195,191,195,150,195,156,194,162,194,163,194,165,226,130,167, - 198,146,195,161,195,173,195,179,195,186,195,177,195,145,194,170, - 194,186,194,191,226,140,144,194,172,194,189,194,188,194,161,194, - 171,194,187,226,150,145,226,150,146,226,150,147,226,148,130,226, - 148,164,226,149,161,226,149,162,226,149,150,226,149,149,226,149, - 163,226,149,145,226,149,151,226,149,157,226,149,156,226,149,155, - 226,148,144,226,148,148,226,148,180,226,148,172,226,148,156,226, - 148,128,226,148,188,226,149,158,226,149,159,226,149,154,226,149, - 148,226,149,169,226,149,166,226,149,160,226,149,144,226,149,172, - 226,149,167,226,149,168,226,149,164,226,149,165,226,149,153,226, - 149,152,226,149,146,226,149,147,226,149,171,226,149,170,226,148, - 152,226,148,140,226,150,136,226,150,132,226,150,140,226,150,144, - 226,150,128,206,177,195,159,206,147,207,128,206,163,207,131,194, - 181,207,132,206,166,206,152,206,169,206,180,226,136,158,207,134, - 206,181,226,136,169,226,137,161,194,177,226,137,165,226,137,164, - 226,140,160,226,140,161,195,183,226,137,136,194,176,226,136,153, - 194,183,226,136,154,226,129,191,194,178,226,150,160,194,160,99, - 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, - 8,0,0,0,67,0,0,0,115,106,0,0,0,116,0,114, - 11,116,1,160,2,100,1,161,1,1,0,116,3,100,2,131, - 1,130,1,100,3,97,0,122,28,122,8,100,4,100,5,108, - 4,109,5,125,0,1,0,87,0,110,15,4,0,116,6,121, - 52,1,0,1,0,1,0,116,1,160,2,100,1,161,1,1, - 0,116,3,100,2,131,1,130,1,87,0,100,6,97,0,110, - 3,100,6,97,0,119,0,116,1,160,2,100,7,161,1,1, - 0,124,0,83,0,119,0,41,8,78,122,27,122,105,112,105, - 109,112,111,114,116,58,32,122,108,105,98,32,85,78,65,86, - 65,73,76,65,66,76,69,250,41,99,97,110,39,116,32,100, - 101,99,111,109,112,114,101,115,115,32,100,97,116,97,59,32, - 122,108,105,98,32,110,111,116,32,97,118,97,105,108,97,98, - 108,101,84,114,0,0,0,0,169,1,218,10,100,101,99,111, - 109,112,114,101,115,115,70,122,25,122,105,112,105,109,112,111, - 114,116,58,32,122,108,105,98,32,97,118,97,105,108,97,98, - 108,101,41,7,218,15,95,105,109,112,111,114,116,105,110,103, - 95,122,108,105,98,114,48,0,0,0,114,81,0,0,0,114, - 3,0,0,0,90,4,122,108,105,98,114,147,0,0,0,218, - 9,69,120,99,101,112,116,105,111,110,114,146,0,0,0,114, - 9,0,0,0,114,9,0,0,0,114,10,0,0,0,218,20, - 95,103,101,116,95,100,101,99,111,109,112,114,101,115,115,95, - 102,117,110,99,48,2,0,0,115,28,0,0,0,4,2,10, - 3,8,1,4,2,4,1,16,1,12,1,10,1,8,1,2, - 253,12,5,10,2,4,1,2,249,114,150,0,0,0,99,2, - 0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,9, - 0,0,0,67,0,0,0,115,120,1,0,0,124,1,92,8, - 125,2,125,3,125,4,125,5,125,6,125,7,125,8,125,9, - 124,4,100,1,107,0,114,18,116,0,100,2,131,1,130,1, - 116,1,160,2,124,0,161,1,143,127,125,10,122,7,124,10, - 160,3,124,6,161,1,1,0,87,0,110,15,4,0,116,4, - 121,187,1,0,1,0,1,0,116,0,100,3,124,0,155,2, - 157,2,124,0,100,4,141,2,130,1,124,10,160,5,100,5, - 161,1,125,11,116,6,124,11,131,1,100,5,107,3,114,62, - 116,7,100,6,131,1,130,1,124,11,100,0,100,7,133,2, - 25,0,100,8,107,3,114,79,116,0,100,9,124,0,155,2, - 157,2,124,0,100,4,141,2,130,1,116,8,124,11,100,10, - 100,11,133,2,25,0,131,1,125,12,116,8,124,11,100,11, - 100,5,133,2,25,0,131,1,125,13,100,5,124,12,23,0, - 124,13,23,0,125,14,124,6,124,14,55,0,125,6,122,7, - 124,10,160,3,124,6,161,1,1,0,87,0,110,15,4,0, - 116,4,121,186,1,0,1,0,1,0,116,0,100,3,124,0, - 155,2,157,2,124,0,100,4,141,2,130,1,124,10,160,5, - 124,4,161,1,125,15,116,6,124,15,131,1,124,4,107,3, - 114,143,116,4,100,12,131,1,130,1,87,0,100,0,4,0, - 4,0,131,3,1,0,110,8,49,0,115,153,119,1,1,0, - 1,0,1,0,89,0,1,0,124,3,100,1,107,2,114,164, - 124,15,83,0,122,5,116,9,131,0,125,16,87,0,110,10, - 4,0,116,10,121,185,1,0,1,0,1,0,116,0,100,13, - 131,1,130,1,124,16,124,15,100,14,131,2,83,0,119,0, - 119,0,119,0,41,15,78,114,0,0,0,0,122,18,110,101, - 103,97,116,105,118,101,32,100,97,116,97,32,115,105,122,101, - 114,98,0,0,0,114,12,0,0,0,114,110,0,0,0,114, - 104,0,0,0,114,99,0,0,0,115,4,0,0,0,80,75, - 3,4,122,23,98,97,100,32,108,111,99,97,108,32,102,105, - 108,101,32,104,101,97,100,101,114,58,32,233,26,0,0,0, - 114,109,0,0,0,122,26,122,105,112,105,109,112,111,114,116, - 58,32,99,97,110,39,116,32,114,101,97,100,32,100,97,116, - 97,114,145,0,0,0,105,241,255,255,255,41,11,114,3,0, - 0,0,114,116,0,0,0,114,117,0,0,0,114,118,0,0, - 0,114,22,0,0,0,114,120,0,0,0,114,58,0,0,0, - 114,125,0,0,0,114,1,0,0,0,114,150,0,0,0,114, - 149,0,0,0,41,17,114,29,0,0,0,114,61,0,0,0, - 90,8,100,97,116,97,112,97,116,104,114,136,0,0,0,114, - 140,0,0,0,114,131,0,0,0,114,143,0,0,0,114,137, - 0,0,0,114,138,0,0,0,114,139,0,0,0,114,129,0, - 0,0,114,130,0,0,0,114,141,0,0,0,114,142,0,0, - 0,114,133,0,0,0,90,8,114,97,119,95,100,97,116,97, - 114,147,0,0,0,114,9,0,0,0,114,9,0,0,0,114, - 10,0,0,0,114,59,0,0,0,69,2,0,0,115,72,0, - 0,0,20,1,8,1,8,1,12,2,2,2,14,1,12,1, - 18,1,10,1,12,1,8,1,16,2,18,2,16,2,16,1, - 12,1,8,1,2,1,14,1,12,1,18,1,10,1,12,1, - 8,1,2,255,28,233,8,26,4,2,2,3,10,1,12,1, - 8,1,10,1,2,254,2,243,2,240,114,59,0,0,0,99, - 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,67,0,0,0,115,16,0,0,0,116,0,124, - 0,124,1,24,0,131,1,100,1,107,1,83,0,41,2,78, - 114,5,0,0,0,41,1,218,3,97,98,115,41,2,90,2, - 116,49,90,2,116,50,114,9,0,0,0,114,9,0,0,0, - 114,10,0,0,0,218,9,95,101,113,95,109,116,105,109,101, - 115,2,0,0,115,2,0,0,0,16,2,114,153,0,0,0, - 99,5,0,0,0,0,0,0,0,0,0,0,0,14,0,0, - 0,6,0,0,0,67,0,0,0,115,254,0,0,0,124,3, - 124,2,100,1,156,2,125,5,116,0,160,1,124,4,124,3, - 124,5,161,3,125,6,124,6,100,2,64,0,100,3,107,3, - 125,7,124,7,114,63,124,6,100,4,64,0,100,3,107,3, - 125,8,116,2,106,3,100,5,107,3,114,62,124,8,115,38, - 116,2,106,3,100,6,107,2,114,62,116,4,124,0,124,2, - 131,2,125,9,124,9,100,0,117,1,114,62,116,2,160,5, - 116,0,106,6,124,9,161,2,125,10,116,0,160,7,124,4, - 124,10,124,3,124,5,161,4,1,0,110,40,116,8,124,0, - 124,2,131,2,92,2,125,11,125,12,124,11,114,103,116,9, - 116,10,124,4,100,7,100,8,133,2,25,0,131,1,124,11, - 131,2,114,93,116,10,124,4,100,8,100,9,133,2,25,0, - 131,1,124,12,107,3,114,103,116,11,160,12,100,10,124,3, - 155,2,157,2,161,1,1,0,100,0,83,0,116,13,160,14, - 124,4,100,9,100,0,133,2,25,0,161,1,125,13,116,15, - 124,13,116,16,131,2,115,125,116,17,100,11,124,1,155,2, - 100,12,157,3,131,1,130,1,124,13,83,0,41,13,78,41, - 2,114,47,0,0,0,114,13,0,0,0,114,5,0,0,0, - 114,0,0,0,0,114,93,0,0,0,90,5,110,101,118,101, - 114,90,6,97,108,119,97,121,115,114,105,0,0,0,114,100, - 0,0,0,114,101,0,0,0,122,22,98,121,116,101,99,111, - 100,101,32,105,115,32,115,116,97,108,101,32,102,111,114,32, - 122,16,99,111,109,112,105,108,101,100,32,109,111,100,117,108, - 101,32,122,21,32,105,115,32,110,111,116,32,97,32,99,111, - 100,101,32,111,98,106,101,99,116,41,18,114,21,0,0,0, - 90,13,95,99,108,97,115,115,105,102,121,95,112,121,99,218, - 4,95,105,109,112,90,21,99,104,101,99,107,95,104,97,115, - 104,95,98,97,115,101,100,95,112,121,99,115,218,15,95,103, - 101,116,95,112,121,99,95,115,111,117,114,99,101,218,11,115, - 111,117,114,99,101,95,104,97,115,104,90,17,95,82,65,87, - 95,77,65,71,73,67,95,78,85,77,66,69,82,90,18,95, - 118,97,108,105,100,97,116,101,95,104,97,115,104,95,112,121, - 99,218,29,95,103,101,116,95,109,116,105,109,101,95,97,110, - 100,95,115,105,122,101,95,111,102,95,115,111,117,114,99,101, - 114,153,0,0,0,114,2,0,0,0,114,48,0,0,0,114, - 81,0,0,0,218,7,109,97,114,115,104,97,108,90,5,108, - 111,97,100,115,114,15,0,0,0,218,10,95,99,111,100,101, - 95,116,121,112,101,218,9,84,121,112,101,69,114,114,111,114, - 41,14,114,32,0,0,0,114,60,0,0,0,114,69,0,0, - 0,114,41,0,0,0,114,132,0,0,0,90,11,101,120,99, - 95,100,101,116,97,105,108,115,114,135,0,0,0,90,10,104, - 97,115,104,95,98,97,115,101,100,90,12,99,104,101,99,107, - 95,115,111,117,114,99,101,90,12,115,111,117,114,99,101,95, - 98,121,116,101,115,114,156,0,0,0,90,12,115,111,117,114, - 99,101,95,109,116,105,109,101,90,11,115,111,117,114,99,101, - 95,115,105,122,101,114,53,0,0,0,114,9,0,0,0,114, - 9,0,0,0,114,10,0,0,0,218,15,95,117,110,109,97, - 114,115,104,97,108,95,99,111,100,101,123,2,0,0,115,72, - 0,0,0,2,2,2,1,6,254,14,5,12,2,4,1,12, - 1,10,1,2,1,2,255,8,1,2,255,10,2,8,1,4, - 1,4,1,2,1,4,254,4,5,8,1,4,255,2,128,8, - 4,6,255,4,3,22,3,18,1,2,255,4,2,8,1,4, - 255,4,2,18,2,10,1,16,1,4,1,114,161,0,0,0, + 32,32,32,114,50,0,0,0,114,52,0,0,0,114,9,0, + 0,0,114,9,0,0,0,114,10,0,0,0,218,12,103,101, + 116,95,102,105,108,101,110,97,109,101,221,0,0,0,115,4, + 0,0,0,16,8,4,1,122,24,122,105,112,105,109,112,111, + 114,116,101,114,46,103,101,116,95,102,105,108,101,110,97,109, + 101,99,2,0,0,0,0,0,0,0,0,0,0,0,6,0, + 0,0,8,0,0,0,67,0,0,0,115,126,0,0,0,116, + 0,124,0,124,1,131,2,125,2,124,2,100,1,117,0,114, + 18,116,1,100,2,124,1,155,2,157,2,124,1,100,3,141, + 2,130,1,116,2,124,0,124,1,131,2,125,3,124,2,114, + 32,116,3,160,4,124,3,100,4,161,2,125,4,110,5,124, + 3,155,0,100,5,157,2,125,4,122,7,124,0,106,5,124, + 4,25,0,125,5,87,0,110,10,4,0,116,6,121,54,1, + 0,1,0,1,0,89,0,100,1,83,0,119,0,116,7,124, + 0,106,8,124,5,131,2,160,9,161,0,83,0,41,6,122, + 253,103,101,116,95,115,111,117,114,99,101,40,102,117,108,108, + 110,97,109,101,41,32,45,62,32,115,111,117,114,99,101,32, + 115,116,114,105,110,103,46,10,10,32,32,32,32,32,32,32, + 32,82,101,116,117,114,110,32,116,104,101,32,115,111,117,114, + 99,101,32,99,111,100,101,32,102,111,114,32,116,104,101,32, + 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, + 46,32,82,97,105,115,101,32,90,105,112,73,109,112,111,114, + 116,69,114,114,111,114,10,32,32,32,32,32,32,32,32,105, + 102,32,116,104,101,32,109,111,100,117,108,101,32,99,111,117, + 108,100,110,39,116,32,98,101,32,102,111,117,110,100,44,32, + 114,101,116,117,114,110,32,78,111,110,101,32,105,102,32,116, + 104,101,32,97,114,99,104,105,118,101,32,100,111,101,115,10, + 32,32,32,32,32,32,32,32,99,111,110,116,97,105,110,32, + 116,104,101,32,109,111,100,117,108,101,44,32,98,117,116,32, + 104,97,115,32,110,111,32,115,111,117,114,99,101,32,102,111, + 114,32,105,116,46,10,32,32,32,32,32,32,32,32,78,250, + 18,99,97,110,39,116,32,102,105,110,100,32,109,111,100,117, + 108,101,32,169,1,114,47,0,0,0,250,11,95,95,105,110, + 105,116,95,95,46,112,121,250,3,46,112,121,41,10,114,38, + 0,0,0,114,3,0,0,0,114,39,0,0,0,114,21,0, + 0,0,114,30,0,0,0,114,28,0,0,0,114,26,0,0, + 0,114,59,0,0,0,114,29,0,0,0,218,6,100,101,99, + 111,100,101,41,6,114,32,0,0,0,114,41,0,0,0,114, + 42,0,0,0,114,13,0,0,0,218,8,102,117,108,108,112, + 97,116,104,114,61,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,10,0,0,0,218,10,103,101,116,95,115,111,117, + 114,99,101,233,0,0,0,115,26,0,0,0,10,7,8,1, + 18,1,10,2,4,1,14,1,10,2,2,2,14,1,12,1, + 6,2,2,254,16,3,122,22,122,105,112,105,109,112,111,114, + 116,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,67,0,0,0,115,40,0,0,0,116,0,124,0, + 124,1,131,2,125,2,124,2,100,1,117,0,114,18,116,1, + 100,2,124,1,155,2,157,2,124,1,100,3,141,2,130,1, + 124,2,83,0,41,4,122,171,105,115,95,112,97,99,107,97, + 103,101,40,102,117,108,108,110,97,109,101,41,32,45,62,32, + 98,111,111,108,46,10,10,32,32,32,32,32,32,32,32,82, + 101,116,117,114,110,32,84,114,117,101,32,105,102,32,116,104, + 101,32,109,111,100,117,108,101,32,115,112,101,99,105,102,105, + 101,100,32,98,121,32,102,117,108,108,110,97,109,101,32,105, + 115,32,97,32,112,97,99,107,97,103,101,46,10,32,32,32, + 32,32,32,32,32,82,97,105,115,101,32,90,105,112,73,109, + 112,111,114,116,69,114,114,111,114,32,105,102,32,116,104,101, + 32,109,111,100,117,108,101,32,99,111,117,108,100,110,39,116, + 32,98,101,32,102,111,117,110,100,46,10,32,32,32,32,32, + 32,32,32,78,114,64,0,0,0,114,65,0,0,0,41,2, + 114,38,0,0,0,114,3,0,0,0,41,3,114,32,0,0, + 0,114,41,0,0,0,114,42,0,0,0,114,9,0,0,0, + 114,9,0,0,0,114,10,0,0,0,114,46,0,0,0,3, + 1,0,0,115,8,0,0,0,10,6,8,1,18,1,4,1, + 122,22,122,105,112,105,109,112,111,114,116,101,114,46,105,115, + 95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,0, + 0,0,0,0,0,9,0,0,0,8,0,0,0,67,0,0, + 0,115,252,0,0,0,100,1,125,2,116,0,160,1,124,2, + 116,2,161,2,1,0,116,3,124,0,124,1,131,2,92,3, + 125,3,125,4,125,5,116,4,106,5,160,6,124,1,161,1, + 125,6,124,6,100,2,117,0,115,31,116,7,124,6,116,8, + 131,2,115,40,116,8,124,1,131,1,125,6,124,6,116,4, + 106,5,124,1,60,0,124,0,124,6,95,9,122,42,124,4, + 114,62,116,10,124,0,124,1,131,2,125,7,116,11,160,12, + 124,0,106,13,124,7,161,2,125,8,124,8,103,1,124,6, + 95,14,116,15,124,6,100,3,131,2,115,70,116,16,124,6, + 95,16,116,11,160,17,124,6,106,18,124,1,124,5,161,3, + 1,0,116,19,124,3,124,6,106,18,131,2,1,0,87,0, + 110,8,1,0,1,0,1,0,116,4,106,5,124,1,61,0, + 130,0,122,7,116,4,106,5,124,1,25,0,125,6,87,0, + 110,15,4,0,116,20,121,116,1,0,1,0,1,0,116,21, + 100,4,124,1,155,2,100,5,157,3,131,1,130,1,119,0, + 116,22,160,23,100,6,124,1,124,5,161,3,1,0,124,6, + 83,0,41,7,97,64,1,0,0,108,111,97,100,95,109,111, + 100,117,108,101,40,102,117,108,108,110,97,109,101,41,32,45, + 62,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, + 32,32,32,76,111,97,100,32,116,104,101,32,109,111,100,117, + 108,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32, + 39,102,117,108,108,110,97,109,101,39,46,32,39,102,117,108, + 108,110,97,109,101,39,32,109,117,115,116,32,98,101,32,116, + 104,101,10,32,32,32,32,32,32,32,32,102,117,108,108,121, + 32,113,117,97,108,105,102,105,101,100,32,40,100,111,116,116, + 101,100,41,32,109,111,100,117,108,101,32,110,97,109,101,46, + 32,73,116,32,114,101,116,117,114,110,115,32,116,104,101,32, + 105,109,112,111,114,116,101,100,10,32,32,32,32,32,32,32, + 32,109,111,100,117,108,101,44,32,111,114,32,114,97,105,115, + 101,115,32,90,105,112,73,109,112,111,114,116,69,114,114,111, + 114,32,105,102,32,105,116,32,99,111,117,108,100,32,110,111, + 116,32,98,101,32,105,109,112,111,114,116,101,100,46,10,10, + 32,32,32,32,32,32,32,32,68,101,112,114,101,99,97,116, + 101,100,32,115,105,110,99,101,32,80,121,116,104,111,110,32, + 51,46,49,48,46,32,85,115,101,32,101,120,101,99,95,109, + 111,100,117,108,101,40,41,32,105,110,115,116,101,97,100,46, + 10,32,32,32,32,32,32,32,32,122,114,122,105,112,105,109, + 112,111,114,116,46,122,105,112,105,109,112,111,114,116,101,114, + 46,108,111,97,100,95,109,111,100,117,108,101,40,41,32,105, + 115,32,100,101,112,114,101,99,97,116,101,100,32,97,110,100, + 32,115,108,97,116,101,100,32,102,111,114,32,114,101,109,111, + 118,97,108,32,105,110,32,80,121,116,104,111,110,32,51,46, + 49,50,59,32,117,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,78,218,12, + 95,95,98,117,105,108,116,105,110,115,95,95,122,14,76,111, + 97,100,101,100,32,109,111,100,117,108,101,32,122,25,32,110, + 111,116,32,102,111,117,110,100,32,105,110,32,115,121,115,46, + 109,111,100,117,108,101,115,122,30,105,109,112,111,114,116,32, + 123,125,32,35,32,108,111,97,100,101,100,32,102,114,111,109, + 32,90,105,112,32,123,125,41,24,114,35,0,0,0,114,36, + 0,0,0,114,37,0,0,0,114,51,0,0,0,218,3,115, + 121,115,218,7,109,111,100,117,108,101,115,218,3,103,101,116, + 114,15,0,0,0,218,12,95,109,111,100,117,108,101,95,116, + 121,112,101,218,10,95,95,108,111,97,100,101,114,95,95,114, + 39,0,0,0,114,21,0,0,0,114,30,0,0,0,114,29, + 0,0,0,90,8,95,95,112,97,116,104,95,95,218,7,104, + 97,115,97,116,116,114,114,71,0,0,0,90,14,95,102,105, + 120,95,117,112,95,109,111,100,117,108,101,218,8,95,95,100, + 105,99,116,95,95,218,4,101,120,101,99,114,26,0,0,0, + 218,11,73,109,112,111,114,116,69,114,114,111,114,114,48,0, + 0,0,218,16,95,118,101,114,98,111,115,101,95,109,101,115, + 115,97,103,101,41,9,114,32,0,0,0,114,41,0,0,0, + 218,3,109,115,103,114,53,0,0,0,114,54,0,0,0,114, + 43,0,0,0,90,3,109,111,100,114,13,0,0,0,114,69, + 0,0,0,114,9,0,0,0,114,9,0,0,0,114,10,0, + 0,0,218,11,108,111,97,100,95,109,111,100,117,108,101,16, + 1,0,0,115,54,0,0,0,4,9,12,2,16,1,12,1, + 18,1,8,1,10,1,6,1,2,2,4,1,10,3,14,1, + 8,1,10,2,6,1,16,1,16,1,6,1,8,1,2,1, + 2,2,14,1,12,1,16,1,2,255,14,2,4,1,122,23, + 122,105,112,105,109,112,111,114,116,101,114,46,108,111,97,100, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,8,0,0,0,67,0,0,0, + 115,64,0,0,0,122,10,124,0,160,0,124,1,161,1,115, + 9,87,0,100,1,83,0,87,0,110,10,4,0,116,1,121, + 20,1,0,1,0,1,0,89,0,100,1,83,0,119,0,100, + 2,100,3,108,2,109,3,125,2,1,0,124,2,124,0,124, + 1,131,2,83,0,41,4,122,204,82,101,116,117,114,110,32, + 116,104,101,32,82,101,115,111,117,114,99,101,82,101,97,100, + 101,114,32,102,111,114,32,97,32,112,97,99,107,97,103,101, + 32,105,110,32,97,32,122,105,112,32,102,105,108,101,46,10, + 10,32,32,32,32,32,32,32,32,73,102,32,39,102,117,108, + 108,110,97,109,101,39,32,105,115,32,97,32,112,97,99,107, + 97,103,101,32,119,105,116,104,105,110,32,116,104,101,32,122, + 105,112,32,102,105,108,101,44,32,114,101,116,117,114,110,32, + 116,104,101,10,32,32,32,32,32,32,32,32,39,82,101,115, + 111,117,114,99,101,82,101,97,100,101,114,39,32,111,98,106, + 101,99,116,32,102,111,114,32,116,104,101,32,112,97,99,107, + 97,103,101,46,32,32,79,116,104,101,114,119,105,115,101,32, + 114,101,116,117,114,110,32,78,111,110,101,46,10,32,32,32, + 32,32,32,32,32,78,114,0,0,0,0,41,1,218,9,90, + 105,112,82,101,97,100,101,114,41,4,114,46,0,0,0,114, + 3,0,0,0,90,17,105,109,112,111,114,116,108,105,98,46, + 114,101,97,100,101,114,115,114,84,0,0,0,41,3,114,32, + 0,0,0,114,41,0,0,0,114,84,0,0,0,114,9,0, + 0,0,114,9,0,0,0,114,10,0,0,0,218,19,103,101, + 116,95,114,101,115,111,117,114,99,101,95,114,101,97,100,101, + 114,59,1,0,0,115,18,0,0,0,2,6,10,1,6,1, + 4,255,12,2,6,1,2,255,12,2,10,1,122,31,122,105, + 112,105,109,112,111,114,116,101,114,46,103,101,116,95,114,101, + 115,111,117,114,99,101,95,114,101,97,100,101,114,99,1,0, + 0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0, + 0,0,67,0,0,0,115,72,0,0,0,122,15,116,0,124, + 0,106,1,131,1,124,0,95,2,124,0,106,2,116,3,124, + 0,106,1,60,0,87,0,100,1,83,0,4,0,116,4,121, + 35,1,0,1,0,1,0,116,3,160,5,124,0,106,1,100, + 1,161,2,1,0,105,0,124,0,95,2,89,0,100,1,83, + 0,119,0,41,2,122,41,82,101,108,111,97,100,32,116,104, + 101,32,102,105,108,101,32,100,97,116,97,32,111,102,32,116, + 104,101,32,97,114,99,104,105,118,101,32,112,97,116,104,46, + 78,41,6,114,27,0,0,0,114,29,0,0,0,114,28,0, + 0,0,114,25,0,0,0,114,3,0,0,0,218,3,112,111, + 112,169,1,114,32,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,10,0,0,0,218,17,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,74,1,0,0,115,14, + 0,0,0,2,2,12,1,18,1,12,1,14,1,12,1,2, + 254,122,29,122,105,112,105,109,112,111,114,116,101,114,46,105, + 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,67,0,0,0,115,28,0,0,0,124,0, - 160,0,100,1,100,2,161,2,125,0,124,0,160,0,100,3, - 100,2,161,2,125,0,124,0,83,0,41,4,78,115,2,0, - 0,0,13,10,243,1,0,0,0,10,243,1,0,0,0,13, - 41,1,114,19,0,0,0,41,1,218,6,115,111,117,114,99, - 101,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, - 218,23,95,110,111,114,109,97,108,105,122,101,95,108,105,110, - 101,95,101,110,100,105,110,103,115,168,2,0,0,115,6,0, - 0,0,12,1,12,1,4,1,114,165,0,0,0,99,2,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,6,0, - 0,0,67,0,0,0,115,24,0,0,0,116,0,124,1,131, - 1,125,1,116,1,124,1,124,0,100,1,100,2,100,3,141, - 4,83,0,41,4,78,114,79,0,0,0,84,41,1,90,12, - 100,111,110,116,95,105,110,104,101,114,105,116,41,2,114,165, - 0,0,0,218,7,99,111,109,112,105,108,101,41,2,114,60, - 0,0,0,114,164,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,218,15,95,99,111,109,112,105,108, - 101,95,115,111,117,114,99,101,175,2,0,0,115,4,0,0, - 0,8,1,16,1,114,167,0,0,0,99,2,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,11,0,0,0,67, - 0,0,0,115,68,0,0,0,116,0,160,1,124,0,100,1, - 63,0,100,2,23,0,124,0,100,3,63,0,100,4,64,0, - 124,0,100,5,64,0,124,1,100,6,63,0,124,1,100,3, - 63,0,100,7,64,0,124,1,100,5,64,0,100,8,20,0, - 100,9,100,9,100,9,102,9,161,1,83,0,41,10,78,233, - 9,0,0,0,105,188,7,0,0,233,5,0,0,0,233,15, - 0,0,0,233,31,0,0,0,233,11,0,0,0,233,63,0, - 0,0,114,93,0,0,0,114,14,0,0,0,41,2,114,137, - 0,0,0,90,6,109,107,116,105,109,101,41,2,218,1,100, - 114,144,0,0,0,114,9,0,0,0,114,9,0,0,0,114, - 10,0,0,0,218,14,95,112,97,114,115,101,95,100,111,115, - 116,105,109,101,181,2,0,0,115,18,0,0,0,4,1,10, - 1,10,1,6,1,6,1,10,1,10,1,6,1,6,249,114, - 175,0,0,0,99,2,0,0,0,0,0,0,0,0,0,0, - 0,6,0,0,0,10,0,0,0,67,0,0,0,115,110,0, - 0,0,122,41,124,1,100,1,100,0,133,2,25,0,100,2, - 118,0,115,11,74,0,130,1,124,1,100,0,100,1,133,2, - 25,0,125,1,124,0,106,0,124,1,25,0,125,2,124,2, - 100,3,25,0,125,3,124,2,100,4,25,0,125,4,124,2, - 100,5,25,0,125,5,116,1,124,4,124,3,131,2,124,5, - 102,2,87,0,83,0,4,0,116,2,116,3,116,4,102,3, - 121,54,1,0,1,0,1,0,89,0,100,6,83,0,119,0, - 41,7,78,114,14,0,0,0,169,2,218,1,99,218,1,111, - 114,169,0,0,0,233,6,0,0,0,233,3,0,0,0,41, - 2,114,0,0,0,0,114,0,0,0,0,41,5,114,28,0, - 0,0,114,175,0,0,0,114,26,0,0,0,218,10,73,110, - 100,101,120,69,114,114,111,114,114,160,0,0,0,41,6,114, - 32,0,0,0,114,13,0,0,0,114,61,0,0,0,114,137, - 0,0,0,114,138,0,0,0,90,17,117,110,99,111,109,112, - 114,101,115,115,101,100,95,115,105,122,101,114,9,0,0,0, - 114,9,0,0,0,114,10,0,0,0,114,157,0,0,0,194, - 2,0,0,115,22,0,0,0,2,1,20,2,12,1,10,1, - 8,3,8,1,8,1,16,1,18,1,6,1,2,255,114,157, - 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,8,0,0,0,67,0,0,0,115,80,0,0, - 0,124,1,100,1,100,0,133,2,25,0,100,2,118,0,115, - 10,74,0,130,1,124,1,100,0,100,1,133,2,25,0,125, - 1,122,7,124,0,106,0,124,1,25,0,125,2,87,0,110, - 9,4,0,116,1,121,39,1,0,1,0,1,0,89,0,100, - 0,83,0,116,2,124,0,106,3,124,2,131,2,83,0,119, - 0,41,3,78,114,14,0,0,0,114,176,0,0,0,41,4, - 114,28,0,0,0,114,26,0,0,0,114,59,0,0,0,114, - 29,0,0,0,41,3,114,32,0,0,0,114,13,0,0,0, - 114,61,0,0,0,114,9,0,0,0,114,9,0,0,0,114, - 10,0,0,0,114,155,0,0,0,213,2,0,0,115,16,0, - 0,0,20,2,12,1,2,2,14,1,12,1,6,1,12,2, - 2,253,114,155,0,0,0,99,2,0,0,0,0,0,0,0, - 0,0,0,0,14,0,0,0,11,0,0,0,67,0,0,0, - 115,14,1,0,0,116,0,124,0,124,1,131,2,125,2,100, - 0,125,3,116,1,68,0,93,100,92,3,125,4,125,5,125, - 6,124,2,124,4,23,0,125,7,116,2,106,3,100,1,124, - 0,106,4,116,5,124,7,100,2,100,3,141,5,1,0,122, - 7,124,0,106,6,124,7,25,0,125,8,87,0,110,8,4, - 0,116,7,121,134,1,0,1,0,1,0,89,0,113,9,124, - 8,100,4,25,0,125,9,116,8,124,0,106,4,124,8,131, - 2,125,10,100,0,125,11,124,5,114,89,122,10,116,9,124, - 0,124,9,124,7,124,1,124,10,131,5,125,11,87,0,110, - 24,4,0,116,10,121,133,1,0,125,12,1,0,122,8,124, - 12,125,3,87,0,89,0,100,0,125,12,126,12,110,9,100, - 0,125,12,126,12,119,1,116,11,124,9,124,10,131,2,125, - 11,124,11,100,0,117,0,114,99,113,9,124,8,100,4,25, - 0,125,9,124,11,124,6,124,9,102,3,2,0,1,0,83, - 0,124,3,114,124,100,5,124,3,155,0,157,2,125,13,116, - 12,124,13,124,1,100,6,141,2,124,3,130,2,116,12,100, - 7,124,1,155,2,157,2,124,1,100,6,141,2,130,1,119, - 0,119,0,41,8,78,122,13,116,114,121,105,110,103,32,123, - 125,123,125,123,125,114,93,0,0,0,41,1,90,9,118,101, - 114,98,111,115,105,116,121,114,0,0,0,0,122,20,109,111, - 100,117,108,101,32,108,111,97,100,32,102,97,105,108,101,100, - 58,32,114,65,0,0,0,114,64,0,0,0,41,13,114,39, - 0,0,0,114,95,0,0,0,114,48,0,0,0,114,81,0, - 0,0,114,29,0,0,0,114,20,0,0,0,114,28,0,0, - 0,114,26,0,0,0,114,59,0,0,0,114,161,0,0,0, - 114,80,0,0,0,114,167,0,0,0,114,3,0,0,0,41, - 14,114,32,0,0,0,114,41,0,0,0,114,13,0,0,0, - 90,12,105,109,112,111,114,116,95,101,114,114,111,114,114,96, - 0,0,0,114,97,0,0,0,114,54,0,0,0,114,69,0, - 0,0,114,61,0,0,0,114,43,0,0,0,114,132,0,0, - 0,114,53,0,0,0,90,3,101,120,99,114,82,0,0,0, + 0,5,0,0,0,67,0,0,0,115,24,0,0,0,100,1, + 124,0,106,0,155,0,116,1,155,0,124,0,106,2,155,0, + 100,2,157,5,83,0,41,3,78,122,21,60,122,105,112,105, + 109,112,111,114,116,101,114,32,111,98,106,101,99,116,32,34, + 122,2,34,62,41,3,114,29,0,0,0,114,20,0,0,0, + 114,31,0,0,0,114,87,0,0,0,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,218,8,95,95,114,101,112, + 114,95,95,84,1,0,0,115,2,0,0,0,24,1,122,20, + 122,105,112,105,109,112,111,114,116,101,114,46,95,95,114,101, + 112,114,95,95,169,1,78,41,17,114,6,0,0,0,114,7, + 0,0,0,114,8,0,0,0,218,7,95,95,100,111,99,95, + 95,114,34,0,0,0,114,44,0,0,0,114,45,0,0,0, + 114,49,0,0,0,114,55,0,0,0,114,62,0,0,0,114, + 63,0,0,0,114,70,0,0,0,114,46,0,0,0,114,83, + 0,0,0,114,85,0,0,0,114,88,0,0,0,114,89,0, + 0,0,114,9,0,0,0,114,9,0,0,0,114,9,0,0, + 0,114,10,0,0,0,114,4,0,0,0,46,0,0,0,115, + 30,0,0,0,8,0,4,1,8,17,10,46,10,37,10,16, + 8,27,8,10,8,21,8,12,8,26,8,13,8,43,8,15, + 12,10,122,12,95,95,105,110,105,116,95,95,46,112,121,99, + 84,114,66,0,0,0,70,41,3,122,4,46,112,121,99,84, + 70,41,3,114,67,0,0,0,70,70,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, + 0,0,0,115,20,0,0,0,124,0,106,0,124,1,160,1, + 100,1,161,1,100,2,25,0,23,0,83,0,41,3,78,218, + 1,46,233,2,0,0,0,41,2,114,31,0,0,0,218,10, + 114,112,97,114,116,105,116,105,111,110,41,2,114,32,0,0, + 0,114,41,0,0,0,114,9,0,0,0,114,9,0,0,0, + 114,10,0,0,0,114,39,0,0,0,102,1,0,0,115,2, + 0,0,0,20,1,114,39,0,0,0,99,2,0,0,0,0, + 0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,67, + 0,0,0,115,18,0,0,0,124,1,116,0,23,0,125,2, + 124,2,124,0,106,1,118,0,83,0,114,90,0,0,0,41, + 2,114,20,0,0,0,114,28,0,0,0,41,3,114,32,0, + 0,0,114,13,0,0,0,90,7,100,105,114,112,97,116,104, 114,9,0,0,0,114,9,0,0,0,114,10,0,0,0,114, - 51,0,0,0,228,2,0,0,115,58,0,0,0,10,1,4, - 1,14,1,8,1,22,1,2,1,14,1,12,1,4,1,8, - 2,12,1,4,1,4,1,2,1,20,1,14,1,16,1,8, - 128,10,2,8,1,2,3,8,1,14,1,4,2,10,1,14, - 1,18,2,2,241,2,247,114,51,0,0,0,41,46,114,91, - 0,0,0,90,26,95,102,114,111,122,101,110,95,105,109,112, - 111,114,116,108,105,98,95,101,120,116,101,114,110,97,108,114, - 21,0,0,0,114,1,0,0,0,114,2,0,0,0,90,17, - 95,102,114,111,122,101,110,95,105,109,112,111,114,116,108,105, - 98,114,48,0,0,0,114,154,0,0,0,114,116,0,0,0, - 114,158,0,0,0,114,72,0,0,0,114,137,0,0,0,114, - 35,0,0,0,90,7,95,95,97,108,108,95,95,114,20,0, - 0,0,90,15,112,97,116,104,95,115,101,112,97,114,97,116, - 111,114,115,114,18,0,0,0,114,80,0,0,0,114,3,0, - 0,0,114,25,0,0,0,218,4,116,121,112,101,114,75,0, - 0,0,114,119,0,0,0,114,121,0,0,0,114,123,0,0, - 0,90,13,95,76,111,97,100,101,114,66,97,115,105,99,115, - 114,4,0,0,0,114,95,0,0,0,114,39,0,0,0,114, - 40,0,0,0,114,38,0,0,0,114,27,0,0,0,114,128, - 0,0,0,114,148,0,0,0,114,150,0,0,0,114,59,0, - 0,0,114,153,0,0,0,114,161,0,0,0,218,8,95,95, - 99,111,100,101,95,95,114,159,0,0,0,114,165,0,0,0, - 114,167,0,0,0,114,175,0,0,0,114,157,0,0,0,114, - 155,0,0,0,114,51,0,0,0,114,9,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,218,8,60, - 109,111,100,117,108,101,62,1,0,0,0,115,90,0,0,0, - 4,0,8,16,16,1,8,1,8,1,8,1,8,1,8,1, - 8,1,8,1,8,2,6,3,14,1,16,3,4,4,8,2, - 4,2,4,1,4,1,18,2,0,127,0,127,12,50,12,1, - 2,1,2,1,4,252,8,9,8,4,8,9,8,31,2,126, - 2,254,4,29,8,5,8,21,8,46,8,8,10,40,8,5, - 8,7,8,6,8,13,8,19,12,15, + 40,0,0,0,106,1,0,0,115,4,0,0,0,8,4,10, + 2,114,40,0,0,0,99,2,0,0,0,0,0,0,0,0, + 0,0,0,7,0,0,0,4,0,0,0,67,0,0,0,115, + 56,0,0,0,116,0,124,0,124,1,131,2,125,2,116,1, + 68,0,93,18,92,3,125,3,125,4,125,5,124,2,124,3, + 23,0,125,6,124,6,124,0,106,2,118,0,114,25,124,5, + 2,0,1,0,83,0,113,7,100,0,83,0,114,90,0,0, + 0,41,3,114,39,0,0,0,218,16,95,122,105,112,95,115, + 101,97,114,99,104,111,114,100,101,114,114,28,0,0,0,41, + 7,114,32,0,0,0,114,41,0,0,0,114,13,0,0,0, + 218,6,115,117,102,102,105,120,218,10,105,115,98,121,116,101, + 99,111,100,101,114,54,0,0,0,114,69,0,0,0,114,9, + 0,0,0,114,9,0,0,0,114,10,0,0,0,114,38,0, + 0,0,115,1,0,0,115,14,0,0,0,10,1,14,1,8, + 1,10,1,8,1,2,255,4,2,114,38,0,0,0,99,1, + 0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,9, + 0,0,0,67,0,0,0,115,220,4,0,0,122,7,116,0, + 160,1,124,0,161,1,125,1,87,0,110,16,4,0,116,2, + 121,23,1,0,1,0,1,0,116,3,100,1,124,0,155,2, + 157,2,124,0,100,2,141,2,130,1,119,0,124,1,144,2, + 143,65,1,0,122,18,124,1,160,4,116,5,11,0,100,3, + 161,2,1,0,124,1,160,6,161,0,125,2,124,1,160,7, + 116,5,161,1,125,3,87,0,110,16,4,0,116,2,121,62, + 1,0,1,0,1,0,116,3,100,4,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,119,0,116,8,124,3,131,1, + 116,5,107,3,114,78,116,3,100,4,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,124,3,100,0,100,5,133,2, + 25,0,116,9,107,3,114,201,122,12,124,1,160,4,100,6, + 100,3,161,2,1,0,124,1,160,6,161,0,125,4,87,0, + 110,16,4,0,116,2,121,114,1,0,1,0,1,0,116,3, + 100,4,124,0,155,2,157,2,124,0,100,2,141,2,130,1, + 119,0,116,10,124,4,116,11,24,0,116,5,24,0,100,6, + 131,2,125,5,122,11,124,1,160,4,124,5,161,1,1,0, + 124,1,160,7,161,0,125,6,87,0,110,16,4,0,116,2, + 121,151,1,0,1,0,1,0,116,3,100,4,124,0,155,2, + 157,2,124,0,100,2,141,2,130,1,119,0,124,6,160,12, + 116,9,161,1,125,7,124,7,100,6,107,0,114,170,116,3, + 100,7,124,0,155,2,157,2,124,0,100,2,141,2,130,1, + 124,6,124,7,124,7,116,5,23,0,133,2,25,0,125,3, + 116,8,124,3,131,1,116,5,107,3,114,193,116,3,100,8, + 124,0,155,2,157,2,124,0,100,2,141,2,130,1,124,4, + 116,8,124,6,131,1,24,0,124,7,23,0,125,2,116,13, + 124,3,100,9,100,10,133,2,25,0,131,1,125,8,116,13, + 124,3,100,10,100,11,133,2,25,0,131,1,125,9,124,2, + 124,8,107,0,114,230,116,3,100,12,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,124,2,124,9,107,0,114,243, + 116,3,100,13,124,0,155,2,157,2,124,0,100,2,141,2, + 130,1,124,2,124,8,56,0,125,2,124,2,124,9,24,0, + 125,10,124,10,100,6,107,0,144,1,114,9,116,3,100,14, + 124,0,155,2,157,2,124,0,100,2,141,2,130,1,105,0, + 125,11,100,6,125,12,122,7,124,1,160,4,124,2,161,1, + 1,0,87,0,110,17,4,0,116,2,144,1,121,37,1,0, + 1,0,1,0,116,3,100,4,124,0,155,2,157,2,124,0, + 100,2,141,2,130,1,119,0,9,0,124,1,160,7,100,16, + 161,1,125,3,116,8,124,3,131,1,100,5,107,0,144,1, + 114,55,116,14,100,17,131,1,130,1,124,3,100,0,100,5, + 133,2,25,0,100,18,107,3,144,1,114,66,144,2,113,85, + 116,8,124,3,131,1,100,16,107,3,144,1,114,77,116,14, + 100,17,131,1,130,1,116,15,124,3,100,19,100,20,133,2, + 25,0,131,1,125,13,116,15,124,3,100,20,100,9,133,2, + 25,0,131,1,125,14,116,15,124,3,100,9,100,21,133,2, + 25,0,131,1,125,15,116,15,124,3,100,21,100,10,133,2, + 25,0,131,1,125,16,116,13,124,3,100,10,100,11,133,2, + 25,0,131,1,125,17,116,13,124,3,100,11,100,22,133,2, + 25,0,131,1,125,18,116,13,124,3,100,22,100,23,133,2, + 25,0,131,1,125,4,116,15,124,3,100,23,100,24,133,2, + 25,0,131,1,125,19,116,15,124,3,100,24,100,25,133,2, + 25,0,131,1,125,20,116,15,124,3,100,25,100,26,133,2, + 25,0,131,1,125,21,116,13,124,3,100,27,100,16,133,2, + 25,0,131,1,125,22,124,19,124,20,23,0,124,21,23,0, + 125,8,124,22,124,9,107,4,144,1,114,185,116,3,100,28, + 124,0,155,2,157,2,124,0,100,2,141,2,130,1,124,22, + 124,10,55,0,125,22,122,7,124,1,160,7,124,19,161,1, + 125,23,87,0,110,17,4,0,116,2,144,1,121,213,1,0, + 1,0,1,0,116,3,100,4,124,0,155,2,157,2,124,0, + 100,2,141,2,130,1,119,0,116,8,124,23,131,1,124,19, + 107,3,144,1,114,230,116,3,100,4,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,122,25,116,8,124,1,160,7, + 124,8,124,19,24,0,161,1,131,1,124,8,124,19,24,0, + 107,3,144,1,114,254,116,3,100,4,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,87,0,110,17,4,0,116,2, + 144,2,121,16,1,0,1,0,1,0,116,3,100,4,124,0, + 155,2,157,2,124,0,100,2,141,2,130,1,119,0,124,13, + 100,29,64,0,144,2,114,27,124,23,160,16,161,0,125,23, + 110,26,122,7,124,23,160,16,100,30,161,1,125,23,87,0, + 110,18,4,0,116,17,144,2,121,52,1,0,1,0,1,0, + 124,23,160,16,100,31,161,1,160,18,116,19,161,1,125,23, + 89,0,110,1,119,0,124,23,160,20,100,32,116,21,161,2, + 125,23,116,22,160,23,124,0,124,23,161,2,125,24,124,24, + 124,14,124,18,124,4,124,22,124,15,124,16,124,17,102,8, + 125,25,124,25,124,11,124,23,60,0,124,12,100,33,55,0, + 125,12,144,1,113,39,87,0,100,0,4,0,4,0,131,3, + 1,0,110,9,49,0,144,2,115,96,119,1,1,0,1,0, + 1,0,89,0,1,0,116,24,160,25,100,34,124,12,124,0, + 161,3,1,0,124,11,83,0,41,35,78,122,21,99,97,110, + 39,116,32,111,112,101,110,32,90,105,112,32,102,105,108,101, + 58,32,114,12,0,0,0,114,93,0,0,0,250,21,99,97, + 110,39,116,32,114,101,97,100,32,90,105,112,32,102,105,108, + 101,58,32,233,4,0,0,0,114,0,0,0,0,122,16,110, + 111,116,32,97,32,90,105,112,32,102,105,108,101,58,32,122, + 18,99,111,114,114,117,112,116,32,90,105,112,32,102,105,108, + 101,58,32,233,12,0,0,0,233,16,0,0,0,233,20,0, + 0,0,122,28,98,97,100,32,99,101,110,116,114,97,108,32, + 100,105,114,101,99,116,111,114,121,32,115,105,122,101,58,32, + 122,30,98,97,100,32,99,101,110,116,114,97,108,32,100,105, + 114,101,99,116,111,114,121,32,111,102,102,115,101,116,58,32, + 122,38,98,97,100,32,99,101,110,116,114,97,108,32,100,105, + 114,101,99,116,111,114,121,32,115,105,122,101,32,111,114,32, + 111,102,102,115,101,116,58,32,84,233,46,0,0,0,250,27, + 69,79,70,32,114,101,97,100,32,119,104,101,114,101,32,110, + 111,116,32,101,120,112,101,99,116,101,100,115,4,0,0,0, + 80,75,1,2,233,8,0,0,0,233,10,0,0,0,233,14, + 0,0,0,233,24,0,0,0,233,28,0,0,0,233,30,0, + 0,0,233,32,0,0,0,233,34,0,0,0,233,42,0,0, + 0,122,25,98,97,100,32,108,111,99,97,108,32,104,101,97, + 100,101,114,32,111,102,102,115,101,116,58,32,105,0,8,0, + 0,218,5,97,115,99,105,105,90,6,108,97,116,105,110,49, + 250,1,47,114,5,0,0,0,122,33,122,105,112,105,109,112, + 111,114,116,58,32,102,111,117,110,100,32,123,125,32,110,97, + 109,101,115,32,105,110,32,123,33,114,125,41,26,218,3,95, + 105,111,218,9,111,112,101,110,95,99,111,100,101,114,22,0, + 0,0,114,3,0,0,0,218,4,115,101,101,107,218,20,69, + 78,68,95,67,69,78,84,82,65,76,95,68,73,82,95,83, + 73,90,69,90,4,116,101,108,108,218,4,114,101,97,100,114, + 58,0,0,0,218,18,83,84,82,73,78,71,95,69,78,68, + 95,65,82,67,72,73,86,69,218,3,109,97,120,218,15,77, + 65,88,95,67,79,77,77,69,78,84,95,76,69,78,218,5, + 114,102,105,110,100,114,2,0,0,0,218,8,69,79,70,69, + 114,114,111,114,114,1,0,0,0,114,68,0,0,0,218,18, + 85,110,105,99,111,100,101,68,101,99,111,100,101,69,114,114, + 111,114,218,9,116,114,97,110,115,108,97,116,101,218,11,99, + 112,52,51,55,95,116,97,98,108,101,114,19,0,0,0,114, + 20,0,0,0,114,21,0,0,0,114,30,0,0,0,114,48, + 0,0,0,114,81,0,0,0,41,26,114,29,0,0,0,218, + 2,102,112,90,15,104,101,97,100,101,114,95,112,111,115,105, + 116,105,111,110,218,6,98,117,102,102,101,114,218,9,102,105, + 108,101,95,115,105,122,101,90,17,109,97,120,95,99,111,109, + 109,101,110,116,95,115,116,97,114,116,218,4,100,97,116,97, + 90,3,112,111,115,218,11,104,101,97,100,101,114,95,115,105, + 122,101,90,13,104,101,97,100,101,114,95,111,102,102,115,101, + 116,90,10,97,114,99,95,111,102,102,115,101,116,114,33,0, + 0,0,218,5,99,111,117,110,116,218,5,102,108,97,103,115, + 218,8,99,111,109,112,114,101,115,115,218,4,116,105,109,101, + 218,4,100,97,116,101,218,3,99,114,99,218,9,100,97,116, + 97,95,115,105,122,101,218,9,110,97,109,101,95,115,105,122, + 101,218,10,101,120,116,114,97,95,115,105,122,101,90,12,99, + 111,109,109,101,110,116,95,115,105,122,101,218,11,102,105,108, + 101,95,111,102,102,115,101,116,114,47,0,0,0,114,13,0, + 0,0,218,1,116,114,9,0,0,0,114,9,0,0,0,114, + 10,0,0,0,114,27,0,0,0,146,1,0,0,115,238,0, + 0,0,2,1,14,1,12,1,18,1,2,255,8,3,2,1, + 14,1,8,1,14,1,12,1,18,1,2,255,12,2,18,1, + 16,1,2,3,12,1,12,1,12,1,10,1,2,1,6,255, + 2,255,8,3,2,1,2,255,2,1,4,255,2,2,10,1, + 12,1,12,1,10,1,2,1,6,255,2,255,10,3,8,1, + 10,1,2,1,6,255,16,2,12,1,10,1,2,1,6,255, + 16,2,16,2,16,1,8,1,18,1,8,1,18,1,8,1, + 8,1,10,1,18,1,4,2,4,2,2,1,14,1,14,1, + 18,1,2,255,2,2,10,1,14,1,8,1,18,2,4,1, + 14,1,8,1,16,1,16,1,16,1,16,1,16,1,16,1, + 16,1,16,1,16,1,16,1,16,1,12,1,10,1,18,1, + 8,1,2,2,14,1,14,1,18,1,2,255,14,2,18,1, + 2,4,28,1,18,1,4,255,14,2,18,1,2,255,10,3, + 10,2,2,3,14,1,14,1,20,1,2,255,12,3,12,1, + 20,1,8,1,8,1,4,202,2,6,30,196,14,109,4,1, + 114,27,0,0,0,117,190,1,0,0,0,1,2,3,4,5, + 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, + 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, + 38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53, + 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69, + 70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85, + 86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101, + 102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117, + 118,119,120,121,122,123,124,125,126,127,195,135,195,188,195,169, + 195,162,195,164,195,160,195,165,195,167,195,170,195,171,195,168, + 195,175,195,174,195,172,195,132,195,133,195,137,195,166,195,134, + 195,180,195,182,195,178,195,187,195,185,195,191,195,150,195,156, + 194,162,194,163,194,165,226,130,167,198,146,195,161,195,173,195, + 179,195,186,195,177,195,145,194,170,194,186,194,191,226,140,144, + 194,172,194,189,194,188,194,161,194,171,194,187,226,150,145,226, + 150,146,226,150,147,226,148,130,226,148,164,226,149,161,226,149, + 162,226,149,150,226,149,149,226,149,163,226,149,145,226,149,151, + 226,149,157,226,149,156,226,149,155,226,148,144,226,148,148,226, + 148,180,226,148,172,226,148,156,226,148,128,226,148,188,226,149, + 158,226,149,159,226,149,154,226,149,148,226,149,169,226,149,166, + 226,149,160,226,149,144,226,149,172,226,149,167,226,149,168,226, + 149,164,226,149,165,226,149,153,226,149,152,226,149,146,226,149, + 147,226,149,171,226,149,170,226,148,152,226,148,140,226,150,136, + 226,150,132,226,150,140,226,150,144,226,150,128,206,177,195,159, + 206,147,207,128,206,163,207,131,194,181,207,132,206,166,206,152, + 206,169,206,180,226,136,158,207,134,206,181,226,136,169,226,137, + 161,194,177,226,137,165,226,137,164,226,140,160,226,140,161,195, + 183,226,137,136,194,176,226,136,153,194,183,226,136,154,226,129, + 191,194,178,226,150,160,194,160,99,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,8,0,0,0,67,0,0, + 0,115,106,0,0,0,116,0,114,11,116,1,160,2,100,1, + 161,1,1,0,116,3,100,2,131,1,130,1,100,3,97,0, + 122,29,122,8,100,4,100,5,108,4,109,5,125,0,1,0, + 87,0,110,16,4,0,116,6,121,38,1,0,1,0,1,0, + 116,1,160,2,100,1,161,1,1,0,116,3,100,2,131,1, + 130,1,119,0,87,0,100,6,97,0,110,3,100,6,97,0, + 119,0,116,1,160,2,100,7,161,1,1,0,124,0,83,0, + 41,8,78,122,27,122,105,112,105,109,112,111,114,116,58,32, + 122,108,105,98,32,85,78,65,86,65,73,76,65,66,76,69, + 250,41,99,97,110,39,116,32,100,101,99,111,109,112,114,101, + 115,115,32,100,97,116,97,59,32,122,108,105,98,32,110,111, + 116,32,97,118,97,105,108,97,98,108,101,84,114,0,0,0, + 0,169,1,218,10,100,101,99,111,109,112,114,101,115,115,70, + 122,25,122,105,112,105,109,112,111,114,116,58,32,122,108,105, + 98,32,97,118,97,105,108,97,98,108,101,41,7,218,15,95, + 105,109,112,111,114,116,105,110,103,95,122,108,105,98,114,48, + 0,0,0,114,81,0,0,0,114,3,0,0,0,90,4,122, + 108,105,98,114,147,0,0,0,218,9,69,120,99,101,112,116, + 105,111,110,114,146,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,10,0,0,0,218,20,95,103,101,116,95,100,101, + 99,111,109,112,114,101,115,115,95,102,117,110,99,48,2,0, + 0,115,28,0,0,0,4,2,10,3,8,1,4,2,4,1, + 16,1,12,1,10,1,8,1,2,254,2,255,12,5,10,2, + 4,1,114,150,0,0,0,99,2,0,0,0,0,0,0,0, + 0,0,0,0,17,0,0,0,9,0,0,0,67,0,0,0, + 115,120,1,0,0,124,1,92,8,125,2,125,3,125,4,125, + 5,125,6,125,7,125,8,125,9,124,4,100,1,107,0,114, + 18,116,0,100,2,131,1,130,1,116,1,160,2,124,0,161, + 1,143,129,125,10,122,7,124,10,160,3,124,6,161,1,1, + 0,87,0,110,16,4,0,116,4,121,47,1,0,1,0,1, + 0,116,0,100,3,124,0,155,2,157,2,124,0,100,4,141, + 2,130,1,119,0,124,10,160,5,100,5,161,1,125,11,116, + 6,124,11,131,1,100,5,107,3,114,63,116,7,100,6,131, + 1,130,1,124,11,100,0,100,7,133,2,25,0,100,8,107, + 3,114,80,116,0,100,9,124,0,155,2,157,2,124,0,100, + 4,141,2,130,1,116,8,124,11,100,10,100,11,133,2,25, + 0,131,1,125,12,116,8,124,11,100,11,100,5,133,2,25, + 0,131,1,125,13,100,5,124,12,23,0,124,13,23,0,125, + 14,124,6,124,14,55,0,125,6,122,7,124,10,160,3,124, + 6,161,1,1,0,87,0,110,16,4,0,116,4,121,129,1, + 0,1,0,1,0,116,0,100,3,124,0,155,2,157,2,124, + 0,100,4,141,2,130,1,119,0,124,10,160,5,124,4,161, + 1,125,15,116,6,124,15,131,1,124,4,107,3,114,145,116, + 4,100,12,131,1,130,1,87,0,100,0,4,0,4,0,131, + 3,1,0,110,8,49,0,115,155,119,1,1,0,1,0,1, + 0,89,0,1,0,124,3,100,1,107,2,114,166,124,15,83, + 0,122,5,116,9,131,0,125,16,87,0,110,11,4,0,116, + 10,121,182,1,0,1,0,1,0,116,0,100,13,131,1,130, + 1,119,0,124,16,124,15,100,14,131,2,83,0,41,15,78, + 114,0,0,0,0,122,18,110,101,103,97,116,105,118,101,32, + 100,97,116,97,32,115,105,122,101,114,98,0,0,0,114,12, + 0,0,0,114,110,0,0,0,114,104,0,0,0,114,99,0, + 0,0,115,4,0,0,0,80,75,3,4,122,23,98,97,100, + 32,108,111,99,97,108,32,102,105,108,101,32,104,101,97,100, + 101,114,58,32,233,26,0,0,0,114,109,0,0,0,122,26, + 122,105,112,105,109,112,111,114,116,58,32,99,97,110,39,116, + 32,114,101,97,100,32,100,97,116,97,114,145,0,0,0,105, + 241,255,255,255,41,11,114,3,0,0,0,114,116,0,0,0, + 114,117,0,0,0,114,118,0,0,0,114,22,0,0,0,114, + 120,0,0,0,114,58,0,0,0,114,125,0,0,0,114,1, + 0,0,0,114,150,0,0,0,114,149,0,0,0,41,17,114, + 29,0,0,0,114,61,0,0,0,90,8,100,97,116,97,112, + 97,116,104,114,136,0,0,0,114,140,0,0,0,114,131,0, + 0,0,114,143,0,0,0,114,137,0,0,0,114,138,0,0, + 0,114,139,0,0,0,114,129,0,0,0,114,130,0,0,0, + 114,141,0,0,0,114,142,0,0,0,114,133,0,0,0,90, + 8,114,97,119,95,100,97,116,97,114,147,0,0,0,114,9, + 0,0,0,114,9,0,0,0,114,10,0,0,0,114,59,0, + 0,0,69,2,0,0,115,72,0,0,0,20,1,8,1,8, + 1,12,2,2,2,14,1,12,1,18,1,2,255,10,2,12, + 1,8,1,16,2,18,2,16,2,16,1,12,1,8,1,2, + 1,14,1,12,1,18,1,2,255,10,2,12,1,8,1,2, + 255,28,233,8,26,4,2,2,3,10,1,12,1,8,1,2, + 255,10,2,114,59,0,0,0,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, + 0,115,16,0,0,0,116,0,124,0,124,1,24,0,131,1, + 100,1,107,1,83,0,41,2,78,114,5,0,0,0,41,1, + 218,3,97,98,115,41,2,90,2,116,49,90,2,116,50,114, + 9,0,0,0,114,9,0,0,0,114,10,0,0,0,218,9, + 95,101,113,95,109,116,105,109,101,115,2,0,0,115,2,0, + 0,0,16,2,114,153,0,0,0,99,5,0,0,0,0,0, + 0,0,0,0,0,0,14,0,0,0,6,0,0,0,67,0, + 0,0,115,254,0,0,0,124,3,124,2,100,1,156,2,125, + 5,116,0,160,1,124,4,124,3,124,5,161,3,125,6,124, + 6,100,2,64,0,100,3,107,3,125,7,124,7,114,63,124, + 6,100,4,64,0,100,3,107,3,125,8,116,2,106,3,100, + 5,107,3,114,62,124,8,115,38,116,2,106,3,100,6,107, + 2,114,62,116,4,124,0,124,2,131,2,125,9,124,9,100, + 0,117,1,114,62,116,2,160,5,116,0,106,6,124,9,161, + 2,125,10,116,0,160,7,124,4,124,10,124,3,124,5,161, + 4,1,0,110,40,116,8,124,0,124,2,131,2,92,2,125, + 11,125,12,124,11,114,103,116,9,116,10,124,4,100,7,100, + 8,133,2,25,0,131,1,124,11,131,2,114,93,116,10,124, + 4,100,8,100,9,133,2,25,0,131,1,124,12,107,3,114, + 103,116,11,160,12,100,10,124,3,155,2,157,2,161,1,1, + 0,100,0,83,0,116,13,160,14,124,4,100,9,100,0,133, + 2,25,0,161,1,125,13,116,15,124,13,116,16,131,2,115, + 125,116,17,100,11,124,1,155,2,100,12,157,3,131,1,130, + 1,124,13,83,0,41,13,78,41,2,114,47,0,0,0,114, + 13,0,0,0,114,5,0,0,0,114,0,0,0,0,114,93, + 0,0,0,90,5,110,101,118,101,114,90,6,97,108,119,97, + 121,115,114,105,0,0,0,114,100,0,0,0,114,101,0,0, + 0,122,22,98,121,116,101,99,111,100,101,32,105,115,32,115, + 116,97,108,101,32,102,111,114,32,122,16,99,111,109,112,105, + 108,101,100,32,109,111,100,117,108,101,32,122,21,32,105,115, + 32,110,111,116,32,97,32,99,111,100,101,32,111,98,106,101, + 99,116,41,18,114,21,0,0,0,90,13,95,99,108,97,115, + 115,105,102,121,95,112,121,99,218,4,95,105,109,112,90,21, + 99,104,101,99,107,95,104,97,115,104,95,98,97,115,101,100, + 95,112,121,99,115,218,15,95,103,101,116,95,112,121,99,95, + 115,111,117,114,99,101,218,11,115,111,117,114,99,101,95,104, + 97,115,104,90,17,95,82,65,87,95,77,65,71,73,67,95, + 78,85,77,66,69,82,90,18,95,118,97,108,105,100,97,116, + 101,95,104,97,115,104,95,112,121,99,218,29,95,103,101,116, + 95,109,116,105,109,101,95,97,110,100,95,115,105,122,101,95, + 111,102,95,115,111,117,114,99,101,114,153,0,0,0,114,2, + 0,0,0,114,48,0,0,0,114,81,0,0,0,218,7,109, + 97,114,115,104,97,108,90,5,108,111,97,100,115,114,15,0, + 0,0,218,10,95,99,111,100,101,95,116,121,112,101,218,9, + 84,121,112,101,69,114,114,111,114,41,14,114,32,0,0,0, + 114,60,0,0,0,114,69,0,0,0,114,41,0,0,0,114, + 132,0,0,0,90,11,101,120,99,95,100,101,116,97,105,108, + 115,114,135,0,0,0,90,10,104,97,115,104,95,98,97,115, + 101,100,90,12,99,104,101,99,107,95,115,111,117,114,99,101, + 90,12,115,111,117,114,99,101,95,98,121,116,101,115,114,156, + 0,0,0,90,12,115,111,117,114,99,101,95,109,116,105,109, + 101,90,11,115,111,117,114,99,101,95,115,105,122,101,114,53, + 0,0,0,114,9,0,0,0,114,9,0,0,0,114,10,0, + 0,0,218,15,95,117,110,109,97,114,115,104,97,108,95,99, + 111,100,101,123,2,0,0,115,72,0,0,0,2,2,2,1, + 6,254,14,5,12,2,4,1,12,1,10,1,2,1,2,255, + 8,1,2,255,10,2,8,1,4,1,4,1,2,1,4,254, + 4,5,8,1,4,255,2,128,8,4,6,255,4,3,22,3, + 18,1,2,255,4,2,8,1,4,255,4,2,18,2,10,1, + 16,1,4,1,114,161,0,0,0,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,4,0,0,0,67,0, + 0,0,115,28,0,0,0,124,0,160,0,100,1,100,2,161, + 2,125,0,124,0,160,0,100,3,100,2,161,2,125,0,124, + 0,83,0,41,4,78,115,2,0,0,0,13,10,243,1,0, + 0,0,10,243,1,0,0,0,13,41,1,114,19,0,0,0, + 41,1,218,6,115,111,117,114,99,101,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,218,23,95,110,111,114,109, + 97,108,105,122,101,95,108,105,110,101,95,101,110,100,105,110, + 103,115,168,2,0,0,115,6,0,0,0,12,1,12,1,4, + 1,114,165,0,0,0,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,6,0,0,0,67,0,0,0,115, + 24,0,0,0,116,0,124,1,131,1,125,1,116,1,124,1, + 124,0,100,1,100,2,100,3,141,4,83,0,41,4,78,114, + 79,0,0,0,84,41,1,90,12,100,111,110,116,95,105,110, + 104,101,114,105,116,41,2,114,165,0,0,0,218,7,99,111, + 109,112,105,108,101,41,2,114,60,0,0,0,114,164,0,0, + 0,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, + 218,15,95,99,111,109,112,105,108,101,95,115,111,117,114,99, + 101,175,2,0,0,115,4,0,0,0,8,1,16,1,114,167, + 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,11,0,0,0,67,0,0,0,115,68,0,0, + 0,116,0,160,1,124,0,100,1,63,0,100,2,23,0,124, + 0,100,3,63,0,100,4,64,0,124,0,100,5,64,0,124, + 1,100,6,63,0,124,1,100,3,63,0,100,7,64,0,124, + 1,100,5,64,0,100,8,20,0,100,9,100,9,100,9,102, + 9,161,1,83,0,41,10,78,233,9,0,0,0,105,188,7, + 0,0,233,5,0,0,0,233,15,0,0,0,233,31,0,0, + 0,233,11,0,0,0,233,63,0,0,0,114,93,0,0,0, + 114,14,0,0,0,41,2,114,137,0,0,0,90,6,109,107, + 116,105,109,101,41,2,218,1,100,114,144,0,0,0,114,9, + 0,0,0,114,9,0,0,0,114,10,0,0,0,218,14,95, + 112,97,114,115,101,95,100,111,115,116,105,109,101,181,2,0, + 0,115,18,0,0,0,4,1,10,1,10,1,6,1,6,1, + 10,1,10,1,6,1,6,249,114,175,0,0,0,99,2,0, + 0,0,0,0,0,0,0,0,0,0,6,0,0,0,10,0, + 0,0,67,0,0,0,115,110,0,0,0,122,41,124,1,100, + 1,100,0,133,2,25,0,100,2,118,0,115,11,74,0,130, + 1,124,1,100,0,100,1,133,2,25,0,125,1,124,0,106, + 0,124,1,25,0,125,2,124,2,100,3,25,0,125,3,124, + 2,100,4,25,0,125,4,124,2,100,5,25,0,125,5,116, + 1,124,4,124,3,131,2,124,5,102,2,87,0,83,0,4, + 0,116,2,116,3,116,4,102,3,121,54,1,0,1,0,1, + 0,89,0,100,6,83,0,119,0,41,7,78,114,14,0,0, + 0,169,2,218,1,99,218,1,111,114,169,0,0,0,233,6, + 0,0,0,233,3,0,0,0,41,2,114,0,0,0,0,114, + 0,0,0,0,41,5,114,28,0,0,0,114,175,0,0,0, + 114,26,0,0,0,218,10,73,110,100,101,120,69,114,114,111, + 114,114,160,0,0,0,41,6,114,32,0,0,0,114,13,0, + 0,0,114,61,0,0,0,114,137,0,0,0,114,138,0,0, + 0,90,17,117,110,99,111,109,112,114,101,115,115,101,100,95, + 115,105,122,101,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,114,157,0,0,0,194,2,0,0,115,22,0,0, + 0,2,1,20,2,12,1,10,1,8,3,8,1,8,1,16, + 1,18,1,6,1,2,255,114,157,0,0,0,99,2,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,8,0,0, + 0,67,0,0,0,115,80,0,0,0,124,1,100,1,100,0, + 133,2,25,0,100,2,118,0,115,10,74,0,130,1,124,1, + 100,0,100,1,133,2,25,0,125,1,122,7,124,0,106,0, + 124,1,25,0,125,2,87,0,110,10,4,0,116,1,121,33, + 1,0,1,0,1,0,89,0,100,0,83,0,119,0,116,2, + 124,0,106,3,124,2,131,2,83,0,41,3,78,114,14,0, + 0,0,114,176,0,0,0,41,4,114,28,0,0,0,114,26, + 0,0,0,114,59,0,0,0,114,29,0,0,0,41,3,114, + 32,0,0,0,114,13,0,0,0,114,61,0,0,0,114,9, + 0,0,0,114,9,0,0,0,114,10,0,0,0,114,155,0, + 0,0,213,2,0,0,115,16,0,0,0,20,2,12,1,2, + 2,14,1,12,1,6,1,2,255,12,3,114,155,0,0,0, + 99,2,0,0,0,0,0,0,0,0,0,0,0,14,0,0, + 0,11,0,0,0,67,0,0,0,115,14,1,0,0,116,0, + 124,0,124,1,131,2,125,2,100,0,125,3,116,1,68,0, + 93,102,92,3,125,4,125,5,125,6,124,2,124,4,23,0, + 125,7,116,2,106,3,100,1,124,0,106,4,116,5,124,7, + 100,2,100,3,141,5,1,0,122,7,124,0,106,6,124,7, + 25,0,125,8,87,0,110,9,4,0,116,7,121,45,1,0, + 1,0,1,0,89,0,113,9,119,0,124,8,100,4,25,0, + 125,9,116,8,124,0,106,4,124,8,131,2,125,10,100,0, + 125,11,124,5,114,91,122,10,116,9,124,0,124,9,124,7, + 124,1,124,10,131,5,125,11,87,0,113,96,4,0,116,10, + 121,90,1,0,125,12,1,0,122,8,124,12,125,3,87,0, + 89,0,100,0,125,12,126,12,113,96,100,0,125,12,126,12, + 119,1,119,0,116,11,124,9,124,10,131,2,125,11,124,11, + 100,0,117,0,114,101,113,9,124,8,100,4,25,0,125,9, + 124,11,124,6,124,9,102,3,2,0,1,0,83,0,124,3, + 114,126,100,5,124,3,155,0,157,2,125,13,116,12,124,13, + 124,1,100,6,141,2,124,3,130,2,116,12,100,7,124,1, + 155,2,157,2,124,1,100,6,141,2,130,1,41,8,78,122, + 13,116,114,121,105,110,103,32,123,125,123,125,123,125,114,93, + 0,0,0,41,1,90,9,118,101,114,98,111,115,105,116,121, + 114,0,0,0,0,122,20,109,111,100,117,108,101,32,108,111, + 97,100,32,102,97,105,108,101,100,58,32,114,65,0,0,0, + 114,64,0,0,0,41,13,114,39,0,0,0,114,95,0,0, + 0,114,48,0,0,0,114,81,0,0,0,114,29,0,0,0, + 114,20,0,0,0,114,28,0,0,0,114,26,0,0,0,114, + 59,0,0,0,114,161,0,0,0,114,80,0,0,0,114,167, + 0,0,0,114,3,0,0,0,41,14,114,32,0,0,0,114, + 41,0,0,0,114,13,0,0,0,90,12,105,109,112,111,114, + 116,95,101,114,114,111,114,114,96,0,0,0,114,97,0,0, + 0,114,54,0,0,0,114,69,0,0,0,114,61,0,0,0, + 114,43,0,0,0,114,132,0,0,0,114,53,0,0,0,90, + 3,101,120,99,114,82,0,0,0,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,114,51,0,0,0,228,2,0, + 0,115,58,0,0,0,10,1,4,1,14,1,8,1,22,1, + 2,1,14,1,12,1,4,1,2,255,8,3,12,1,4,1, + 4,1,2,1,20,1,14,1,16,1,8,128,2,255,10,3, + 8,1,2,3,8,1,14,1,4,2,10,1,14,1,18,2, + 114,51,0,0,0,41,46,114,91,0,0,0,90,26,95,102, + 114,111,122,101,110,95,105,109,112,111,114,116,108,105,98,95, + 101,120,116,101,114,110,97,108,114,21,0,0,0,114,1,0, + 0,0,114,2,0,0,0,90,17,95,102,114,111,122,101,110, + 95,105,109,112,111,114,116,108,105,98,114,48,0,0,0,114, + 154,0,0,0,114,116,0,0,0,114,158,0,0,0,114,72, + 0,0,0,114,137,0,0,0,114,35,0,0,0,90,7,95, + 95,97,108,108,95,95,114,20,0,0,0,90,15,112,97,116, + 104,95,115,101,112,97,114,97,116,111,114,115,114,18,0,0, + 0,114,80,0,0,0,114,3,0,0,0,114,25,0,0,0, + 218,4,116,121,112,101,114,75,0,0,0,114,119,0,0,0, + 114,121,0,0,0,114,123,0,0,0,90,13,95,76,111,97, + 100,101,114,66,97,115,105,99,115,114,4,0,0,0,114,95, + 0,0,0,114,39,0,0,0,114,40,0,0,0,114,38,0, + 0,0,114,27,0,0,0,114,128,0,0,0,114,148,0,0, + 0,114,150,0,0,0,114,59,0,0,0,114,153,0,0,0, + 114,161,0,0,0,218,8,95,95,99,111,100,101,95,95,114, + 159,0,0,0,114,165,0,0,0,114,167,0,0,0,114,175, + 0,0,0,114,157,0,0,0,114,155,0,0,0,114,51,0, + 0,0,114,9,0,0,0,114,9,0,0,0,114,9,0,0, + 0,114,10,0,0,0,218,8,60,109,111,100,117,108,101,62, + 1,0,0,0,115,90,0,0,0,4,0,8,16,16,1,8, + 1,8,1,8,1,8,1,8,1,8,1,8,1,8,2,6, + 3,14,1,16,3,4,4,8,2,4,2,4,1,4,1,18, + 2,0,127,0,127,12,50,12,1,2,1,2,1,4,252,8, + 9,8,4,8,9,8,31,2,126,2,254,4,29,8,5,8, + 21,8,46,8,8,10,40,8,5,8,7,8,6,8,13,8, + 19,12,15, }; diff --git a/Python/initconfig.c b/Python/initconfig.c index 27ae48dd3c97c8..b2986116fdc350 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -2464,7 +2464,7 @@ warnoptions_append(PyConfig *config, PyWideStringList *options, { /* config_init_warnoptions() add existing config warnoptions at the end: ensure that the new option is not already present in this list to - prevent change the options order whne config_init_warnoptions() is + prevent change the options order when config_init_warnoptions() is called twice. */ if (_PyWideStringList_Find(&config->warnoptions, option)) { /* Already present: do nothing */ diff --git a/Python/marshal.c b/Python/marshal.c index fa4ec9eb605f05..41252406060def 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -596,14 +596,18 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) { char buf[BUFSIZ]; WFILE wf; + if (PySys_Audit("marshal.dumps", "Oi", x, version) < 0) { + return; /* caller must check PyErr_Occurred() */ + } memset(&wf, 0, sizeof(wf)); wf.fp = fp; wf.ptr = wf.buf = buf; wf.end = wf.ptr + sizeof(buf); wf.error = WFERR_OK; wf.version = version; - if (w_init_refs(&wf, version)) - return; /* caller mush check PyErr_Occurred() */ + if (w_init_refs(&wf, version)) { + return; /* caller must check PyErr_Occurred() */ + } w_object(x, &wf); w_clear_refs(&wf); w_flush(&wf); @@ -1371,12 +1375,6 @@ r_object(RFILE *p) if (linetable == NULL) goto code_error; - if (PySys_Audit("code.__new__", "OOOiiiiii", - code, filename, name, argcount, posonlyargcount, - kwonlyargcount, nlocals, stacksize, flags) < 0) { - goto code_error; - } - v = (PyObject *) PyCode_NewWithPosOnlyArgs( argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags, @@ -1435,6 +1433,15 @@ read_object(RFILE *p) fprintf(stderr, "XXX readobject called with exception set\n"); return NULL; } + if (p->ptr && p->end) { + if (PySys_Audit("marshal.loads", "y#", p->ptr, (Py_ssize_t)(p->end - p->ptr)) < 0) { + return NULL; + } + } else if (p->fp || p->readable) { + if (PySys_Audit("marshal.load", NULL) < 0) { + return NULL; + } + } v = r_object(p); if (v == NULL && !PyErr_Occurred()) PyErr_SetString(PyExc_TypeError, "NULL object in marshal data for object"); @@ -1531,7 +1538,7 @@ PyMarshal_ReadObjectFromFile(FILE *fp) rf.refs = PyList_New(0); if (rf.refs == NULL) return NULL; - result = r_object(&rf); + result = read_object(&rf); Py_DECREF(rf.refs); if (rf.buf != NULL) PyMem_Free(rf.buf); @@ -1552,7 +1559,7 @@ PyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len) rf.refs = PyList_New(0); if (rf.refs == NULL) return NULL; - result = r_object(&rf); + result = read_object(&rf); Py_DECREF(rf.refs); if (rf.buf != NULL) PyMem_Free(rf.buf); @@ -1564,6 +1571,9 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) { WFILE wf; + if (PySys_Audit("marshal.dumps", "Oi", x, version) < 0) { + return NULL; + } memset(&wf, 0, sizeof(wf)); wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); if (wf.str == NULL) diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 470aba75bea969..1017a571f2b829 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -405,7 +405,7 @@ config_init_pathconfig(PyConfig *config, int compute_path_config) #undef COPY_ATTR #ifdef MS_WINDOWS - /* If a ._pth file is found: isolated and site_import are overriden */ + /* If a ._pth file is found: isolated and site_import are overridden */ if (pathconfig.isolated != -1) { config->isolated = pathconfig.isolated; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2dbebe45fd4b0b..eeaf20b4617a20 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -17,6 +17,10 @@ #include // setlocale() +#if defined(__APPLE__) +#include +#endif + #ifdef HAVE_SIGNAL_H # include // SIG_IGN #endif @@ -34,7 +38,6 @@ (PyObject_TypeCheck((op), &PyWindowsConsoleIO_Type)) #endif - #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) @@ -59,7 +62,30 @@ static void wait_for_thread_shutdown(PyThreadState *tstate); static void call_ll_exitfuncs(_PyRuntimeState *runtime); int _Py_UnhandledKeyboardInterrupt = 0; -_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; + +/* The following places the `_PyRuntime` structure in a location that can be + * found without any external information. This is meant to ease access to the + * interpreter state for various runtime debugging tools, but is *not* an + * officially supported feature */ + +#if defined(MS_WINDOWS) + +#pragma section("PyRuntime", read, write) +__declspec(allocate("PyRuntime")) + +#elif defined(__APPLE__) + +__attribute__(( + section(SEG_DATA ",PyRuntime") +)) + +#endif + +_PyRuntimeState _PyRuntime +#if defined(__linux__) && (defined(__GNUC__) || defined(__clang__)) +__attribute__ ((section (".PyRuntime"))) +#endif += _PyRuntimeState_INIT; static int runtime_initialized = 0; PyStatus @@ -1031,6 +1057,8 @@ pyinit_main_reconfigure(PyThreadState *tstate) static PyStatus init_interp_main(PyThreadState *tstate) { + extern void _PyThread_debug_deprecation(void); + assert(!_PyErr_Occurred(tstate)); PyStatus status; @@ -1132,6 +1160,9 @@ init_interp_main(PyThreadState *tstate) #endif } + // Warn about PYTHONTHREADDEBUG deprecation + _PyThread_debug_deprecation(); + assert(!_PyErr_Occurred(tstate)); return _PyStatus_OK(); diff --git a/Python/pystate.c b/Python/pystate.c index aeebd6f61c6d7f..df98eb11bb0a49 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -147,12 +147,15 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); - int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_ids.lock); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does + * not force the default allocator. */ + int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + if (reinit_interp < 0 || reinit_main_id < 0 || reinit_xidregistry < 0 diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f00e3eb0de803f..0f1794acec73ae 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2,7 +2,7 @@ /* Top level execution of Python code (including in __main__) */ /* To help control the interfaces between the startup, execution and - * shutdown code, the phases are split across separate modules (boostrap, + * shutdown code, the phases are split across separate modules (bootstrap, * pythonrun, shutdown) */ @@ -13,7 +13,8 @@ #include "pycore_ast.h" // PyAST_mod2obj #include "pycore_compile.h" // _PyAST_Compile() #include "pycore_interp.h" // PyInterpreterState.importlib -#include "pycore_object.h" // _PyDebug_PrintTotalRefs() +#include "pycore_object.h" // _PyDebug_PrintTotalRefs(), + // _PyType_GetQualName() #include "pycore_parser.h" // _PyParser_ASTFromString() #include "pycore_pyerrors.h" // _PyErr_Fetch, _Py_Offer_Suggestions #include "pycore_pylifecycle.h" // _Py_UnhandledKeyboardInterrupt @@ -942,7 +943,7 @@ print_exception(PyObject *f, PyObject *value) if (end_lineno > lineno) { end_offset = (error_line != NULL) ? line_size : -1; } - // Limit the ammount of '^' that we can display to + // Limit the amount of '^' that we can display to // the size of the text in the source line. if (error_line != NULL && end_offset > line_size + 1) { end_offset = line_size + 1; @@ -961,36 +962,37 @@ print_exception(PyObject *f, PyObject *value) /* Don't do anything else */ } else { - PyObject* moduleName; - const char *className; + PyObject* modulename; + _Py_IDENTIFIER(__module__); assert(PyExceptionClass_Check(type)); - className = PyExceptionClass_Name(type); - if (className != NULL) { - const char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } - moduleName = _PyObject_GetAttrId(type, &PyId___module__); - if (moduleName == NULL || !PyUnicode_Check(moduleName)) + modulename = _PyObject_GetAttrId(type, &PyId___module__); + if (modulename == NULL || !PyUnicode_Check(modulename)) { - Py_XDECREF(moduleName); - err = PyFile_WriteString("", f); + Py_XDECREF(modulename); + PyErr_Clear(); + err = PyFile_WriteString(".", f); } else { - if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) + if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins)) { - err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW); + err = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); err += PyFile_WriteString(".", f); } - Py_DECREF(moduleName); + Py_DECREF(modulename); } if (err == 0) { - if (className == NULL) - err = PyFile_WriteString("", f); - else - err = PyFile_WriteString(className, f); + PyObject* qualname = _PyType_GetQualName((PyTypeObject *)type); + if (qualname == NULL || !PyUnicode_Check(qualname)) { + Py_XDECREF(qualname); + PyErr_Clear(); + err = PyFile_WriteString("", f); + } + else { + err = PyFile_WriteObject(qualname, f, Py_PRINT_RAW); + Py_DECREF(qualname); + } } } if (err == 0 && (value != Py_None)) { diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index b09b8dc7a394ae..50cf340e543b40 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -61,6 +61,7 @@ static const char* _Py_stdlib_module_names[] = { "_pyio", "_queue", "_random", +"_scproxy", "_sha1", "_sha256", "_sha3", diff --git a/Python/structmember.c b/Python/structmember.c index ba88e15f938691..c7e318811d82b8 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -5,11 +5,11 @@ #include "structmember.h" // PyMemberDef PyObject * -PyMember_GetOne(const char *addr, PyMemberDef *l) +PyMember_GetOne(const char *obj_addr, PyMemberDef *l) { PyObject *v; - addr += l->offset; + const char* addr = obj_addr + l->offset; switch (l->type) { case T_BOOL: v = PyBool_FromLong(*(char*)addr); @@ -69,8 +69,13 @@ PyMember_GetOne(const char *addr, PyMemberDef *l) break; case T_OBJECT_EX: v = *(PyObject **)addr; - if (v == NULL) - PyErr_SetString(PyExc_AttributeError, l->name); + if (v == NULL) { + PyObject *obj = (PyObject *)obj_addr; + PyTypeObject *tp = Py_TYPE(obj); + PyErr_Format(PyExc_AttributeError, + "'%.200s' object has no attribute '%s'", + tp->tp_name, l->name); + } Py_XINCREF(v); break; case T_LONGLONG: diff --git a/Python/suggestions.c b/Python/suggestions.c index 6fb01f10cd37c9..4e2f9055779b27 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -149,6 +149,9 @@ calculate_suggestions(PyObject *dir, if (item_str == NULL) { return NULL; } + if (PyUnicode_CompareWithASCIIString(name, item_str) == 0) { + continue; + } // No more than 1/3 of the involved characters should need changed. Py_ssize_t max_distance = (name_size + item_size + 3) * MOVE_COST / 6; // Don't take matches we've already beaten. @@ -197,13 +200,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference // Abort if we don't have a variable name or we have an invalid one // or if we don't have a traceback to work with - if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) { + if (name == NULL || !PyUnicode_CheckExact(name) || + traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type) + ) { return NULL; } // Move to the traceback of the exception - while (traceback->tb_next != NULL) { - traceback = traceback->tb_next; + while (1) { + PyTracebackObject *next = traceback->tb_next; + if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) { + break; + } + else { + traceback = next; + } } PyFrameObject *frame = traceback->tb_frame; diff --git a/Python/symtable.c b/Python/symtable.c index 62bd1e2ec48f8a..07f9d1132c797e 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -49,6 +49,12 @@ "'%s' can not be used within an annotation" +#define LOCATION(x) \ + (x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset + +#define ST_LOCATION(x) \ + (x)->ste_lineno, (x)->ste_col_offset, (x)->ste_end_lineno, (x)->ste_end_col_offset + static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno, int col_offset, @@ -96,7 +102,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_child_free = 0; ste->ste_generator = 0; ste->ste_coroutine = 0; - ste->ste_comprehension = 0; + ste->ste_comprehension = NoComprehension; ste->ste_returns_value = 0; ste->ste_needs_class_closure = 0; ste->ste_comp_iter_target = 0; @@ -221,6 +227,7 @@ static int symtable_visit_withitem(struct symtable *st, withitem_ty item); static int symtable_visit_match_case(struct symtable *st, match_case_ty m); static int symtable_visit_pattern(struct symtable *st, pattern_ty s); static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty); +static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -1024,7 +1031,8 @@ symtable_lookup(struct symtable *st, PyObject *name) } static int -symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste) +symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste, + int lineno, int col_offset, int end_lineno, int end_col_offset) { PyObject *o; PyObject *dict; @@ -1041,10 +1049,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s /* Is it better to use 'mangled' or 'name' here? */ PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= flag; @@ -1065,10 +1071,8 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name); PyErr_RangedSyntaxLocationObject(st->st_filename, - ste->ste_lineno, - ste->ste_col_offset + 1, - ste->ste_end_lineno, - ste->ste_end_col_offset + 1); + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); goto error; } val |= DEF_COMP_ITER; @@ -1113,8 +1117,11 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s } static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) { - return symtable_add_def_helper(st, name, flag, st->st_cur); +symtable_add_def(struct symtable *st, PyObject *name, int flag, + int lineno, int col_offset, int end_lineno, int end_col_offset) +{ + return symtable_add_def_helper(st, name, flag, st->st_cur, + lineno, col_offset, end_lineno, end_col_offset); } /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. @@ -1199,7 +1206,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } switch (s->kind) { case FunctionDef_kind: - if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); @@ -1212,8 +1219,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, - s->lineno, s->col_offset, - s->end_lineno, s->end_col_offset)) + LOCATION(s))) VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); @@ -1222,7 +1228,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) break; case ClassDef_kind: { PyObject *tmp; - if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); @@ -1275,12 +1281,12 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } if (s->v.AnnAssign.simple && !symtable_add_def(st, e_name->v.Name.id, - DEF_ANNOT | DEF_LOCAL)) { + DEF_ANNOT | DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } else { if (s->v.AnnAssign.value - && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL)) { + && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL, LOCATION(e_name))) { VISIT_QUIT(st, 0); } } @@ -1377,7 +1383,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_GLOBAL)) + if (!symtable_add_def(st, name, DEF_GLOBAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1412,7 +1418,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) s->end_col_offset + 1); VISIT_QUIT(st, 0); } - if (!symtable_add_def(st, name, DEF_NONLOCAL)) + if (!symtable_add_def(st, name, DEF_NONLOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) @@ -1433,7 +1439,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.With.body); break; case AsyncFunctionDef_kind: - if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL)) + if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); if (s->v.AsyncFunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults); @@ -1508,27 +1514,25 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) if (ste->ste_type == FunctionBlock) { long target_in_scope = _PyST_GetSymbol(ste, target_name); if (target_in_scope & DEF_GLOBAL) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); } else { - if (!symtable_add_def(st, target_name, DEF_NONLOCAL)) + if (!symtable_add_def(st, target_name, DEF_NONLOCAL, LOCATION(e))) VISIT_QUIT(st, 0); } - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste); + return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste, LOCATION(e)); } /* If we find a ModuleBlock entry, add as GLOBAL */ if (ste->ste_type == ModuleBlock) { - if (!symtable_add_def(st, target_name, DEF_GLOBAL)) + if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e))) VISIT_QUIT(st, 0); - if (!symtable_record_directive(st, target_name, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset)) + if (!symtable_record_directive(st, target_name, LOCATION(e))) VISIT_QUIT(st, 0); - return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste); + return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e)); } /* Disallow usage in ClassBlock */ if (ste->ste_type == ClassBlock) { @@ -1651,6 +1655,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case YieldFrom_kind: if (!symtable_raise_if_annotation_block(st, "yield expression", e)) { @@ -1658,6 +1665,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) } VISIT(st, expr, e->v.YieldFrom.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_comprehension) { + return symtable_raise_if_comprehension_block(st, e); + } break; case Await_kind: if (!symtable_raise_if_annotation_block(st, "await expression", e)) { @@ -1707,14 +1717,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) break; case Name_kind: if (!symtable_add_def(st, e->v.Name.id, - e->v.Name.ctx == Load ? USE : DEF_LOCAL)) + e->v.Name.ctx == Load ? USE : DEF_LOCAL, LOCATION(e))) VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && _PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) + !symtable_add_def(st, __class__, USE, LOCATION(e))) VISIT_QUIT(st, 0); } break; @@ -1749,14 +1759,14 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) break; case MatchStar_kind: if (p->v.MatchStar.name) { - symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL, LOCATION(p)); } break; case MatchMapping_kind: VISIT_SEQ(st, expr, p->v.MatchMapping.keys); VISIT_SEQ(st, pattern, p->v.MatchMapping.patterns); if (p->v.MatchMapping.rest) { - symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL); + symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL, LOCATION(p)); } break; case MatchClass_kind: @@ -1769,7 +1779,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p) VISIT(st, pattern, p->v.MatchAs.pattern); } if (p->v.MatchAs.name) { - symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL); + symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL, LOCATION(p)); } break; case MatchOr_kind: @@ -1785,7 +1795,7 @@ symtable_implicit_arg(struct symtable *st, int pos) PyObject *id = PyUnicode_FromFormat(".%d", pos); if (id == NULL) return 0; - if (!symtable_add_def(st, id, DEF_PARAM)) { + if (!symtable_add_def(st, id, DEF_PARAM, ST_LOCATION(st->st_cur))) { Py_DECREF(id); return 0; } @@ -1803,7 +1813,7 @@ symtable_visit_params(struct symtable *st, asdl_arg_seq *args) for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!symtable_add_def(st, arg->arg, DEF_PARAM)) + if (!symtable_add_def(st, arg->arg, DEF_PARAM, LOCATION(arg))) return 0; } @@ -1887,12 +1897,12 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a) if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) return 0; if (a->vararg) { - if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM, LOCATION(a->vararg))) return 0; st->st_cur->ste_varargs = 1; } if (a->kwarg) { - if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM)) + if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM, LOCATION(a->kwarg))) return 0; st->st_cur->ste_varkeywords = 1; } @@ -1906,7 +1916,7 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) if (eh->v.ExceptHandler.type) VISIT(st, expr, eh->v.ExceptHandler.type); if (eh->v.ExceptHandler.name) - if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) + if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL, LOCATION(eh))) return 0; VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); return 1; @@ -1954,16 +1964,16 @@ symtable_visit_alias(struct symtable *st, alias_ty a) Py_INCREF(store_name); } if (!_PyUnicode_EqualToASCIIString(name, "*")) { - int r = symtable_add_def(st, store_name, DEF_IMPORT); + int r = symtable_add_def(st, store_name, DEF_IMPORT, LOCATION(a)); Py_DECREF(store_name); return r; } else { if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - int end_lineno = st->st_cur->ste_end_lineno; - int end_col_offset = st->st_cur->ste_end_col_offset; + int lineno = a->lineno; + int col_offset = a->col_offset; + int end_lineno = a->end_lineno; + int end_col_offset = a->end_col_offset; PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); PyErr_RangedSyntaxLocationObject(st->st_filename, lineno, col_offset + 1, @@ -2021,10 +2031,23 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, e->end_lineno, e->end_col_offset)) { return 0; } + switch(e->kind) { + case ListComp_kind: + st->st_cur->ste_comprehension = ListComprehension; + break; + case SetComp_kind: + st->st_cur->ste_comprehension = SetComprehension; + break; + case DictComp_kind: + st->st_cur->ste_comprehension = DictComprehension; + break; + default: + st->st_cur->ste_comprehension = GeneratorExpression; + break; + } if (outermost->is_async) { st->st_cur->ste_coroutine = 1; } - st->st_cur->ste_comprehension = 1; /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { @@ -2041,20 +2064,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, if (value) VISIT(st, expr, value); VISIT(st, expr, elt); - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - (e->kind == ListComp_kind) ? "'yield' inside list comprehension" : - (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : - (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : - "'yield' inside generator expression"); - PyErr_RangedSyntaxLocationObject(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset + 1, - st->st_cur->ste_end_lineno, - st->st_cur->ste_end_col_offset + 1); - symtable_exit_block(st); - return 0; - } st->st_cur->ste_generator = is_generator; return symtable_exit_block(st); } @@ -2108,6 +2117,20 @@ symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_t return 0; } +static int +symtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) { + _Py_comprehension_ty type = st->st_cur->ste_comprehension; + PyErr_SetString(PyExc_SyntaxError, + (type == ListComprehension) ? "'yield' inside list comprehension" : + (type == SetComprehension) ? "'yield' inside set comprehension" : + (type == DictComprehension) ? "'yield' inside dict comprehension" : + "'yield' inside generator expression"); + PyErr_RangedSyntaxLocationObject(st->st_filename, + e->lineno, e->col_offset + 1, + e->end_lineno, e->end_col_offset + 1); + VISIT_QUIT(st, 0); +} + struct symtable * _Py_SymtableStringObjectFlags(const char *str, PyObject *filename, int start, PyCompilerFlags *flags) diff --git a/Python/thread.c b/Python/thread.c index a10f5728dc0ceb..dfe28b6bdb680d 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -75,6 +75,25 @@ PyThread_init_thread(void) PyThread__init_thread(); } +void +_PyThread_debug_deprecation(void) +{ +#ifdef Py_DEBUG + if (thread_debug) { + // Flush previous dprintf() logs + fflush(stdout); + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "The threading debug (PYTHONTHREADDEBUG environment " + "variable) is deprecated and will be removed " + "in Python 3.12", + 0)) + { + _PyErr_WriteUnraisableMsg("at Python startup", NULL); + } + } +#endif +} + #if defined(_POSIX_THREADS) # define PYTHREAD_NAME "pthread" # include "thread_pthread.h" diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 05b982d32dc526..0ce5e94f89bf72 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -76,16 +76,22 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) } } else if (milliseconds != 0) { /* wait at least until the target */ - ULONGLONG now, target = GetTickCount64() + milliseconds; + _PyTime_t now = _PyTime_GetPerfCounter(); + if (now <= 0) { + Py_FatalError("_PyTime_GetPerfCounter() == 0"); + } + _PyTime_t nanoseconds = _PyTime_FromNanoseconds((_PyTime_t)milliseconds * 1000000); + _PyTime_t target = now + nanoseconds; while (mutex->locked) { - if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, (long long)milliseconds*1000) < 0) { + _PyTime_t microseconds = _PyTime_AsMicroseconds(nanoseconds, _PyTime_ROUND_TIMEOUT); + if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, microseconds) < 0) { result = WAIT_FAILED; break; } - now = GetTickCount64(); + now = _PyTime_GetPerfCounter(); if (target <= now) break; - milliseconds = (DWORD)(target-now); + nanoseconds = target - now; } } if (!mutex->locked) { diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index ec7d737518b68c..35b9810aa377f2 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -32,18 +32,17 @@ #define THREAD_STACK_SIZE 0 /* use default stack size */ #endif -/* The default stack size for new threads on OSX and BSD is small enough that +/* The default stack size for new threads on BSD is small enough that * we'll get hard crashes instead of 'maximum recursion depth exceeded' * exceptions. * - * The default stack sizes below are the empirically determined minimal stack + * The default stack size below is the empirically determined minimal stack * sizes where a simple recursive function doesn't cause a hard crash. + * + * For macOS the value of THREAD_STACK_SIZE is determined in configure.ac + * as it also depends on the other configure options like chosen sanitizer + * runtimes. */ -#if defined(__APPLE__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 -#undef THREAD_STACK_SIZE -/* Note: This matches the value of -Wl,-stack_size in configure.ac */ -#define THREAD_STACK_SIZE 0x1000000 -#endif #if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 #undef THREAD_STACK_SIZE #define THREAD_STACK_SIZE 0x400000 @@ -93,12 +92,17 @@ * mutexes and condition variables: */ #if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \ - defined(HAVE_SEM_TIMEDWAIT)) + (defined(HAVE_SEM_TIMEDWAIT) || defined(HAVE_SEM_CLOCKWAIT))) # define USE_SEMAPHORES #else # undef USE_SEMAPHORES #endif +#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) +// monotonic is supported statically. It doesn't mean it works on runtime. +#define CONDATTR_MONOTONIC +#endif + /* On platforms that don't use standard POSIX threads pthread_sigmask() * isn't present. DEC threads uses sigprocmask() instead as do most @@ -124,16 +128,23 @@ do { \ ts.tv_nsec = tv.tv_usec * 1000; \ } while(0) +#if defined(CONDATTR_MONOTONIC) || defined(HAVE_SEM_CLOCKWAIT) +static void +monotonic_abs_timeout(long long us, struct timespec *abs) +{ + clock_gettime(CLOCK_MONOTONIC, abs); + abs->tv_sec += us / 1000000; + abs->tv_nsec += (us % 1000000) * 1000; + abs->tv_sec += abs->tv_nsec / 1000000000; + abs->tv_nsec %= 1000000000; +} +#endif + /* * pthread_cond support */ -#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) -// monotonic is supported statically. It doesn't mean it works on runtime. -#define CONDATTR_MONOTONIC -#endif - // NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported. static pthread_condattr_t *condattr_monotonic = NULL; @@ -155,16 +166,13 @@ _PyThread_cond_init(PyCOND_T *cond) return pthread_cond_init(cond, condattr_monotonic); } + void _PyThread_cond_after(long long us, struct timespec *abs) { #ifdef CONDATTR_MONOTONIC if (condattr_monotonic) { - clock_gettime(CLOCK_MONOTONIC, abs); - abs->tv_sec += us / 1000000; - abs->tv_nsec += (us % 1000000) * 1000; - abs->tv_sec += abs->tv_nsec / 1000000000; - abs->tv_nsec %= 1000000000; + monotonic_abs_timeout(us, abs); return; } #endif @@ -435,7 +443,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, sem_t *thelock = (sem_t *)lock; int status, error = 0; struct timespec ts; +#ifndef HAVE_SEM_CLOCKWAIT _PyTime_t deadline = 0; +#endif (void) error; /* silence unused-but-set-variable warning */ dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", @@ -446,6 +456,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, } if (microseconds > 0) { +#ifdef HAVE_SEM_CLOCKWAIT + monotonic_abs_timeout(microseconds, &ts); +#else MICROSECONDS_TO_TIMESPEC(microseconds, ts); if (!intr_flag) { @@ -454,11 +467,17 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, _PyTime_t timeout = _PyTime_FromNanoseconds(microseconds * 1000); deadline = _PyTime_GetMonotonicClock() + timeout; } +#endif } while (1) { if (microseconds > 0) { +#ifdef HAVE_SEM_CLOCKWAIT + status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC, + &ts)); +#else status = fix_status(sem_timedwait(thelock, &ts)); +#endif } else if (microseconds == 0) { status = fix_status(sem_trywait(thelock)); @@ -473,6 +492,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, break; } + // sem_clockwait() uses an absolute timeout, there is no need + // to recompute the relative timeout. +#ifndef HAVE_SEM_CLOCKWAIT if (microseconds > 0) { /* wait interrupted by a signal (EINTR): recompute the timeout */ _PyTime_t dt = deadline - _PyTime_GetMonotonicClock(); @@ -494,13 +516,19 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, microseconds = 0; } } +#endif } /* Don't check the status if we're stopping because of an interrupt. */ if (!(intr_flag && status == EINTR)) { if (microseconds > 0) { - if (status != ETIMEDOUT) + if (status != ETIMEDOUT) { +#ifdef HAVE_SEM_CLOCKWAIT + CHECK_STATUS("sem_clockwait"); +#else CHECK_STATUS("sem_timedwait"); +#endif + } } else if (microseconds == 0) { if (status != EAGAIN) diff --git a/Python/traceback.c b/Python/traceback.c index 470324b1afd83f..7d6f7f435a6ba6 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -4,6 +4,7 @@ #include "Python.h" #include "code.h" +#include "pycore_interp.h" // PyInterpreterState.gc #include "frameobject.h" // PyFrame_GetBack() #include "structmember.h" // PyMemberDef #include "osdefs.h" // SEP @@ -233,7 +234,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame) assert(tb_next == NULL || PyTraceBack_Check(tb_next)); assert(frame != NULL); - return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_lasti*2, + return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_lasti*sizeof(_Py_CODEUNIT), PyFrame_GetLineNumber(frame)); } @@ -716,6 +717,26 @@ _Py_DumpASCII(int fd, PyObject *text) truncated = 0; } + // Is an ASCII string? + if (ascii->state.ascii) { + assert(kind == PyUnicode_1BYTE_KIND); + char *str = data; + + int need_escape = 0; + for (i=0; i < size; i++) { + ch = str[i]; + if (!(' ' <= ch && ch <= 126)) { + need_escape = 1; + break; + } + } + if (!need_escape) { + // The string can be written with a single write() syscall + _Py_write_noraise(fd, str, size); + goto done; + } + } + for (i=0; i < size; i++) { if (kind != PyUnicode_WCHAR_KIND) ch = PyUnicode_READ(kind, data, i); @@ -739,6 +760,8 @@ _Py_DumpASCII(int fd, PyObject *text) _Py_DumpHexadecimal(fd, ch, 8); } } + +done: if (truncated) { PUTS(fd, "..."); } @@ -795,26 +818,26 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header) PUTS(fd, "Stack (most recent call first):\n"); } - frame = PyThreadState_GetFrame(tstate); + // Use a borrowed reference. Avoid Py_INCREF/Py_DECREF, since this function + // can be called in a signal handler by the faulthandler module which must + // not modify Python objects. + frame = tstate->frame; if (frame == NULL) { - PUTS(fd, "\n"); + PUTS(fd, " \n"); return; } depth = 0; while (1) { if (MAX_FRAME_DEPTH <= depth) { - Py_DECREF(frame); PUTS(fd, " ...\n"); break; } if (!PyFrame_Check(frame)) { - Py_DECREF(frame); break; } dump_frame(fd, frame); - PyFrameObject *back = PyFrame_GetBack(frame); - Py_DECREF(frame); + PyFrameObject *back = frame->f_back; if (back == NULL) { break; @@ -914,6 +937,9 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, break; } write_thread_id(fd, tstate, tstate == current_tstate); + if (tstate == current_tstate && tstate->interp->gc.collecting) { + PUTS(fd, " Garbage-collecting\n"); + } dump_traceback(fd, tstate, 0); tstate = PyThreadState_Next(tstate); nthreads++; diff --git a/README.rst b/README.rst index 18d6e6a96f937e..d98a2ad9a3dae2 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.10.0 alpha 7 -===================================== +This is Python version 3.10.1 +============================= .. image:: https://travis-ci.com/python/cpython.svg?branch=master :alt: CPython build status on Travis CI @@ -18,7 +18,7 @@ This is Python version 3.10.0 alpha 7 :target: https://discuss.python.org/ -Copyright (c) 2001-2021 Python Software Foundation. All rights reserved. +Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. See the end of this file for further copyright and license information. @@ -110,12 +110,12 @@ The entire Python directory is cleaned of temporary files that may have resulted from a previous compilation. An instrumented version of the interpreter is built, using suitable compiler -flags for each flavour. Note that this is just an intermediary step. The -binary resulting from this step is not good for real life workloads as it has +flags for each flavor. Note that this is just an intermediary step. The +binary resulting from this step is not good for real-life workloads as it has profiling instructions embedded inside. After the instrumented interpreter is built, the Makefile will run a training -workload. This is necessary in order to profile the interpreter execution. +workload. This is necessary in order to profile the interpreter's execution. Note also that any output, both stdout and stderr, that may appear at this step is suppressed. @@ -229,12 +229,13 @@ Proposals for enhancement ------------------------- If you have a proposal to change Python, you may want to send an email to the -comp.lang.python or `python-ideas`_ mailing lists for initial feedback. A +`comp.lang.python`_ or `python-ideas`_ mailing lists for initial feedback. A Python Enhancement Proposal (PEP) may be submitted if your idea gains ground. All current PEPs, as well as guidelines for submitting a new PEP, are listed at `python.org/dev/peps/ `_. .. _python-ideas: https://mail.python.org/mailman/listinfo/python-ideas/ +.. _comp.lang.python: https://mail.python.org/mailman/listinfo/python-list Release Schedule @@ -246,7 +247,7 @@ See :pep:`619` for Python 3.10 release details. Copyright and License Information --------------------------------- -Copyright (c) 2001-2021 Python Software Foundation. All rights reserved. +Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. Copyright (c) 2000 BeOpen.com. All rights reserved. diff --git a/Tools/c-analyzer/c_analyzer/__main__.py b/Tools/c-analyzer/c_analyzer/__main__.py index 24fc6cd182656b..5d89b29adf899e 100644 --- a/Tools/c-analyzer/c_analyzer/__main__.py +++ b/Tools/c-analyzer/c_analyzer/__main__.py @@ -482,7 +482,7 @@ def cmd_data(datacmd, filenames, known=None, *, cmd_analyze, ), 'data': ( - 'check/manage local data (e.g. knwon types, ignored vars, caches)', + 'check/manage local data (e.g. known types, ignored vars, caches)', [_cli_data], cmd_data, ), diff --git a/Tools/c-analyzer/c_analyzer/info.py b/Tools/c-analyzer/c_analyzer/info.py index b75918e5e7a687..27c3a5a4ee76f2 100644 --- a/Tools/c-analyzer/c_analyzer/info.py +++ b/Tools/c-analyzer/c_analyzer/info.py @@ -230,11 +230,11 @@ def fix_filename(self, relroot=fsutil.USE_CWD, **kwargs): return self def as_rowdata(self, columns=None): - # XXX finsih! + # XXX finish! return self.item.as_rowdata(columns) def render_rowdata(self, columns=None): - # XXX finsih! + # XXX finish! return self.item.render_rowdata(columns) def render(self, fmt='line', *, itemonly=False): diff --git a/Tools/c-analyzer/c_common/logging.py b/Tools/c-analyzer/c_common/logging.py index 12398f7e385fdb..10af852ec3c5e6 100644 --- a/Tools/c-analyzer/c_common/logging.py +++ b/Tools/c-analyzer/c_common/logging.py @@ -41,7 +41,7 @@ def configure_logger(logger, verbosity=VERBOSITY, *, def hide_emit_errors(): """Ignore errors while emitting log entries. - Rather than printing a message desribing the error, we show nothing. + Rather than printing a message describing the error, we show nothing. """ # For now we simply ignore all exceptions. If we wanted to ignore # specific ones (e.g. BrokenPipeError) then we would need to use diff --git a/Tools/c-analyzer/c_common/strutil.py b/Tools/c-analyzer/c_common/strutil.py index e7535d45bbba23..07193c091e4c3f 100644 --- a/Tools/c-analyzer/c_common/strutil.py +++ b/Tools/c-analyzer/c_common/strutil.py @@ -26,7 +26,7 @@ def parse_entries(entries, *, ignoresep=None): # We read the entire file here to ensure the file # gets closed sooner rather than later. Note that # the file would stay open if this iterator is never - # exchausted. + # exhausted. lines = infile.read().splitlines() for line in _iter_significant_lines(lines): yield line, filename diff --git a/Tools/c-analyzer/c_common/tables.py b/Tools/c-analyzer/c_common/tables.py index 85b501925715d3..130be6beba5f81 100644 --- a/Tools/c-analyzer/c_common/tables.py +++ b/Tools/c-analyzer/c_common/tables.py @@ -236,12 +236,12 @@ def build_table(specs, *, sep=' ', defaultwidth=None): _COLSPEC_RE = re.compile(textwrap.dedent(r''' ^ (?: - [[] + \[ ( (?: [^\s\]] [^\]]* )? [^\s\]] ) #