diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 9e9ce2108ed818d..bf164d19ef2234f 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(build.sourceBranchName)-linux' testRunPlatform: linux - openssl_version: 1.1.1n + openssl_version: 1.1.1q steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1n + openssl_version: 1.1.1q steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/find-tools.yml b/.azure-pipelines/find-tools.yml deleted file mode 100644 index 9ad0f5622bb31e4..000000000000000 --- a/.azure-pipelines/find-tools.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Locate a set of the tools used for builds - -steps: - - template: windows-release/find-sdk.yml - parameters: - toolname: 'signtool.exe' - - - powershell: | - $vcvarsall = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` - -prerelease ` - -latest ` - -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` - -find VC\Auxiliary\Build\vcvarsall.bat) - Write-Host "Found vcvarsall at $vcvarsall" - Write-Host "##vso[task.setVariable variable=vcvarsall]$vcvarsall" - displayName: 'Find vcvarsall.bat' - - - powershell: | - $msbuild = (& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` - -prerelease ` - -latest ` - -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` - -find MSBuild\Current\Bin\msbuild.exe) - Write-Host "Found MSBuild at $msbuild" - Write-Host "##vso[task.setVariable variable=msbuild]$msbuild" - displayName: 'Find MSBuild' diff --git a/.azure-pipelines/libffi-build.yml b/.azure-pipelines/libffi-build.yml deleted file mode 100644 index dd26ff215a807ac..000000000000000 --- a/.azure-pipelines/libffi-build.yml +++ /dev/null @@ -1,86 +0,0 @@ -name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) - -variables: - IntDir: '$(Build.BinariesDirectory)' - OutDir: '$(Build.ArtifactStagingDirectory)' - - # MUST BE SET AT QUEUE TIME - # SigningCertificate: 'Python Software Foundation' - # SourcesRepo: 'https://github.com/python/cpython-source-deps' - # SourceTag: 'libffi-3.4.2' - -jobs: -- job: Build_LibFFI - displayName: LibFFI - pool: - vmImage: windows-latest - - workspace: - clean: all - - steps: - - checkout: none - - - template: ./find-tools.yml - - - powershell: | - mkdir -Force "$(IntDir)\script" - iwr "https://github.com/python/cpython/raw/main/PCbuild/prepare_libffi.bat" ` - -outfile "$(IntDir)\script\prepare_libffi.bat" - displayName: 'Download build script' - - - powershell: | - git clone $(SourcesRepo) -b $(SourceTag) --depth 1 -c core.autocrlf=false -c core.eol=lf . - displayName: 'Check out LibFFI sources' - - - script: 'prepare_libffi.bat --install-cygwin' - workingDirectory: '$(IntDir)\script' - displayName: 'Install Cygwin and build' - env: - VCVARSALL: '$(vcvarsall)' - LIBFFI_SOURCE: '$(Build.SourcesDirectory)' - LIBFFI_OUT: '$(OutDir)' - - - powershell: | - if ((gci *\*.dll).Count -lt 4) { - Write-Error "Did not generate enough DLL files" - } - if ((gci *\Include\ffi.h).Count -lt 4) { - Write-Error "Did not generate enough include files" - } - failOnStderr: true - workingDirectory: '$(OutDir)' - displayName: 'Verify files were created' - - - publish: '$(OutDir)' - artifact: 'unsigned' - displayName: 'Publish unsigned build' - -- job: Sign_LibFFI - displayName: Sign LibFFI - dependsOn: Build_LibFFI - pool: - name: 'Windows Release' - - workspace: - clean: all - - steps: - - checkout: none - - download: current - artifact: unsigned - - - template: ./find-tools.yml - - - powershell: | - signtool sign /q /a ` - /n "Python Software Foundation" ` - /fd sha256 ` - /tr http://timestamp.digicert.com/ /td sha256 ` - /d "LibFFI for Python" ` - (gci "$(Pipeline.Workspace)\unsigned\*.dll" -r) - displayName: 'Sign files' - - - publish: '$(Pipeline.Workspace)\unsigned' - artifact: 'libffi' - displayName: 'Publish libffi' diff --git a/.azure-pipelines/openssl-build.yml b/.azure-pipelines/openssl-build.yml deleted file mode 100644 index 8aab7ea0b94193b..000000000000000 --- a/.azure-pipelines/openssl-build.yml +++ /dev/null @@ -1,110 +0,0 @@ -name: $(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) - -variables: - IntDir: '$(Build.BinariesDirectory)' - OutDir: '$(Build.ArtifactStagingDirectory)' - - # MUST BE SET AT QUEUE TIME - # SigningCertificate: 'Python Software Foundation' - # SourcesRepo: 'https://github.com/python/cpython-source-deps' - # SourceTag: 'openssl-1.1.1k' - -jobs: -- job: Build_SSL - displayName: OpenSSL - pool: - name: 'Windows Release' - #vmImage: windows-latest - - strategy: - matrix: - win32: - Platform: 'win32' - VCPlatform: 'amd64_x86' - OpenSSLPlatform: 'VC-WIN32 no-asm' - amd64: - Platform: 'amd64' - VCPlatform: 'amd64' - OpenSSLPlatform: 'VC-WIN64A-masm' - arm32: - Platform: 'arm32' - VCPlatform: 'amd64_arm' - OpenSSLPlatform: 'VC-WIN32-ARM' - arm64: - Platform: 'arm64' - VCPlatform: 'amd64_arm64' - OpenSSLPlatform: 'VC-WIN64-ARM' - - workspace: - clean: all - - steps: - - checkout: none - - - template: ./find-tools.yml - - - powershell: | - git clone $(SourcesRepo) -b $(SourceTag) --depth 1 . - displayName: 'Check out OpenSSL sources' - - - powershell: | - $f = gi ms\uplink.c - $c1 = gc $f - $c2 = $c1 -replace '\(\(h = GetModuleHandle\(NULL\)\) == NULL\)', '((h = GetModuleHandleA("_ssl.pyd")) == NULL) if ((h = GetModuleHandleA("_ssl_d.pyd")) == NULL) if ((h = GetModuleHandle(NULL)) == NULL /*patched*/)' - if ($c2 -ne $c1) { - $c2 | Out-File $f -Encoding ASCII - } else { - Write-Host '##warning Failed to patch uplink.c' - } - displayName: 'Apply uplink.c patch' - - - script: | - call "$(vcvarsall)" $(VCPlatform) - perl "$(Build.SourcesDirectory)\Configure" $(OpenSSLPlatform) - nmake - workingDirectory: '$(IntDir)' - displayName: 'Build OpenSSL' - - - script: | - call "$(vcvarsall)" $(VCPlatform) - signtool sign /q /a /n "$(SigningCertificate)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "OpenSSL for Python" *.dll - workingDirectory: '$(IntDir)' - displayName: 'Sign OpenSSL Build' - condition: and(succeeded(), variables['SigningCertificate']) - - - task: CopyFiles@2 - displayName: 'Copy built libraries for upload' - inputs: - SourceFolder: '$(IntDir)' - Contents: | - lib*.dll - lib*.pdb - lib*.lib - include\openssl\*.h - TargetFolder: '$(OutDir)' - - - task: CopyFiles@2 - displayName: 'Copy header files for upload' - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - include\openssl\* - TargetFolder: '$(OutDir)' - - - task: CopyFiles@2 - displayName: 'Copy applink files for upload' - inputs: - SourceFolder: '$(Build.SourcesDirectory)\ms' - Contents: applink.c - TargetFolder: '$(OutDir)\include' - - - task: CopyFiles@2 - displayName: 'Copy LICENSE for upload' - inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: LICENSE - TargetFolder: '$(OutDir)' - - - publish: '$(OutDir)' - artifact: '$(Platform)' - displayName: 'Publishing $(Platform)' diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index c3ecc6705728026..3cbd19fda982f17 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -57,7 +57,7 @@ jobs: variables: testRunTitle: '$(system.pullRequest.TargetBranch)-linux' testRunPlatform: linux - openssl_version: 1.1.1n + openssl_version: 1.1.1q steps: - template: ./posix-steps.yml @@ -83,7 +83,7 @@ jobs: variables: testRunTitle: '$(Build.SourceBranchName)-linux-coverage' testRunPlatform: linux-coverage - openssl_version: 1.1.1n + openssl_version: 1.1.1q steps: - template: ./posix-steps.yml diff --git a/.azure-pipelines/tcltk-build.yml b/.azure-pipelines/tcltk-build.yml deleted file mode 100644 index f9e50d3711a4607..000000000000000 --- a/.azure-pipelines/tcltk-build.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: tcl$(TkSourceTag)_$(Date:yyyyMMdd)$(Rev:.rr) - -variables: - IntDir: '$(Build.BinariesDirectory)\obj' - ExternalsDir: '$(Build.BinariesDirectory)\externals' - OutDir: '$(Build.ArtifactStagingDirectory)' - Configuration: 'Release' - - # MUST BE SET AT QUEUE TIME - # SigningCertificate: 'Python Software Foundation' - # SourcesRepo: 'https://github.com/python/cpython-source-deps' - # TclSourceTag: 'tcl-core-8.6.12.0' - # TkSourceTag: 'tk-8.6.12.0' - # TixSourceTag: 'tix-8.4.3.6' - -jobs: -- job: Build_TclTk - displayName: 'Tcl/Tk' - pool: - name: 'Windows Release' - #vmImage: windows-latest - - workspace: - clean: all - - steps: - - template: ./find-tools.yml - - - powershell: | - git clone $(SourcesRepo) -b $(TclSourceTag) --depth 1 "$(ExternalsDir)\$(TclSourceTag)" - displayName: 'Check out Tcl sources' - - - powershell: | - git clone $(SourcesRepo) -b $(TkSourceTag) --depth 1 "$(ExternalsDir)\$(TkSourceTag)" - displayName: 'Check out Tk sources' - - - powershell: | - git clone $(SourcesRepo) -b $(TixSourceTag) --depth 1 "$(ExternalsDir)\$(TixSourceTag)" - displayName: 'Check out Tix sources' - - # This msbuild.rsp file will be used by the build to forcibly override these variables - - powershell: | - del -Force -EA 0 msbuild.rsp - "/p:IntDir=$(IntDir)\" >> msbuild.rsp - "/p:ExternalsDir=$(ExternalsDir)\" >> msbuild.rsp - "/p:tclDir=$(ExternalsDir)\$(TclSourceTag)\" >> msbuild.rsp - "/p:tkDir=$(ExternalsDir)\$(TkSourceTag)\" >> msbuild.rsp - "/p:tixDir=$(ExternalsDir)\$(TixSourceTag)\" >> msbuild.rsp - displayName: 'Generate msbuild.rsp' - - - powershell: | - & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" - & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" - & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=Win32 /p:tcltkDir="$(OutDir)\win32" - displayName: 'Build for win32' - - - powershell: | - & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" - & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" - & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64" - displayName: 'Build for amd64' - - - powershell: | - & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64" - & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64" - & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64" - displayName: 'Build for arm64' - - - publish: '$(OutDir)' - artifact: 'tcltk' - displayName: 'Publishing tcltk' diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cacd925cf4e3788..2568560c074f64b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,11 +5,11 @@ # https://git-scm.com/docs/gitignore#_pattern_format # asyncio -**/*asyncio* @1st1 @asvetlov +**/*asyncio* @1st1 @asvetlov @gvanrossum # Core **/*context* @1st1 -**/*genobject* @1st1 @markshannon +**/*genobject* @markshannon **/*hamt* @1st1 Objects/set* @rhettinger Objects/dict* @methane @markshannon diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d800442ad07e36f..1db5c505149397a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -175,7 +175,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1n + OPENSSL_VER: 1.1.1q PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout@v3 @@ -234,7 +234,7 @@ jobs: strategy: fail-fast: false matrix: - openssl_ver: [1.1.1n, 3.0.2] + openssl_ver: [1.1.1q, 3.0.5] env: OPENSSL_VER: ${{ matrix.openssl_ver }} MULTISSL_DIR: ${{ github.workspace }}/multissl @@ -281,7 +281,7 @@ jobs: needs: check_source if: needs.check_source.outputs.run_tests == 'true' env: - OPENSSL_VER: 1.1.1n + OPENSSL_VER: 1.1.1q PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: diff --git a/.github/workflows/project-updater.yml b/.github/workflows/project-updater.yml index 716ed7841feaeb7..ea98700e7fae9c7 100644 --- a/.github/workflows/project-updater.yml +++ b/.github/workflows/project-updater.yml @@ -8,12 +8,20 @@ on: jobs: add-to-project: - name: Add to the Release and Deferred Blocker project + name: Add issues to projects runs-on: ubuntu-latest + strategy: + matrix: + include: + # if an issue has any of these labels, it will be added + # to the corresponding project + - { project: 2, label: "release-blocker, deferred-blocker" } + - { project: 3, label: expert-subinterpreters } + - { project: 29, label: expert-asyncio } + steps: - uses: actions/add-to-project@v0.1.0 with: - project-url: https://github.com/orgs/python/projects/2 + project-url: https://github.com/orgs/python/projects/${{ matrix.project }} github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} - labeled: release-blocker, deferred-blocker - label-operator: OR + labeled: ${{ matrix.label }} diff --git a/.gitignore b/.gitignore index 0ddfd717d737f8f..924c136ba9aa05a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,12 @@ *.cover *.iml *.o +*.lto *.a *.so *.so.* *.dylib +*.dSYM *.dll *.wasm *.orig diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 038498f325ceb35..2a9cf0ea702209b 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1774,6 +1774,18 @@ Python-level trace functions in previous versions. The caller must hold the :term:`GIL`. +.. c:function:: void PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *obj) + + Like :c:func:`PyEval_SetProfile` but sets the profile function in all running threads + belonging to the current interpreter instead of the setting it only on the current thread. + + The caller must hold the :term:`GIL`. + + As :c:func:`PyEval_SetProfile`, this function ignores any exceptions raised while + setting the profile functions in all threads. + +.. versionadded:: 3.12 + .. c:function:: void PyEval_SetTrace(Py_tracefunc func, PyObject *obj) @@ -1788,6 +1800,18 @@ Python-level trace functions in previous versions. The caller must hold the :term:`GIL`. +.. c:function:: void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj) + + Like :c:func:`PyEval_SetTrace` but sets the tracing function in all running threads + belonging to the current interpreter instead of the setting it only on the current thread. + + The caller must hold the :term:`GIL`. + + As :c:func:`PyEval_SetTrace`, this function ignores any exceptions raised while + setting the trace functions in all threads. + +.. versionadded:: 3.12 + .. _advanced-debugging: diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 2074ec4e0e8ea53..c4a342ee811ca9e 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -1155,6 +1155,20 @@ PyConfig Default: ``-1`` in Python mode, ``0`` in isolated mode. + .. c:member:: int perf_profiling + + Enable compatibility mode with the perf profiler? + + If non-zero, initialize the perf trampoline. See :ref:`perf_profiling` + for more information. + + Set by :option:`-X perf <-X>` command line option and by the + :envvar:`PYTHONPERFSUPPORT` environment variable. + + Default: ``-1``. + + .. versionadded:: 3.12 + .. c:member:: int use_environment Use :ref:`environment variables `? diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index d9fcd0de1fec6db..557ccfc052343e6 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -153,7 +153,7 @@ complete listing. .. c:macro:: Py_GETENV(s) Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the - command line (i.e. if ``Py_IgnoreEnvironmentFlag`` is set). + command line (see :c:member:`PyConfig.use_environment`). .. c:macro:: Py_MAX(x, y) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 86d4536f8d28e73..f1eb09bb5691688 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -469,19 +469,21 @@ Accessing attributes of extension types .. _pymemberdef-offsets: Heap allocated types (created using :c:func:`PyType_FromSpec` or similar), - ``PyMemberDef`` may contain definitions for the special members - ``__dictoffset__``, ``__weaklistoffset__`` and ``__vectorcalloffset__``, - corresponding to - :c:member:`~PyTypeObject.tp_dictoffset`, - :c:member:`~PyTypeObject.tp_weaklistoffset` and + ``PyMemberDef`` may contain definitions for the special member + ``__vectorcalloffset__``, corresponding to :c:member:`~PyTypeObject.tp_vectorcall_offset` in type objects. These must be defined with ``T_PYSSIZET`` and ``READONLY``, for example:: static PyMemberDef spam_type_members[] = { - {"__dictoffset__", T_PYSSIZET, offsetof(Spam_object, dict), READONLY}, + {"__vectorcalloffset__", T_PYSSIZET, offsetof(Spam_object, vectorcall), READONLY}, {NULL} /* Sentinel */ }; + The legacy offsets :c:member:`~PyTypeObject.tp_dictoffset` and + :c:member:`~PyTypeObject.tp_weaklistoffset` are still supported, but extensions are + strongly encouraged to use ``Py_TPFLAGS_MANAGED_DICT`` and + ``Py_TPFLAGS_MANAGED_WEAKREF`` instead. + .. c:function:: PyObject* PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m) diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index 32c2bc8a0880ea6..11d5e0e03ec0983 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -167,7 +167,7 @@ Operating System Utilities .. versionchanged:: 3.8 The function now uses the UTF-8 encoding on Windows if - :c:data:`Py_LegacyWindowsFSEncodingFlag` is zero; + :c:member:`PyConfig.legacy_windows_fs_encoding` is zero; .. c:function:: char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) @@ -209,7 +209,7 @@ Operating System Utilities .. versionchanged:: 3.8 The function now uses the UTF-8 encoding on Windows if - :c:data:`Py_LegacyWindowsFSEncodingFlag` is zero. + :c:member:`PyConfig.legacy_windows_fs_encoding` is zero. .. _systemfunctions: diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index aa77c285e3b8299..deb5502a4dff9e8 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -327,9 +327,9 @@ The following functions and structs are used to create * :c:member:`~PyTypeObject.tp_weaklist` * :c:member:`~PyTypeObject.tp_vectorcall` * :c:member:`~PyTypeObject.tp_weaklistoffset` - (see :ref:`PyMemberDef `) + (use :const:`Py_TPFLAGS_MANAGED_WEAKREF` instead) * :c:member:`~PyTypeObject.tp_dictoffset` - (see :ref:`PyMemberDef `) + (use :const:`Py_TPFLAGS_MANAGED_DICT` instead) * :c:member:`~PyTypeObject.tp_vectorcall_offset` (see :ref:`PyMemberDef `) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index b8baa7c7dc39eef..2439f7c41b5665e 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -96,7 +96,7 @@ Quick Reference | | | __gt__, | | | | | | | | __ge__ | | | | | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ - | :c:member:`~PyTypeObject.tp_weaklistoffset` | :c:type:`Py_ssize_t` | | | X | | ? | + | (:c:member:`~PyTypeObject.tp_weaklistoffset`) | :c:type:`Py_ssize_t` | | | X | | ? | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ | :c:member:`~PyTypeObject.tp_iter` | :c:type:`getiterfunc` | __iter__ | | | | X | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ @@ -117,7 +117,7 @@ Quick Reference | :c:member:`~PyTypeObject.tp_descr_set` | :c:type:`descrsetfunc` | __set__, | | | | X | | | | __delete__ | | | | | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ - | :c:member:`~PyTypeObject.tp_dictoffset` | :c:type:`Py_ssize_t` | | | X | | ? | + | (:c:member:`~PyTypeObject.tp_dictoffset`) | :c:type:`Py_ssize_t` | | | X | | ? | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ | :c:member:`~PyTypeObject.tp_init` | :c:type:`initproc` | __init__ | X | X | | X | +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ @@ -1018,7 +1018,6 @@ and :c:type:`PyType_Type` effectively act as defaults.) :const:`Py_TPFLAGS_HAVE_GC` flag bit is clear in the subtype and the :c:member:`~PyTypeObject.tp_traverse` and :c:member:`~PyTypeObject.tp_clear` fields in the subtype exist and have ``NULL`` values. - .. XXX are most flag bits *really* inherited individually? **Default:** @@ -1135,6 +1134,33 @@ and :c:type:`PyType_Type` effectively act as defaults.) :const:`Py_TPFLAGS_IMMUTABLETYPE` flag set. For extension types, it is inherited whenever :c:member:`~PyTypeObject.tp_descr_get` is inherited. + .. data:: Py_TPFLAGS_MANAGED_DICT + + This bit indicates that instances of the class have a ``__dict___`` + attribute, and that the space for the dictionary is managed by the VM. + + If this flag is set, :const:`Py_TPFLAGS_HAVE_GC` should also be set. + + .. versionadded:: 3.12 + + **Inheritance:** + + This flag is inherited unless the + :c:member:`~PyTypeObject.tp_dictoffset` field is set in a superclass. + + + .. data:: Py_TPFLAGS_MANAGED_WEAKREF + + This bit indicates that instances of the class should be weakly + referenceable. + + .. versionadded:: 3.12 + + **Inheritance:** + + This flag is inherited unless the + :c:member:`~PyTypeObject.tp_weaklistoffset` field is set in a superclass. + .. XXX Document more flags here? @@ -1487,6 +1513,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: Py_ssize_t PyTypeObject.tp_weaklistoffset + While this field is still supported, :const:`Py_TPFLAGS_MANAGED_WEAKREF` + should be used instead, if at all possible. + If the instances of this type are weakly referenceable, this field is greater than zero and contains the offset in the instance structure of the weak reference list head (ignoring the GC header, if present); this offset is used by @@ -1497,6 +1526,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) Do not confuse this field with :c:member:`~PyTypeObject.tp_weaklist`; that is the list head for weak references to the type object itself. + It is an error to set both the :const:`Py_TPFLAGS_MANAGED_WEAKREF` bit and + :c:member:`~PyTypeObject.tp_weaklist`. + **Inheritance:** This field is inherited by subtypes, but see the rules listed below. A subtype @@ -1504,19 +1536,12 @@ and :c:type:`PyType_Type` effectively act as defaults.) reference list head than the base type. Since the list head is always found via :c:member:`~PyTypeObject.tp_weaklistoffset`, this should not be a problem. - When a type defined by a class statement has no :attr:`~object.__slots__` declaration, - and none of its base types are weakly referenceable, the type is made weakly - referenceable by adding a weak reference list head slot to the instance layout - and setting the :c:member:`~PyTypeObject.tp_weaklistoffset` of that slot's offset. - - When a type's :attr:`__slots__` declaration contains a slot named - :attr:`__weakref__`, that slot becomes the weak reference list head for - instances of the type, and the slot's offset is stored in the type's - :c:member:`~PyTypeObject.tp_weaklistoffset`. + **Default:** - When a type's :attr:`__slots__` declaration does not contain a slot named - :attr:`__weakref__`, the type inherits its :c:member:`~PyTypeObject.tp_weaklistoffset` from its - base type. + If the :const:`Py_TPFLAGS_MANAGED_WEAKREF` bit is set in the + :c:member:`~PyTypeObject.tp_dict` field, then + :c:member:`~PyTypeObject.tp_weaklistoffset` will be set to a negative value, + to indicate that it is unsafe to use this field. .. c:member:: getiterfunc PyTypeObject.tp_iter @@ -1695,6 +1720,9 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. c:member:: Py_ssize_t PyTypeObject.tp_dictoffset + While this field is still supported, :const:`Py_TPFLAGS_MANAGED_DICT` should be + used instead, if at all possible. + If the instances of this type have a dictionary containing instance variables, this field is non-zero and contains the offset in the instances of the type of the instance variable dictionary; this offset is used by @@ -1703,17 +1731,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) Do not confuse this field with :c:member:`~PyTypeObject.tp_dict`; that is the dictionary for attributes of the type object itself. - If the value of this field is greater than zero, it specifies the offset from - the start of the instance structure. If the value is less than zero, it - specifies the offset from the *end* of the instance structure. A negative - offset is more expensive to use, and should only be used when the instance - structure contains a variable-length part. This is used for example to add an - instance variable dictionary to subtypes of :class:`str` or :class:`tuple`. Note - that the :c:member:`~PyTypeObject.tp_basicsize` field should account for the dictionary added to - the end in that case, even though the dictionary is not included in the basic - object layout. On a system with a pointer size of 4 bytes, - :c:member:`~PyTypeObject.tp_dictoffset` should be set to ``-4`` to indicate that the dictionary is - at the very end of the structure. + The value specifies the offset of the dictionary from the start of the instance structure. The :c:member:`~PyTypeObject.tp_dictoffset` should be regarded as write-only. To get the pointer to the dictionary call :c:func:`PyObject_GenericGetDict`. @@ -1721,30 +1739,26 @@ and :c:type:`PyType_Type` effectively act as defaults.) dictionary, so it is may be more efficient to call :c:func:`PyObject_GetAttr` when accessing an attribute on the object. - **Inheritance:** - - This field is inherited by subtypes, but see the rules listed below. A subtype - may override this offset; this means that the subtype instances store the - dictionary at a difference offset than the base type. Since the dictionary is - always found via :c:member:`~PyTypeObject.tp_dictoffset`, this should not be a problem. + It is an error to set both the :const:`Py_TPFLAGS_MANAGED_WEAKREF` bit and + :c:member:`~PyTypeObject.tp_dictoffset`. - When a type defined by a class statement has no :attr:`~object.__slots__` declaration, - and none of its base types has an instance variable dictionary, a dictionary - slot is added to the instance layout and the :c:member:`~PyTypeObject.tp_dictoffset` is set to - that slot's offset. - - When a type defined by a class statement has a :attr:`__slots__` declaration, - the type inherits its :c:member:`~PyTypeObject.tp_dictoffset` from its base type. + **Inheritance:** - (Adding a slot named :attr:`~object.__dict__` to the :attr:`__slots__` declaration does - not have the expected effect, it just causes confusion. Maybe this should be - added as a feature just like :attr:`__weakref__` though.) + This field is inherited by subtypes. A subtype should not override this offset; + doing so could be unsafe, if C code tries to access the dictionary at the + previous offset. + To properly support inheritance, use :const:`Py_TPFLAGS_MANAGED_DICT`. **Default:** This slot has no default. For :ref:`static types `, if the field is ``NULL`` then no :attr:`__dict__` gets created for instances. + If the :const:`Py_TPFLAGS_MANAGED_DICT` bit is set in the + :c:member:`~PyTypeObject.tp_dict` field, then + :c:member:`~PyTypeObject.tp_dictoffset` will be set to ``-1``, to indicate + that it is unsafe to use this field. + .. c:member:: initproc PyTypeObject.tp_init @@ -2005,9 +2019,6 @@ and :c:type:`PyType_Type` effectively act as defaults.) PyErr_Restore(error_type, error_value, error_traceback); } - For this field to be taken into account (even through inheritance), - you must also set the :const:`Py_TPFLAGS_HAVE_FINALIZE` flags bit. - Also, note that, in a garbage collected Python, :c:member:`~PyTypeObject.tp_dealloc` may be called from any Python thread, not just the thread which created the object (if the object @@ -2025,6 +2036,12 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.4 + .. versionchanged:: 3.8 + + Before version 3.8 it was necessary to set the + :const:`Py_TPFLAGS_HAVE_FINALIZE` flags bit in order for this field to be + used. This is no longer required. + .. seealso:: "Safe object finalization" (:pep:`442`) @@ -2062,9 +2079,9 @@ This results in types that are limited relative to types defined in Python: :ref:`sub-interpreters `, so they should not include any subinterpreter-specific state. -Also, since :c:type:`PyTypeObject` is not part of the :ref:`stable ABI `, -any extension modules using static types must be compiled for a specific -Python minor version. +Also, since :c:type:`PyTypeObject` is only part of the :ref:`Limited API +` as an opaque struct, any extension modules using static types must be +compiled for a specific Python minor version. .. _heap-types: @@ -2660,8 +2677,6 @@ A type that supports weakrefs, instance dicts, and hashing:: typedef struct { PyObject_HEAD const char *data; - PyObject *inst_dict; - PyObject *weakreflist; } MyObject; static PyTypeObject MyObject_Type = { @@ -2669,9 +2684,9 @@ A type that supports weakrefs, instance dicts, and hashing:: .tp_name = "mymod.MyObject", .tp_basicsize = sizeof(MyObject), .tp_doc = PyDoc_STR("My objects"), - .tp_weaklistoffset = offsetof(MyObject, weakreflist), - .tp_dictoffset = offsetof(MyObject, inst_dict), - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT | + Py_TPFLAGS_MANAGED_WEAKREF, .tp_new = myobj_new, .tp_traverse = (traverseproc)myobj_traverse, .tp_clear = (inquiry)myobj_clear, diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 7bd47bb9c660a66..b17818e35ed9cf3 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -39,7 +39,7 @@ the same library that the Python runtime is using. Note that if an otherwise unhandled :exc:`SystemExit` is raised, this function will not return ``1``, but exit the process, as long as - ``Py_InspectFlag`` is not set. + :c:member:`PyConfig.inspect` is zero. .. c:function:: int Py_BytesMain(int argc, char **argv) @@ -95,7 +95,7 @@ the same library that the Python runtime is using. Note that if an otherwise unhandled :exc:`SystemExit` is raised, this function will not return ``-1``, but exit the process, as long as - ``Py_InspectFlag`` is not set. + :c:member:`PyConfig.inspect` is zero. .. c:function:: int PyRun_SimpleFile(FILE *fp, const char *filename) diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 1694cad6f43ba7c..51ccacf13f9e3be 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -796,10 +796,18 @@ PyEval_SetProfile:void::: PyEval_SetProfile:Py_tracefunc:func:: PyEval_SetProfile:PyObject*:obj:+1: +PyEval_SetProfileAllThreads:void::: +PyEval_SetProfileAllThreads:Py_tracefunc:func:: +PyEval_SetProfileAllThreads:PyObject*:obj:+1: + PyEval_SetTrace:void::: PyEval_SetTrace:Py_tracefunc:func:: PyEval_SetTrace:PyObject*:obj:+1: +PyEval_SetTraceAllThreads:void::: +PyEval_SetTraceAllThreads:Py_tracefunc:func:: +PyEval_SetTraceAllThreads:PyObject*:obj:+1: + PyEval_EvalCode:PyObject*::+1: PyEval_EvalCode:PyObject*:co:0: PyEval_EvalCode:PyObject*:globals:0: diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index c7c434e58bf04bc..b797dc2817c83e6 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -570,43 +570,28 @@ performance-critical objects (such as numbers). .. seealso:: Documentation for the :mod:`weakref` module. -For an object to be weakly referencable, the extension type must do two things: +For an object to be weakly referencable, the extension type must set the +``Py_TPFLAGS_MANAGED_WEAKREF`` bit of the :c:member:`~PyTypeObject.tp_flags` +field. The legacy :c:member:`~PyTypeObject.tp_weaklistoffset` field should +be left as zero. -#. Include a :c:type:`PyObject\*` field in the C object structure dedicated to - the weak reference mechanism. The object's constructor should leave it - ``NULL`` (which is automatic when using the default - :c:member:`~PyTypeObject.tp_alloc`). - -#. Set the :c:member:`~PyTypeObject.tp_weaklistoffset` type member - to the offset of the aforementioned field in the C object structure, - so that the interpreter knows how to access and modify that field. - -Concretely, here is how a trivial object structure would be augmented -with the required field:: - - typedef struct { - PyObject_HEAD - PyObject *weakreflist; /* List of weak references */ - } TrivialObject; - -And the corresponding member in the statically declared type object:: +Concretely, here is how the statically declared type object would look:: static PyTypeObject TrivialType = { PyVarObject_HEAD_INIT(NULL, 0) /* ... other members omitted for brevity ... */ - .tp_weaklistoffset = offsetof(TrivialObject, weakreflist), + .tp_flags = Py_TPFLAGS_MANAGED_WEAKREF | ..., }; + The only further addition is that ``tp_dealloc`` needs to clear any weak -references (by calling :c:func:`PyObject_ClearWeakRefs`) if the field is -non-``NULL``:: +references (by calling :c:func:`PyObject_ClearWeakRefs`):: static void Trivial_dealloc(TrivialObject *self) { /* Clear weakrefs first before calling any destructors */ - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs((PyObject *) self); /* ... remainder of destruction code omitted for brevity ... */ Py_TYPE(self)->tp_free((PyObject *) self); } diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 510ebb5cf9046b9..6c7e4fc67c0a67d 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -113,8 +113,8 @@ 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 -programming), software engineering (unit testing, logging, profiling, parsing +files), internet protocols (HTTP, FTP, SMTP, XML-RPC, POP, IMAP), +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 of what's available. A wide variety of third-party extensions are also diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 5e9b110f0fe2544..91a6c31c33b8bde 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -582,11 +582,18 @@ a pure Python equivalent: .. testcode:: + def find_name_in_mro(cls, name, default): + "Emulate _PyType_Lookup() in Objects/typeobject.c" + for base in cls.__mro__: + if name in vars(base): + return vars(base)[name] + return default + def object_getattribute(obj, name): "Emulate PyObject_GenericGetAttr() in Objects/object.c" null = object() objtype = type(obj) - cls_var = getattr(objtype, name, null) + cls_var = find_name_in_mro(objtype, name, null) descr_get = getattr(type(cls_var), '__get__', null) if descr_get is not null: if (hasattr(type(cls_var), '__set__') @@ -663,6 +670,15 @@ a pure Python equivalent: def __getattr__(self, name): return ('getattr_hook', self, name) + class D1: + def __get__(self, obj, objtype=None): + return type(self), obj, objtype + + class U1: + x = D1() + + class U2(U1): + pass .. doctest:: :hide: @@ -696,6 +712,10 @@ a pure Python equivalent: >>> b.g == b['g'] == ('getattr_hook', b, 'g') True + >>> u2 = U2() + >>> object_getattribute(u2, 'x') == u2.x == (D1, u2, U2) + True + Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__` code. That is why calling :meth:`__getattribute__` directly or with ``super().__getattribute__`` will bypass :meth:`__getattr__` entirely. diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index 8a378e6659efc4d..f521276a5a83c54 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -30,6 +30,7 @@ Currently, the HOWTOs are: ipaddress.rst clinic.rst instrumentation.rst + perf_profiling.rst annotations.rst isolating-extensions.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 321c4bc510ad990..16df3b730ac80e4 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -2678,6 +2678,88 @@ You can of course use the conventional means of decoration:: ... +.. _buffered-smtp: + +Sending logging messages to email, with buffering +------------------------------------------------- + +To illustrate how you can send log messages via email, so that a set number of +messages are sent per email, you can subclass +:class:`~logging.handlers.BufferingHandler`. In the following example, which you can +adapt to suit your specific needs, a simple test harness is provided which allows you +to run the script with command line arguments specifying what you typically need to +send things via SMTP. (Run the downloaded script with the ``-h`` argument to see the +required and optional arguments.) + +.. code-block:: python + + import logging + import logging.handlers + import smtplib + + class BufferingSMTPHandler(logging.handlers.BufferingHandler): + def __init__(self, mailhost, port, username, password, fromaddr, toaddrs, + subject, capacity): + logging.handlers.BufferingHandler.__init__(self, capacity) + self.mailhost = mailhost + self.mailport = port + self.username = username + self.password = password + self.fromaddr = fromaddr + if isinstance(toaddrs, str): + toaddrs = [toaddrs] + self.toaddrs = toaddrs + self.subject = subject + self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s")) + + def flush(self): + if len(self.buffer) > 0: + try: + smtp = smtplib.SMTP(self.mailhost, self.mailport) + smtp.starttls() + smtp.login(self.username, self.password) + msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, ','.join(self.toaddrs), self.subject) + for record in self.buffer: + s = self.format(record) + msg = msg + s + "\r\n" + smtp.sendmail(self.fromaddr, self.toaddrs, msg) + smtp.quit() + except Exception: + if logging.raiseExceptions: + raise + self.buffer = [] + + if __name__ == '__main__': + import argparse + + ap = argparse.ArgumentParser() + aa = ap.add_argument + aa('host', metavar='HOST', help='SMTP server') + aa('--port', '-p', type=int, default=587, help='SMTP port') + aa('user', metavar='USER', help='SMTP username') + aa('password', metavar='PASSWORD', help='SMTP password') + aa('to', metavar='TO', help='Addressee for emails') + aa('sender', metavar='SENDER', help='Sender email address') + aa('--subject', '-s', + default='Test Logging email from Python logging module (buffering)', + help='Subject of email') + options = ap.parse_args() + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + h = BufferingSMTPHandler(options.host, options.port, options.user, + options.password, options.sender, + options.to, options.subject, 10) + logger.addHandler(h) + for i in range(102): + logger.info("Info index = %d", i) + h.flush() + h.close() + +If you run this script and your SMTP server is correctly set up, you should find that +it sends eleven emails to the addressee you specify. The first ten emails will each +have ten log messages, and the eleventh will have two messages. That makes up 102 +messages as specified in the script. + .. _utc-formatting: Formatting times using UTC (GMT) via configuration diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst new file mode 100644 index 000000000000000..ed8de888b3bc21a --- /dev/null +++ b/Doc/howto/perf_profiling.rst @@ -0,0 +1,203 @@ +.. highlight:: shell-session + +.. _perf_profiling: + +============================================== +Python support for the Linux ``perf`` profiler +============================================== + +:author: Pablo Galindo + +The Linux ``perf`` profiler is a very powerful tool that allows you to profile and +obtain information about the performance of your application. ``perf`` also has +a very vibrant ecosystem of tools that aid with the analysis of the data that it +produces. + +The main problem with using the ``perf`` profiler with Python applications is that +``perf`` only allows to get information about native symbols, this is, the names of +the functions and procedures written in C. This means that the names and file names +of the Python functions in your code will not appear in the output of the ``perf``. + +Since Python 3.12, the interpreter can run in a special mode that allows Python +functions to appear in the output of the ``perf`` profiler. When this mode is +enabled, the interpreter will interpose a small piece of code compiled on the +fly before the execution of every Python function and it will teach ``perf`` the +relationship between this piece of code and the associated Python function using +`perf map files`_. + +.. warning:: + + Support for the ``perf`` profiler is only currently available for Linux on + selected architectures. Check the output of the configure build step or + check the output of ``python -m sysconfig | grep HAVE_PERF_TRAMPOLINE`` + to see if your system is supported. + +For example, consider the following script: + +.. code-block:: python + + def foo(n): + result = 0 + for _ in range(n): + result += 1 + return result + + def bar(n): + foo(n) + + def baz(n): + bar(n) + + if __name__ == "__main__": + baz(1000000) + +We can run perf to sample CPU stack traces at 9999 Hertz: + + $ perf record -F 9999 -g -o perf.data python my_script.py + +Then we can use perf report to analyze the data: + +.. code-block:: shell-session + + $ perf report --stdio -n -g + + # Children Self Samples Command Shared Object Symbol + # ........ ........ ............ .......... .................. .......................................... + # + 91.08% 0.00% 0 python.exe python.exe [.] _start + | + ---_start + | + --90.71%--__libc_start_main + Py_BytesMain + | + |--56.88%--pymain_run_python.constprop.0 + | | + | |--56.13%--_PyRun_AnyFileObject + | | _PyRun_SimpleFileObject + | | | + | | |--55.02%--run_mod + | | | | + | | | --54.65%--PyEval_EvalCode + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | | + | | | |--51.67%--_PyEval_EvalFrameDefault + | | | | | + | | | | |--11.52%--_PyLong_Add + | | | | | | + | | | | | |--2.97%--_PyObject_Malloc + ... + +As you can see here, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault`` appears +(the function that evaluates the Python bytecode) shows up. Unfortunately that's not very useful because all Python +functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which +bytecode-evaluating function. + +Instead, if we run the same experiment with perf support activated we get: + +.. code-block:: shell-session + + $ perf report --stdio -n -g + + # Children Self Samples Command Shared Object Symbol + # ........ ........ ............ .......... .................. ..................................................................... + # + 90.58% 0.36% 1 python.exe python.exe [.] _start + | + ---_start + | + --89.86%--__libc_start_main + Py_BytesMain + | + |--55.43%--pymain_run_python.constprop.0 + | | + | |--54.71%--_PyRun_AnyFileObject + | | _PyRun_SimpleFileObject + | | | + | | |--53.62%--run_mod + | | | | + | | | --53.26%--PyEval_EvalCode + | | | py:::/src/script.py + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | py::baz:/src/script.py + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | py::bar:/src/script.py + | | | _PyEval_EvalFrameDefault + | | | PyObject_Vectorcall + | | | _PyEval_Vector + | | | py::foo:/src/script.py + | | | | + | | | |--51.81%--_PyEval_EvalFrameDefault + | | | | | + | | | | |--13.77%--_PyLong_Add + | | | | | | + | | | | | |--3.26%--_PyObject_Malloc + + + +Enabling perf profiling mode +---------------------------- + +There are two main ways to activate the perf profiling mode. If you want it to be +active since the start of the Python interpreter, you can use the `-Xperf` option: + + $ python -Xperf my_script.py + +You can also set the :envvar:`PYTHONPERFSUPPORT` to a nonzero value to actiavate perf +profiling mode globally. + +There is also support for dynamically activating and deactivating the perf +profiling mode by using the APIs in the :mod:`sys` module: + +.. code-block:: python + + import sys + sys.activate_stack_trampoline("perf") + + # Run some code with Perf profiling active + + sys.deactivate_stack_trampoline() + + # Perf profiling is not active anymore + +These APIs can be handy if you want to activate/deactivate profiling mode in +response to a signal or other communication mechanism with your process. + + + +Now we can analyze the data with ``perf report``: + + $ perf report -g -i perf.data + + +How to obtain the best results +------------------------------- + +For the best results, Python should be compiled with +``CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"`` as this allows +profilers to unwind using only the frame pointer and not on DWARF debug +information. This is because as the code that is interposed to allow perf +support is dynamically generated it doesn't have any DWARF debugging information +available. + +You can check if you system has been compiled with this flag by running: + + $ python -m sysconfig | grep 'no-omit-frame-pointer' + +If you don't see any output it means that your interpreter has not been compiled with +frame pointers and therefore it may not be able to show Python functions in the output +of ``perf``. + +.. _perf map files: https://github.com/torvalds/linux/blob/0513e464f9007b70b96740271a948ca5ab6e7dd7/tools/perf/Documentation/jit-interface.txt diff --git a/Doc/includes/sqlite3/adapter_point_1.py b/Doc/includes/sqlite3/adapter_point_1.py deleted file mode 100644 index 77daf8f16d227b8..000000000000000 --- a/Doc/includes/sqlite3/adapter_point_1.py +++ /dev/null @@ -1,18 +0,0 @@ -import sqlite3 - -class Point: - def __init__(self, x, y): - self.x, self.y = x, y - - def __conform__(self, protocol): - if protocol is sqlite3.PrepareProtocol: - return "%f;%f" % (self.x, self.y) - -con = sqlite3.connect(":memory:") -cur = con.cursor() - -p = Point(4.0, -3.2) -cur.execute("select ?", (p,)) -print(cur.fetchone()[0]) - -con.close() diff --git a/Doc/includes/sqlite3/adapter_point_2.py b/Doc/includes/sqlite3/adapter_point_2.py deleted file mode 100644 index cb86331692b61d5..000000000000000 --- a/Doc/includes/sqlite3/adapter_point_2.py +++ /dev/null @@ -1,19 +0,0 @@ -import sqlite3 - -class Point: - def __init__(self, x, y): - self.x, self.y = x, y - -def adapt_point(point): - return "%f;%f" % (point.x, point.y) - -sqlite3.register_adapter(Point, adapt_point) - -con = sqlite3.connect(":memory:") -cur = con.cursor() - -p = Point(4.0, -3.2) -cur.execute("select ?", (p,)) -print(cur.fetchone()[0]) - -con.close() diff --git a/Doc/includes/sqlite3/blob.py b/Doc/includes/sqlite3/blob.py deleted file mode 100644 index ff58d6c352b6529..000000000000000 --- a/Doc/includes/sqlite3/blob.py +++ /dev/null @@ -1,19 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -con.execute("create table test(blob_col blob)") -con.execute("insert into test(blob_col) values (zeroblob(13))") - -# Write to our blob, using two write operations: -with con.blobopen("test", "blob_col", 1) as blob: - blob.write(b"hello, ") - blob.write(b"world.") - # Modify the first and last bytes of our blob - blob[0] = ord("H") - blob[-1] = ord("!") - -# Read the contents of our blob -with con.blobopen("test", "blob_col", 1) as blob: - greeting = blob.read() - -print(greeting) # outputs "b'Hello, world!'" diff --git a/Doc/includes/sqlite3/collation_reverse.py b/Doc/includes/sqlite3/collation_reverse.py deleted file mode 100644 index 3504a350a04ecb8..000000000000000 --- a/Doc/includes/sqlite3/collation_reverse.py +++ /dev/null @@ -1,20 +0,0 @@ -import sqlite3 - -def collate_reverse(string1, string2): - if string1 == string2: - return 0 - elif string1 < string2: - return 1 - else: - return -1 - -con = sqlite3.connect(":memory:") -con.create_collation("reverse", collate_reverse) - -cur = con.cursor() -cur.execute("create table test(x)") -cur.executemany("insert into test(x) values (?)", [("a",), ("b",)]) -cur.execute("select x from test order by x collate reverse") -for row in cur: - print(row) -con.close() diff --git a/Doc/includes/sqlite3/converter_point.py b/Doc/includes/sqlite3/converter_point.py deleted file mode 100644 index 147807a2225ff00..000000000000000 --- a/Doc/includes/sqlite3/converter_point.py +++ /dev/null @@ -1,40 +0,0 @@ -import sqlite3 - -class Point: - def __init__(self, x, y): - self.x, self.y = x, y - - def __repr__(self): - return f"Point({self.x}, {self.y})" - -def adapt_point(point): - return f"{point.x};{point.y}".encode("utf-8") - -def convert_point(s): - x, y = list(map(float, s.split(b";"))) - return Point(x, y) - -# Register the adapter and converter -sqlite3.register_adapter(Point, adapt_point) -sqlite3.register_converter("point", convert_point) - -# 1) Parse using declared types -p = Point(4.0, -3.2) -con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES) -cur = con.execute("create table test(p point)") - -cur.execute("insert into test(p) values (?)", (p,)) -cur.execute("select p from test") -print("with declared types:", cur.fetchone()[0]) -cur.close() -con.close() - -# 2) Parse using column names -con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) -cur = con.execute("create table test(p)") - -cur.execute("insert into test(p) values (?)", (p,)) -cur.execute('select p as "p [point]" from test') -print("with column names:", cur.fetchone()[0]) -cur.close() -con.close() diff --git a/Doc/includes/sqlite3/ctx_manager.py b/Doc/includes/sqlite3/ctx_manager.py deleted file mode 100644 index 2e1175ef44c6415..000000000000000 --- a/Doc/includes/sqlite3/ctx_manager.py +++ /dev/null @@ -1,20 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -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 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 lang(name) values (?)", ("Python",)) -except sqlite3.IntegrityError: - 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 -con.close() diff --git a/Doc/includes/sqlite3/execute_1.py b/Doc/includes/sqlite3/execute_1.py deleted file mode 100644 index ee0000e2b94a324..000000000000000 --- a/Doc/includes/sqlite3/execute_1.py +++ /dev/null @@ -1,22 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -cur = con.cursor() -cur.execute("create table lang (name, first_appeared)") - -# This is the qmark style: -cur.execute("insert into lang values (?, ?)", ("C", 1972)) - -# The qmark style used with executemany(): -lang_list = [ - ("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 first_appeared=:year", {"year": 1972}) -print(cur.fetchall()) - -con.close() diff --git a/Doc/includes/sqlite3/load_extension.py b/Doc/includes/sqlite3/load_extension.py deleted file mode 100644 index 624cfe262f38b37..000000000000000 --- a/Doc/includes/sqlite3/load_extension.py +++ /dev/null @@ -1,28 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") - -# enable extension loading -con.enable_load_extension(True) - -# Load the fulltext search extension -con.execute("select load_extension('./fts3.so')") - -# alternatively you can load the extension using an API call: -# con.load_extension("./fts3.so") - -# disable extension loading again -con.enable_load_extension(False) - -# example from SQLite wiki -con.execute("create virtual table recipe using fts3(name, ingredients)") -con.executescript(""" - insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes'); - insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery'); - insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour'); - insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter'); - """) -for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"): - print(row) - -con.close() diff --git a/Doc/includes/sqlite3/md5func.py b/Doc/includes/sqlite3/md5func.py deleted file mode 100644 index 16dc348bf001e26..000000000000000 --- a/Doc/includes/sqlite3/md5func.py +++ /dev/null @@ -1,13 +0,0 @@ -import sqlite3 -import hashlib - -def md5sum(t): - return hashlib.md5(t).hexdigest() - -con = sqlite3.connect(":memory:") -con.create_function("md5", 1, md5sum) -cur = con.cursor() -cur.execute("select md5(?)", (b"foo",)) -print(cur.fetchone()[0]) - -con.close() diff --git a/Doc/includes/sqlite3/mysumaggr.py b/Doc/includes/sqlite3/mysumaggr.py deleted file mode 100644 index 11f96395b6c485c..000000000000000 --- a/Doc/includes/sqlite3/mysumaggr.py +++ /dev/null @@ -1,22 +0,0 @@ -import sqlite3 - -class MySum: - def __init__(self): - self.count = 0 - - def step(self, value): - self.count += value - - def finalize(self): - return self.count - -con = sqlite3.connect(":memory:") -con.create_aggregate("mysum", 1, MySum) -cur = con.cursor() -cur.execute("create table test(i)") -cur.execute("insert into test(i) values (1)") -cur.execute("insert into test(i) values (2)") -cur.execute("select mysum(i) from test") -print(cur.fetchone()[0]) - -con.close() diff --git a/Doc/includes/sqlite3/row_factory.py b/Doc/includes/sqlite3/row_factory.py deleted file mode 100644 index 9de6e7b1b9052a3..000000000000000 --- a/Doc/includes/sqlite3/row_factory.py +++ /dev/null @@ -1,15 +0,0 @@ -import sqlite3 - -def dict_factory(cursor, row): - d = {} - for idx, col in enumerate(cursor.description): - d[col[0]] = row[idx] - return d - -con = sqlite3.connect(":memory:") -con.row_factory = dict_factory -cur = con.cursor() -cur.execute("select 1 as a") -print(cur.fetchone()["a"]) - -con.close() diff --git a/Doc/includes/sqlite3/rowclass.py b/Doc/includes/sqlite3/rowclass.py deleted file mode 100644 index fc60287069a854d..000000000000000 --- a/Doc/includes/sqlite3/rowclass.py +++ /dev/null @@ -1,14 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -con.row_factory = sqlite3.Row - -cur = con.cursor() -cur.execute("select 'John' as name, 42 as age") -for row in cur: - assert row[0] == row["name"] - assert row["name"] == row["nAmE"] - assert row[1] == row["age"] - assert row[1] == row["AgE"] - -con.close() diff --git a/Doc/includes/sqlite3/shortcut_methods.py b/Doc/includes/sqlite3/shortcut_methods.py deleted file mode 100644 index 48ea6fad15a8985..000000000000000 --- a/Doc/includes/sqlite3/shortcut_methods.py +++ /dev/null @@ -1,24 +0,0 @@ -import sqlite3 - -langs = [ - ("C++", 1985), - ("Objective-C", 1984), -] - -con = sqlite3.connect(":memory:") - -# Create the table -con.execute("create table lang(name, first_appeared)") - -# Fill the table -con.executemany("insert into lang(name, first_appeared) values (?, ?)", langs) - -# Print the table contents -for row in con.execute("select name, first_appeared from lang"): - print(row) - -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 -con.close() diff --git a/Doc/includes/sqlite3/sumintwindow.py b/Doc/includes/sqlite3/sumintwindow.py deleted file mode 100644 index 0e915d6cc6ae68e..000000000000000 --- a/Doc/includes/sqlite3/sumintwindow.py +++ /dev/null @@ -1,46 +0,0 @@ -# Example taken from https://www.sqlite.org/windowfunctions.html#udfwinfunc -import sqlite3 - - -class WindowSumInt: - def __init__(self): - self.count = 0 - - def step(self, value): - """Adds a row to the current window.""" - self.count += value - - def value(self): - """Returns the current value of the aggregate.""" - return self.count - - def inverse(self, value): - """Removes a row from the current window.""" - self.count -= value - - def finalize(self): - """Returns the final value of the aggregate. - - Any clean-up actions should be placed here. - """ - return self.count - - -con = sqlite3.connect(":memory:") -cur = con.execute("create table test(x, y)") -values = [ - ("a", 4), - ("b", 5), - ("c", 3), - ("d", 8), - ("e", 1), -] -cur.executemany("insert into test values(?, ?)", values) -con.create_window_function("sumint", 1, WindowSumInt) -cur.execute(""" - select x, sumint(y) over ( - order by x rows between 1 preceding and 1 following - ) as sum_y - from test order by x -""") -print(cur.fetchall()) diff --git a/Doc/includes/sqlite3/text_factory.py b/Doc/includes/sqlite3/text_factory.py deleted file mode 100644 index c0d87cd559118c4..000000000000000 --- a/Doc/includes/sqlite3/text_factory.py +++ /dev/null @@ -1,29 +0,0 @@ -import sqlite3 - -con = sqlite3.connect(":memory:") -cur = con.cursor() - -AUSTRIA = "Österreich" - -# by default, rows are returned as str -cur.execute("select ?", (AUSTRIA,)) -row = cur.fetchone() -assert row[0] == AUSTRIA - -# but we can make sqlite3 always return bytestrings ... -con.text_factory = bytes -cur.execute("select ?", (AUSTRIA,)) -row = cur.fetchone() -assert type(row[0]) is bytes -# the bytestrings will be encoded in UTF-8, unless you stored garbage in the -# database ... -assert row[0] == AUSTRIA.encode("utf-8") - -# we can also implement a custom text_factory ... -# here we implement one that appends "foo" to all strings -con.text_factory = lambda x: x.decode("utf-8") + "foo" -cur.execute("select ?", ("bar",)) -row = cur.fetchone() -assert row[0] == "barfoo" - -con.close() diff --git a/Doc/library/asyncio-api-index.rst b/Doc/library/asyncio-api-index.rst index a4e38e469d82f02..54c1cd6582e4941 100644 --- a/Doc/library/asyncio-api-index.rst +++ b/Doc/library/asyncio-api-index.rst @@ -21,8 +21,25 @@ await on multiple things with timeouts. * - :func:`run` - Create event loop, run a coroutine, close the loop. + * - :class:`Runner` + - A context manager that simplifies multiple async function calls. + + * - :class:`Task` + - Task object. + + * - :class:`TaskGroup` + - A context manager that holds a group of tasks. Provides + a convenient and reliable way to wait for all tasks in the group to + finish. + * - :func:`create_task` - - Start an asyncio Task. + - Start an asyncio Task, then returns it. + + * - :func:`current_task` + - Return the current Task. + + * - :func:`all_tasks` + - Return all tasks that are not yet finished for an event loop. * - ``await`` :func:`sleep` - Sleep for a number of seconds. @@ -39,14 +56,8 @@ await on multiple things with timeouts. * - ``await`` :func:`wait` - Monitor for completion. - * - :func:`current_task` - - Return the current Task. - - * - :func:`all_tasks` - - Return all tasks for an event loop. - - * - :class:`Task` - - Task object. + * - :func:`timeout` + - Run with a timeout. Useful in cases when `wait_for` is not suitable. * - :func:`to_thread` - Asynchronously run a function in a separate OS thread. diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 555a0f5cb2a72b5..c86da8c31f6e7ac 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -377,7 +377,8 @@ Opening network connections local_addr=None, server_hostname=None, \ ssl_handshake_timeout=None, \ ssl_shutdown_timeout=None, \ - happy_eyeballs_delay=None, interleave=None) + happy_eyeballs_delay=None, interleave=None, \ + all_errors=False) Open a streaming transport connection to a given address specified by *host* and *port*. @@ -468,6 +469,14 @@ Opening network connections to complete before aborting the connection. ``30.0`` seconds if ``None`` (default). + * *all_errors* determines what exceptions are raised when a connection cannot + be created. By default, only a single ``Exception`` is raised: the first + exception if there is only one or all errors have same message, or a single + ``OSError`` with the error messages combined. When ``all_errors`` is ``True``, + an ``ExceptionGroup`` will be raised containing all exceptions (even if there + is only one). + + .. versionchanged:: 3.5 Added support for SSL/TLS in :class:`ProactorEventLoop`. @@ -500,6 +509,9 @@ Opening network connections Added the *ssl_shutdown_timeout* parameter. + .. versionchanged:: 3.12 + *all_errors* was added. + .. seealso:: The :func:`open_connection` function is a high-level alternative diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index a6b638c1124094e..ffbf421bae5e34a 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -40,7 +40,7 @@ be executed:: >>> main() -To actually run a coroutine, asyncio provides three main mechanisms: +To actually run a coroutine, asyncio provides the following mechanisms: * The :func:`asyncio.run` function to run the top-level entry point "main()" function (see the above example.) diff --git a/Doc/library/bdb.rst b/Doc/library/bdb.rst index 7e4066cd436ad53..7b74bbd652be389 100644 --- a/Doc/library/bdb.rst +++ b/Doc/library/bdb.rst @@ -20,20 +20,21 @@ The following exception is defined: The :mod:`bdb` module also defines two classes: -.. class:: Breakpoint(self, file, line, temporary=0, cond=None, funcname=None) +.. class:: Breakpoint(self, file, line, temporary=False, cond=None, funcname=None) This class implements temporary breakpoints, ignore counts, disabling and (re-)enabling, and conditionals. Breakpoints are indexed by number through a list called :attr:`bpbynumber` - and by ``(file, line)`` pairs through :attr:`bplist`. The former points to a - single instance of class :class:`Breakpoint`. The latter points to a list of - such instances since there may be more than one breakpoint per line. + and by ``(file, line)`` pairs through :attr:`bplist`. The former points to + a single instance of class :class:`Breakpoint`. The latter points to a list + of such instances since there may be more than one breakpoint per line. - When creating a breakpoint, its associated filename should be in canonical - form. If a *funcname* is defined, a breakpoint hit will be counted when the - first line of that function is executed. A conditional breakpoint always - counts a hit. + When creating a breakpoint, its associated :attr:`file name ` should + be in canonical form. If a :attr:`funcname` is defined, a breakpoint + :attr:`hit ` will be counted when the first line of that function is + executed. A :attr:`conditional ` breakpoint always counts a + :attr:`hit `. :class:`Breakpoint` instances have the following methods: @@ -59,12 +60,12 @@ The :mod:`bdb` module also defines two classes: Return a string with all the information about the breakpoint, nicely formatted: - * The breakpoint number. - * If it is temporary or not. - * Its file,line position. - * The condition that causes a break. - * If it must be ignored the next N times. - * The breakpoint hit count. + * Breakpoint number. + * Temporary status (del or keep). + * File/line position. + * Break condition. + * Number of times to ignore. + * Number of times hit. .. versionadded:: 3.2 @@ -73,6 +74,49 @@ The :mod:`bdb` module also defines two classes: Print the output of :meth:`bpformat` to the file *out*, or if it is ``None``, to standard output. + :class:`Breakpoint` instances have the following attributes: + + .. attribute:: file + + File name of the :class:`Breakpoint`. + + .. attribute:: line + + Line number of the :class:`Breakpoint` within :attr:`file`. + + .. attribute:: temporary + + True if a :class:`Breakpoint` at (file, line) is temporary. + + .. attribute:: cond + + Condition for evaluating a :class:`Breakpoint` at (file, line). + + .. attribute:: funcname + + Function name that defines whether a :class:`Breakpoint` is hit upon + entering the function. + + .. attribute:: enabled + + True if :class:`Breakpoint` is enabled. + + .. attribute:: bpbynumber + + Numeric index for a single instance of a :class:`Breakpoint`. + + .. attribute:: bplist + + Dictionary of :class:`Breakpoint` instances indexed by + (:attr:`file`, :attr:`line`) tuples. + + .. attribute:: ignore + + Number of times to ignore a :class:`Breakpoint`. + + .. attribute:: hits + + Count of the number of times a :class:`Breakpoint` has been hit. .. class:: Bdb(skip=None) @@ -95,9 +139,12 @@ The :mod:`bdb` module also defines two classes: .. method:: canonic(filename) - Auxiliary method for getting a filename in a canonical form, that is, as a - case-normalized (on case-insensitive filesystems) absolute path, stripped - of surrounding angle brackets. + Return canonical form of *filename*. + + For real file names, the canonical form is an operating-system-dependent, + :func:`case-normalized ` :func:`absolute path + `. A *filename* with angle brackets, such as `""` + generated in interactive mode, is returned unchanged. .. method:: reset() @@ -166,45 +213,46 @@ The :mod:`bdb` module also defines two classes: Normally derived classes don't override the following methods, but they may if they want to redefine the definition of stopping and breakpoints. + .. method:: is_skipped_line(module_name) + + Return True if *module_name* matches any skip pattern. + .. method:: stop_here(frame) - This method checks if the *frame* is somewhere below :attr:`botframe` in - the call stack. :attr:`botframe` is the frame in which debugging started. + Return True if *frame* is below the starting frame in the stack. .. method:: break_here(frame) - This method checks if there is a breakpoint in the filename and line - belonging to *frame* or, at least, in the current function. If the - breakpoint is a temporary one, this method deletes it. + Return True if there is an effective breakpoint for this line. + + Check whether a line or function breakpoint exists and is in effect. Delete temporary + breakpoints based on information from :func:`effective`. .. method:: break_anywhere(frame) - This method checks if there is a breakpoint in the filename of the current - frame. + Return True if any breakpoint exists for *frame*'s filename. Derived classes should override these methods to gain control over debugger operation. .. method:: user_call(frame, argument_list) - This method is called from :meth:`dispatch_call` when there is the - possibility that a break might be necessary anywhere inside the called - function. + Called from :meth:`dispatch_call` if a break might stop inside the + called function. .. method:: user_line(frame) - This method is called from :meth:`dispatch_line` when either - :meth:`stop_here` or :meth:`break_here` yields ``True``. + Called from :meth:`dispatch_line` when either :meth:`stop_here` or + :meth:`break_here` returns ``True``. .. method:: user_return(frame, return_value) - This method is called from :meth:`dispatch_return` when :meth:`stop_here` - yields ``True``. + Called from :meth:`dispatch_return` when :meth:`stop_here` returns ``True``. .. method:: user_exception(frame, exc_info) - This method is called from :meth:`dispatch_exception` when - :meth:`stop_here` yields ``True``. + Called from :meth:`dispatch_exception` when :meth:`stop_here` + returns ``True``. .. method:: do_clear(arg) @@ -228,9 +276,9 @@ The :mod:`bdb` module also defines two classes: Stop when returning from the given frame. - .. method:: set_until(frame) + .. method:: set_until(frame, lineno=None) - Stop when the line with the line no greater than the current one is + Stop when the line with the *lineno* greater than the current one is reached or when returning from current frame. .. method:: set_trace([frame]) @@ -253,7 +301,7 @@ The :mod:`bdb` module also defines two classes: breakpoints. These methods return a string containing an error message if something went wrong, or ``None`` if all is well. - .. method:: set_break(filename, lineno, temporary=0, cond, funcname) + .. method:: set_break(filename, lineno, temporary=False, cond=None, funcname=None) Set a new breakpoint. If the *lineno* line doesn't exist for the *filename* passed as argument, return an error message. The *filename* @@ -261,8 +309,8 @@ The :mod:`bdb` module also defines two classes: .. method:: clear_break(filename, lineno) - Delete the breakpoints in *filename* and *lineno*. If none were set, an - error message is returned. + Delete the breakpoints in *filename* and *lineno*. If none were set, + return an error message. .. method:: clear_bpbynumber(arg) @@ -272,12 +320,13 @@ The :mod:`bdb` module also defines two classes: .. method:: clear_all_file_breaks(filename) - Delete all breakpoints in *filename*. If none were set, an error message - is returned. + Delete all breakpoints in *filename*. If none were set, return an error + message. .. method:: clear_all_breaks() - Delete all existing breakpoints. + Delete all existing breakpoints. If none were set, return an error + message. .. method:: get_bpbynumber(arg) @@ -290,7 +339,7 @@ The :mod:`bdb` module also defines two classes: .. method:: get_break(filename, lineno) - Check if there is a breakpoint for *lineno* of *filename*. + Return True if there is a breakpoint for *lineno* in *filename*. .. method:: get_breaks(filename, lineno) @@ -311,16 +360,18 @@ The :mod:`bdb` module also defines two classes: .. method:: get_stack(f, t) - Get a list of records for a frame and all higher (calling) and lower - frames, and the size of the higher part. + Return a list of (frame, lineno) tuples in a stack trace, and a size. + + The most recently called frame is last in the list. The size is the number + of frames below the frame where the debugger was invoked. .. method:: format_stack_entry(frame_lineno, lprefix=': ') - Return a string with information about a stack entry, identified by a - ``(frame, lineno)`` tuple: + Return a string with information about a stack entry, which is a + ``(frame, lineno)`` tuple. The return string contains: - * The canonical form of the filename which contains the frame. - * The function name, or ``""``. + * The canonical filename which contains the frame. + * The function name or ``""``. * The input arguments. * The return value. * The line of code (if it exists). @@ -352,20 +403,34 @@ Finally, the module defines the following functions: .. function:: checkfuncname(b, frame) - Check whether we should break here, depending on the way the breakpoint *b* - was set. + Return True if we should break here, depending on the way the + :class:`Breakpoint` *b* was set. - If it was set via line number, it checks if ``b.line`` is the same as the one - in the frame also passed as argument. If the breakpoint was set via function - name, we have to check we are in the right frame (the right function) and if - we are in its first executable line. + If it was set via line number, it checks if + :attr:`b.line ` is the same as the one in *frame*. + If the breakpoint was set via + :attr:`function name `, we have to check we are in + the right *frame* (the right function) and if we are on its first executable + line. .. function:: effective(file, line, frame) - Determine if there is an effective (active) breakpoint at this line of code. - Return a tuple of the breakpoint and a boolean that indicates if it is ok - to delete a temporary breakpoint. Return ``(None, None)`` if there is no - matching breakpoint. + Return ``(active breakpoint, delete temporary flag)`` or ``(None, None)`` as the + breakpoint to act upon. + + The *active breakpoint* is the first entry in + :attr:`bplist ` for the + (:attr:`file `, :attr:`line `) + (which must exist) that is :attr:`enabled `, for + which :func:`checkfuncname` is True, and that has neither a False + :attr:`condition ` nor positive + :attr:`ignore ` count. The *flag*, meaning that a + temporary breakpoint should be deleted, is False only when the + :attr:`cond ` cannot be evaluated (in which case, + :attr:`ignore ` count is ignored). + + If no such entry exists, then (None, None) is returned. + .. function:: set_trace() diff --git a/Doc/library/bisect.rst b/Doc/library/bisect.rst index 76045ea511a5e79..7856bf67a7b829f 100644 --- a/Doc/library/bisect.rst +++ b/Doc/library/bisect.rst @@ -216,7 +216,7 @@ records in a table:: ... Movie('Aliens', 1986, 'Scott') ... ] - >>> # Find the first movie released on or after 1960 + >>> # Find the first movie released after 1960 >>> by_year = attrgetter('released') >>> movies.sort(key=by_year) >>> movies[bisect(movies, 1960, key=by_year)] diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index 9dec7240d9c50fd..0cab95e1500a665 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -167,6 +167,8 @@ The :mod:`csv` module defines the following classes: All other optional or keyword arguments are passed to the underlying :class:`reader` instance. + If the argument passed to *fieldnames* is an iterator, it will be coerced to a :class:`list`. + .. versionchanged:: 3.6 Returned rows are now of type :class:`OrderedDict`. @@ -209,6 +211,8 @@ The :mod:`csv` module defines the following classes: Note that unlike the :class:`DictReader` class, the *fieldnames* parameter of the :class:`DictWriter` class is not optional. + If the argument passed to *fieldnames* is an iterator, it will be coerced to a :class:`list`. + A short usage example:: import csv diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 475737144d40c63..9546696e1c3d76a 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1068,18 +1068,16 @@ Accessing values exported from dlls ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some shared libraries not only export functions, they also export variables. An -example in the Python library itself is the :c:data:`Py_OptimizeFlag`, an integer -set to 0, 1, or 2, depending on the :option:`-O` or :option:`-OO` flag given on -startup. +example in the Python library itself is the :c:data:`Py_Version`, Python +runtime version number encoded in a single constant integer. :mod:`ctypes` can access values like this with the :meth:`in_dll` class methods of the type. *pythonapi* is a predefined symbol giving access to the Python C api:: - >>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag") - >>> print(opt_flag) - c_long(0) - >>> + >>> version = ctypes.c_int.in_dll(ctypes.pythonapi, "Py_Version") + >>> print(hex(version.value)) + 0x30c00a0 If the interpreter would have been started with :option:`-O`, the sample would have printed ``c_long(1)``, or ``c_long(2)`` if :option:`-OO` would have been diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0f042374b6472d8..c3a66a4674b10ac 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2443,6 +2443,11 @@ convenience. These parameters all correspond to ISO 8601 date values. | | Week 01 is the week containing | | | | | Jan 4. | | | +-----------+--------------------------------+------------------------+-------+ +| ``%:z`` | UTC offset in the form | (empty), +00:00, | \(6) | +| | ``±HH:MM[:SS[.ffffff]]`` | -04:00, +10:30, | | +| | (empty string if the object is | +06:34:15, | | +| | naive). | -03:07:12.345216 | | ++-----------+--------------------------------+------------------------+-------+ These may not be available on all platforms when used with the :meth:`strftime` method. The ISO 8601 year and ISO 8601 week directives are not interchangeable @@ -2458,6 +2463,9 @@ differences between platforms in handling of unsupported format specifiers. .. versionadded:: 3.6 ``%G``, ``%u`` and ``%V`` were added. +.. versionadded:: 3.12 + ``%:z`` was added. + Technical Detail ^^^^^^^^^^^^^^^^ @@ -2530,8 +2538,8 @@ Notes: available). (6) - For a naive object, the ``%z`` and ``%Z`` format codes are replaced by empty - strings. + For a naive object, the ``%z``, ``%:z`` and ``%Z`` format codes are replaced + by empty strings. For an aware object: @@ -2557,6 +2565,10 @@ Notes: For example, ``'+01:00:00'`` will be parsed as an offset of one hour. In addition, providing ``'Z'`` is identical to ``'+00:00'``. + ``%:z`` + Behaves exactly as ``%z``, but has a colon separator added between + hours, minutes and seconds. + ``%Z`` In :meth:`strftime`, ``%Z`` is replaced by an empty string if :meth:`tzname` returns ``None``; otherwise ``%Z`` is replaced by the diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 63b064e7b444ecb..47e4bf600721701 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -567,6 +567,17 @@ the original TOS1. .. versionchanged:: 3.11 Exception representation on the stack now consist of one, not three, items. + +.. opcode:: CLEANUP_THROW + + Handles an exception raised during a :meth:`~generator.throw` or + :meth:`~generator.close` call through the current frame. If TOS is an + instance of :exc:`StopIteration`, pop three values from the stack and push + its ``value`` member. Otherwise, re-raise TOS. + + .. versionadded:: 3.12 + + .. opcode:: BEFORE_ASYNC_WITH Resolves ``__aenter__`` and ``__aexit__`` from the object on top of the @@ -988,60 +999,48 @@ iterations of the loop. .. versionadded:: 3.11 -.. opcode:: POP_JUMP_FORWARD_IF_TRUE (delta) +.. opcode:: POP_JUMP_IF_TRUE (delta) If TOS is true, increments the bytecode counter by *delta*. TOS is popped. - .. versionadded:: 3.11 - - -.. opcode:: POP_JUMP_BACKWARD_IF_TRUE (delta) - - If TOS is true, decrements the bytecode counter by *delta*. TOS is popped. - - .. versionadded:: 3.11 + .. versionchanged:: 3.11 + The oparg is now a relative delta rather than an absolute target. + This opcode is a pseudo-instruction, replaced in final bytecode by + the directed versions (forward/backward). + .. versionchanged:: 3.12 + This is no longer a pseudo-instruction. -.. opcode:: POP_JUMP_FORWARD_IF_FALSE (delta) +.. opcode:: POP_JUMP_IF_FALSE (delta) If TOS is false, increments the bytecode counter by *delta*. TOS is popped. - .. versionadded:: 3.11 - - -.. opcode:: POP_JUMP_BACKWARD_IF_FALSE (delta) - - If TOS is false, decrements the bytecode counter by *delta*. TOS is popped. - - .. versionadded:: 3.11 + .. versionchanged:: 3.11 + The oparg is now a relative delta rather than an absolute target. + This opcode is a pseudo-instruction, replaced in final bytecode by + the directed versions (forward/backward). + .. versionchanged:: 3.12 + This is no longer a pseudo-instruction. -.. opcode:: POP_JUMP_FORWARD_IF_NOT_NONE (delta) +.. opcode:: POP_JUMP_IF_NOT_NONE (delta) If TOS is not ``None``, increments the bytecode counter by *delta*. TOS is popped. .. versionadded:: 3.11 - -.. opcode:: POP_JUMP_BACKWARD_IF_NOT_NONE (delta) - - If TOS is not ``None``, decrements the bytecode counter by *delta*. TOS is popped. - - .. versionadded:: 3.11 + .. versionchanged:: 3.12 + This is no longer a pseudo-instruction. -.. opcode:: POP_JUMP_FORWARD_IF_NONE (delta) +.. opcode:: POP_JUMP_IF_NONE (delta) If TOS is ``None``, increments the bytecode counter by *delta*. TOS is popped. .. versionadded:: 3.11 - -.. opcode:: POP_JUMP_BACKWARD_IF_NONE (delta) - - If TOS is ``None``, decrements the bytecode counter by *delta*. TOS is popped. - - .. versionadded:: 3.11 + .. versionchanged:: 3.12 + This is no longer a pseudo-instruction. .. opcode:: JUMP_IF_TRUE_OR_POP (delta) @@ -1344,10 +1343,14 @@ iterations of the loop. .. versionadded:: 3.11 -.. opcode:: SEND +.. opcode:: SEND (delta) + + Equivalent to ``TOS = TOS1.send(TOS)``. Used in ``yield from`` and ``await`` + statements. - Sends ``None`` to the sub-generator of this generator. - Used in ``yield from`` and ``await`` statements. + If the call raises :exc:`StopIteration`, pop both items, push the + exception's ``value`` attribute, and increment the bytecode counter by + *delta*. .. versionadded:: 3.11 @@ -1418,10 +1421,6 @@ but are replaced by real opcodes or removed before bytecode is generated. .. opcode:: JUMP .. opcode:: JUMP_NO_INTERRUPT -.. opcode:: POP_JUMP_IF_FALSE -.. opcode:: POP_JUMP_IF_TRUE -.. opcode:: POP_JUMP_IF_NONE -.. opcode:: POP_JUMP_IF_NOT_NONE Undirected relative jump instructions which are replaced by their directed (forward/backward) counterparts by the assembler. diff --git a/Doc/library/errno.rst b/Doc/library/errno.rst index da4e964ac3f0c91..5122c69697ef914 100644 --- a/Doc/library/errno.rst +++ b/Doc/library/errno.rst @@ -663,6 +663,6 @@ defined by the module. The specific list of defined symbols is available as Capabilities insufficient. This error is mapped to the exception :exc:`PermissionError`. - .. availability:: WASI + .. availability:: WASI, FreeBSD .. versionadded:: 3.11.1 diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst index 5f0ecf1f135ea5c..3751800b3b11189 100644 --- a/Doc/library/fractions.rst +++ b/Doc/library/fractions.rst @@ -98,6 +98,9 @@ another rational number, or from a string. :class:`Fraction` implements ``__int__`` now to satisfy ``typing.SupportsInt`` instance checks. + .. versionchanged:: 3.12 + Space is allowed around the slash for string inputs: `Fraction('2 / 3')`. + .. attribute:: numerator Numerator of the Fraction in lowest term. diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index da7de18722f87e3..b9cf02e87eb6143 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -164,6 +164,8 @@ are always available. They are listed here in alphabetical order. :func:`sys.breakpointhook` can be set to some other function and :func:`breakpoint` will automatically call that, allowing you to drop into the debugger of choice. + If :func:`sys.breakpointhook` is not accessible, this function will + raise :exc:`RuntimeError`. .. audit-event:: builtins.breakpoint breakpointhook breakpoint @@ -908,6 +910,13 @@ are always available. They are listed here in alphabetical order. .. versionchanged:: 3.11 The delegation to :meth:`__trunc__` is deprecated. + .. versionchanged:: 3.12 + :class:`int` string inputs and string representations can be limited to + help avoid denial of service attacks. A :exc:`ValueError` is raised when + the limit is exceeded while converting a string *x* to an :class:`int` or + when converting an :class:`int` into a string would exceed the limit. + See the :ref:`integer string conversion length limitation + ` documentation. .. function:: isinstance(object, classinfo) @@ -1513,6 +1522,8 @@ are always available. They are listed here in alphabetical order. 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 function returns for its instances by defining a :meth:`__repr__` method. + If :func:`sys.displayhook` is not accessible, this function will raise + :exc:`RuntimeError`. .. function:: reversed(seq) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 00aca09bc7af453..47cbe59fa492229 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -49,6 +49,9 @@ The :mod:`functools` module defines the following functions: >>> factorial(12) # makes two new recursive calls, the other 10 are cached 479001600 + The cache is threadsafe so the wrapped function can be used in multiple + threads. + .. versionadded:: 3.9 @@ -140,6 +143,9 @@ The :mod:`functools` module defines the following functions: *maxsize* most recent calls. It can save time when an expensive or I/O bound function is periodically called with the same arguments. + The cache is threadsafe so the wrapped function can be used in multiple + threads. + Since a dictionary is used to cache results, the positional and keyword arguments to the function must be hashable. diff --git a/Doc/library/http.rst b/Doc/library/http.rst index 5895a41d849bd19..9d002dc33ccb8d4 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -137,6 +137,31 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as .. versionadded:: 3.9 Added ``103 EARLY_HINTS``, ``418 IM_A_TEAPOT`` and ``425 TOO_EARLY`` status codes. +HTTP status category +-------------------- + +.. versionadded:: 3.12 + +The enum values have several properties to indicate the HTTP status category: + +==================== ======================== =============================== +Property Indicates that Details +==================== ======================== =============================== +``is_informational`` ``100 <= status <= 199`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_success`` ``200 <= status <= 299`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_redirection`` ``300 <= status <= 399`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_client_error`` ``400 <= status <= 499`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_server_error`` ``500 <= status <= 599`` HTTP/1.1 :rfc:`7231`, Section 6 +==================== ======================== =============================== + + Usage:: + + >>> from http import HTTPStatus + >>> HTTPStatus.OK.is_success + True + >>> HTTPStatus.OK.is_client_error + False + .. class:: HTTPMethod .. versionadded:: 3.11 diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 753e6c1e3b9b46a..97a70646a93cabc 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -1052,8 +1052,12 @@ Text I/O The initial value of the buffer can be set by providing *initial_value*. If newline translation is enabled, newlines will be encoded as if by - :meth:`~TextIOBase.write`. The stream is positioned at the start of - the buffer. + :meth:`~TextIOBase.write`. The stream is positioned at the start of the + buffer which emulates opening an existing file in a `w+` mode, making it + ready for an immediate write from the beginning or for a write that + would overwrite the initial value. To emulate opening a file in an `a+` + mode ready for appending, use `f.seek(0, io.SEEK_END)` to reposition the + stream at the end of the buffer. The *newline* argument works like that of :class:`TextIOWrapper`, except that when writing output to the stream, if *newline* is ``None``, diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 416c4eca5eb48a9..c35ff8c4343fc99 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -668,7 +668,7 @@ loops that truncate the stream. the tee objects being informed. ``tee`` iterators are not threadsafe. A :exc:`RuntimeError` may be - raised when using simultaneously iterators returned by the same :func:`tee` + raised when simultaneously using iterators returned by the same :func:`tee` call, even if the original *iterable* is threadsafe. This itertool may require significant auxiliary storage (depending on how @@ -800,6 +800,18 @@ which incur interpreter overhead. window.append(x) yield sum(map(operator.mul, kernel, window)) + def polynomial_from_roots(roots): + """Compute a polynomial's coefficients from its roots. + + (x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60 + """ + # polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60] + roots = list(map(operator.neg, roots)) + return [ + sum(map(math.prod, combinations(roots, k))) + for k in range(len(roots) + 1) + ] + def flatten(list_of_lists): "Flatten one level of nesting" return chain.from_iterable(list_of_lists) @@ -1137,6 +1149,13 @@ which incur interpreter overhead. >>> list(convolve(data, [1, -2, 1])) [20, 0, -36, 24, -20, 20, -20, -4, 16] + >>> polynomial_from_roots([5, -4, 3]) + [1, -4, -17, 60] + >>> factored = lambda x: (x - 5) * (x + 4) * (x - 3) + >>> expanded = lambda x: x**3 -4*x**2 -17*x + 60 + >>> all(factored(x) == expanded(x) for x in range(-10, 11)) + True + >>> list(flatten([('a', 'b'), (), ('c', 'd', 'e'), ('f',), ('g', 'h', 'i')])) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] diff --git a/Doc/library/json.rst b/Doc/library/json.rst index f65be85d31bf194..d05d62e78cc71e4 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -9,6 +9,11 @@ **Source code:** :source:`Lib/json/__init__.py` +.. testsetup:: * + + import json + from json import AttrDict + -------------- `JSON (JavaScript Object Notation) `_, specified by @@ -18,6 +23,11 @@ is a lightweight data interchange format inspired by `JavaScript `_ object literal syntax (although it is not a strict subset of JavaScript [#rfc-errata]_ ). +.. warning:: + Be cautious when parsing JSON data from untrusted sources. A malicious + JSON string may cause the decoder to consume considerable CPU and memory + resources. Limiting the size of data to be parsed is recommended. + :mod:`json` exposes an API familiar to users of the standard library :mod:`marshal` and :mod:`pickle` modules. @@ -248,6 +258,12 @@ Basic Usage be used to use another datatype or parser for JSON integers (e.g. :class:`float`). + .. versionchanged:: 3.12 + The default *parse_int* of :func:`int` now limits the maximum length of + the integer string via the interpreter's :ref:`integer string + conversion length limitation ` to help avoid denial + of service attacks. + *parse_constant*, if specified, will be called with one of the following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This can be used to raise an exception if invalid JSON numbers @@ -532,6 +548,44 @@ Exceptions .. versionadded:: 3.5 +.. class:: AttrDict(**kwargs) + AttrDict(mapping, **kwargs) + AttrDict(iterable, **kwargs) + + Subclass of :class:`dict` object that also supports attribute style dotted access. + + This class is intended for use with the :attr:`object_hook` in + :func:`json.load` and :func:`json.loads`:: + + .. doctest:: + + >>> json_string = '{"mercury": 88, "venus": 225, "earth": 365, "mars": 687}' + >>> orbital_period = json.loads(json_string, object_hook=AttrDict) + >>> orbital_period['earth'] # Dict style lookup + 365 + >>> orbital_period.earth # Attribute style lookup + 365 + >>> orbital_period.keys() # All dict methods are present + dict_keys(['mercury', 'venus', 'earth', 'mars']) + + Attribute style access only works for keys that are valid attribute + names. In contrast, dictionary style access works for all keys. For + example, ``d.two words`` contains a space and is not syntactically + valid Python, so ``d["two words"]`` should be used instead. + + If a key has the same name as a dictionary method, then a dictionary + lookup finds the key and an attribute lookup finds the method: + + .. doctest:: + + >>> d = AttrDict(items=50) + >>> d['items'] # Lookup the key + 50 + >>> d.items() # Call the method + dict_items([('items', 50)]) + + .. versionadded:: 3.12 + Standard Compliance and Interoperability ---------------------------------------- diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 9f9361a2fd569e2..9b82c1f75e3f073 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -534,6 +534,25 @@ mnemonic that the corresponding value is a callable. The ``filters`` member of ``handlers`` and ``loggers`` can take filter instances in addition to ids. +You can also specify a special key ``'.'`` whose value is a dictionary is a +mapping of attribute names to values. If found, the specified attributes will +be set on the user-defined object before it is returned. Thus, with the +following configuration:: + + { + '()' : 'my.package.customFormatterFactory', + 'bar' : 'baz', + 'spam' : 99.9, + 'answer' : 42, + '.' { + 'foo': 'bar', + 'baz': 'bozz' + } + } + +the returned formatter will have attribute ``foo`` set to ``'bar'`` and +attribute ``baz`` set to ``'bozz'``. + .. _logging-config-dict-externalobj: diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 0dc05255db9cb89..f3b26e726aafc7f 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -572,6 +572,13 @@ over UDP sockets. Returns a new instance of the :class:`DatagramHandler` class intended to communicate with a remote machine whose address is given by *host* and *port*. + .. note:: As UDP is not a streaming protocol, there is no persistent connection + between an instance of this handler and *host*. For this reason, when using a + network socket, a DNS lookup might have to be made each time an event is + logged, which can introduce some latency into the system. If this affects you, + you can do a lookup yourself and initialize this handler using the looked-up IP + address rather than the hostname. + .. versionchanged:: 3.4 If ``port`` is specified as ``None``, a Unix domain socket is created using the value in ``host`` - otherwise, a UDP socket is created. @@ -629,6 +636,12 @@ supports sending logging messages to a remote or local Unix syslog. application needs to run on several platforms). On Windows, you pretty much have to use the UDP option. + .. note:: On macOS 12.x (Monterey), Apple has changed the behaviour of their + syslog daemon - it no longer listens on a domain socket. Therefore, you cannot + expect :class:`SysLogHandler` to work on this system. + + See :gh:`91070` for more information. + .. versionchanged:: 3.2 *socktype* was added. @@ -1047,6 +1060,20 @@ possible, while any potentially slow operations (such as sending an email via the record to a dict or JSON string, or send a modified copy of the record while leaving the original intact. + .. note:: The base implementation formats the message with arguments, sets + the ``message`` and ``msg`` attributes to the formatted message and + sets the ``args`` and ``exc_text`` attributes to ``None`` to allow + pickling and to prevent further attempts at formatting. This means + that a handler on the :class:`QueueListener` side won't have the + information to do custom formatting, e.g. of exceptions. You may wish + to subclass ``QueueHandler`` and override this method to e.g. avoid + setting ``exc_text`` to ``None``. Note that the ``message`` / ``msg`` + / ``args`` changes are related to ensuring the record is pickleable, + and you might or might not be able to avoid doing that depending on + whether your ``args`` are pickleable. (Note that you may have to + consider not only your own code but also code in any libraries that + you use.) + .. method:: enqueue(record) Enqueues the record on the queue using ``put_nowait()``; you may diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 319340a39350e80..c3806b6f5bf81cd 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -170,6 +170,18 @@ is the module's name in the Python package namespace. .. versionadded:: 3.2 + .. method:: Logger.getChildren() + + Returns a set of loggers which are immediate children of this logger. So for + example ``logging.getLogger().getChildren()`` might return a set containing + loggers named ``foo`` and ``bar``, but a logger named ``foo.bar`` wouldn't be + included in the set. Likewise, ``logging.getLogger('foo').getChildren()`` might + return a set including a logger named ``foo.bar``, but it wouldn't include one + named ``foo.bar.baz``. + + .. versionadded:: 3.12 + + .. method:: Logger.debug(msg, *args, **kwargs) Logs a message with level :const:`DEBUG` on this logger. The *msg* is the diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index eaa946462a11c68..caf24a35fdfc849 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -45,6 +45,16 @@ will print to standard output :: [1, 4, 9] +.. seealso:: + + :class:`concurrent.futures.ProcessPoolExecutor` offers a higher level interface + to push tasks to a background process without blocking execution of the + calling process. Compared to using the :class:`~multiprocessing.pool.Pool` + interface directly, the :mod:`concurrent.futures` API more readily allows + the submission of work to the underlying process pool to be separated from + waiting for the results. + + The :class:`Process` class ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index b12f82ed75a6f8f..b3dce151aee2893 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -58,11 +58,14 @@ The numeric tower .. class:: Rational - Subtypes :class:`Real` and adds - :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, which - should be in lowest terms. With these, it provides a default for + Subtypes :class:`Real` and adds :attr:`~Rational.numerator` and + :attr:`~Rational.denominator` properties. It also provides a default for :func:`float`. + The :attr:`~Rational.numerator` and :attr:`~Rational.denominator` values + should be instances of :class:`Integral` and should be in lowest terms with + :attr:`~Rational.denominator` positive. + .. attribute:: numerator Abstract. diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index f7d7745eef52e7c..1375ce1aef953a5 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -1038,7 +1038,7 @@ call fails (for example because the path doesn't exist). # Delete everything reachable from the directory "top". # CAUTION: This is dangerous! For example, if top == Path('/'), # it could delete all of your files. - for root, dirs, files in top.walk(topdown=False): + for root, dirs, files in top.walk(top_down=False): for name in files: (root / name).unlink() for name in dirs: diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 67f8b31f11f4bb5..0dfecc5f9d12e38 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -8,11 +8,17 @@ **Source code:** :source:`Lib/sqlite3/` +.. Make sure we always doctest the tutorial with an empty database. -.. _sqlite3-intro: +.. testsetup:: + + import sqlite3 + src = sqlite3.connect(":memory:", isolation_level=None) + dst = sqlite3.connect("tutorial.db", isolation_level=None) + src.backup(dst) + del src, dst -Introduction ------------- +.. _sqlite3-intro: SQLite is a C library that provides a lightweight disk-based database that doesn't require a separate server process and allows accessing the database @@ -21,13 +27,13 @@ SQLite for internal data storage. It's also possible to prototype an application using SQLite and then port the code to a larger database such as PostgreSQL or Oracle. -The sqlite3 module was written by Gerhard Häring. It provides an SQL interface +The :mod:`!sqlite3` module was written by Gerhard Häring. It provides an SQL interface compliant with the DB-API 2.0 specification described by :pep:`249`, and requires SQLite 3.7.15 or newer. This document includes four main sections: -* :ref:`sqlite3-tutorial` teaches how to use the sqlite3 module. +* :ref:`sqlite3-tutorial` teaches how to use the :mod:`!sqlite3` module. * :ref:`sqlite3-reference` describes the classes and functions this module defines. * :ref:`sqlite3-howtos` details how to handle specific tasks. @@ -47,85 +53,194 @@ This document includes four main sections: PEP written by Marc-André Lemburg. +.. We use the following practises for SQL code: + - UPPERCASE for keywords + - snake_case for schema + - single quotes for string literals + - singular for table names + - if needed, use double quotes for table and column names + .. _sqlite3-tutorial: Tutorial -------- -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:: +In this tutorial, you will create a database of Monty Python movies +using basic :mod:`!sqlite3` functionality. +It assumes a fundamental understanding of database concepts, +including `cursors`_ and `transactions`_. + +First, we need to create a new database and open +a database connection to allow :mod:`!sqlite3` to work with it. +Call :func:`sqlite3.connect` to to create a connection to +the database :file:`tutorial.db` in the current working directory, +implicitly creating it if it does not exist: + +.. testcode:: import sqlite3 - con = sqlite3.connect('example.db') + con = sqlite3.connect("tutorial.db") + +The returned :class:`Connection` object ``con`` +represents the connection to the on-disk database. -The special path name ``:memory:`` can be provided to create a temporary -database in RAM. +In order to execute SQL statements and fetch results from SQL queries, +we will need to use a database cursor. +Call :meth:`con.cursor() ` to create the :class:`Cursor`: -Once a :class:`Connection` has been established, create a :class:`Cursor` object -and call its :meth:`~Cursor.execute` method to perform SQL commands:: +.. testcode:: cur = con.cursor() - # Create table - cur.execute('''CREATE TABLE stocks - (date text, trans text, symbol text, qty real, price real)''') +Now that we've got a database connection and a cursor, +we can create a database table ``movie`` with columns for title, +release year, and review score. +For simplicity, we can just use column names in the table declaration -- +thanks to the `flexible typing`_ feature of SQLite, +specifying the data types is optional. +Execute the ``CREATE TABLE`` statement +by calling :meth:`cur.execute(...) `: + +.. testcode:: + + cur.execute("CREATE TABLE movie(title, year, score)") + +.. Ideally, we'd use sqlite_schema instead of sqlite_master below, + but SQLite versions older than 3.33.0 do not recognise that variant. - # Insert a row of data - cur.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)") +We can verify that the new table has been created by querying +the ``sqlite_master`` table built-in to SQLite, +which should now contain an entry for the ``movie`` table definition +(see `The Schema Table`_ for details). +Execute that query by calling :meth:`cur.execute(...) `, +assign the result to ``res``, +and call :meth:`res.fetchone() ` to fetch the resulting row: + +.. doctest:: + + >>> res = cur.execute("SELECT name FROM sqlite_master") + >>> res.fetchone() + ('movie',) + +We can see that the table has been created, +as the query returns a :class:`tuple` containing the table's name. +If we query ``sqlite_master`` for a non-existent table ``spam``, +:meth:`!res.fetchone()` will return ``None``: + +.. doctest:: + + >>> res = cur.execute("SELECT name FROM sqlite_master WHERE name='spam'") + >>> res.fetchone() is None + True + +Now, add two rows of data supplied as SQL literals +by executing an ``INSERT`` statement, +once again by calling :meth:`cur.execute(...) `: + +.. testcode:: + + cur.execute(""" + INSERT INTO movie VALUES + ('Monty Python and the Holy Grail', 1975, 8.2), + ('And Now for Something Completely Different', 1971, 7.5) + """) + +The ``INSERT`` statement implicitly opens a transaction, +which needs to be committed before changes are saved in the database +(see :ref:`sqlite3-controlling-transactions` for details). +Call :meth:`con.commit() ` on the connection object +to commit the transaction: + +.. testcode:: - # Save (commit) the changes con.commit() - # We can also close the connection if we are done with it. - # Just be sure any changes have been committed or they will be lost. - con.close() +We can verify that the data was inserted correctly +by executing a ``SELECT`` query. +Use the now-familiar :meth:`cur.execute(...) ` to +assign the result to ``res``, +and call :meth:`res.fetchall() ` to return all resulting rows: -The saved data is persistent: it can be reloaded in a subsequent session even -after restarting the Python interpreter:: +.. doctest:: - import sqlite3 - con = sqlite3.connect('example.db') - cur = con.cursor() + >>> res = cur.execute("SELECT score FROM movie") + >>> res.fetchall() + [(8.2,), (7.5,)] -At this point, our database only contains one row:: +The result is a :class:`list` of two :class:`!tuple`\s, one per row, +each containing that row's ``score`` value. - >>> res = cur.execute('SELECT count(rowid) FROM stocks') - >>> print(res.fetchone()) - (1,) +Now, insert three more rows by calling +:meth:`cur.executemany(...) `: -The result is a one-item :class:`tuple`: -one row, with one column. -Now, let us insert three more rows of data, -using :meth:`~Cursor.executemany`:: +.. testcode:: - >>> data = [ - ... ('2006-03-28', 'BUY', 'IBM', 1000, 45.0), - ... ('2006-04-05', 'BUY', 'MSFT', 1000, 72.0), - ... ('2006-04-06', 'SELL', 'IBM', 500, 53.0), - ... ] - >>> cur.executemany('INSERT INTO stocks VALUES(?, ?, ?, ?, ?)', data) + data = [ + ("Monty Python Live at the Hollywood Bowl", 1982, 7.9), + ("Monty Python's The Meaning of Life", 1983, 7.5), + ("Monty Python's Life of Brian", 1979, 8.0), + ] + cur.executemany("INSERT INTO movie VALUES(?, ?, ?)", data) + con.commit() # Remember to commit the transaction after executing INSERT. -Notice that we used ``?`` placeholders to bind *data* to the query. +Notice that ``?`` placeholders are used to bind ``data`` to the query. Always use placeholders instead of :ref:`string formatting ` to bind Python values to SQL statements, -to avoid `SQL injection attacks`_. -See the :ref:`placeholders how-to ` for more details. +to avoid `SQL injection attacks`_ +(see :ref:`sqlite3-placeholders` for more details). + +We can verify that the new rows were inserted +by executing a ``SELECT`` query, +this time iterating over the results of the query: -Then, retrieve the data by iterating over the result of a ``SELECT`` statement:: +.. doctest:: - >>> for row in cur.execute('SELECT * FROM stocks ORDER BY price'): + >>> for row in cur.execute("SELECT year, title FROM movie ORDER BY year"): ... print(row) + (1971, 'And Now for Something Completely Different') + (1975, 'Monty Python and the Holy Grail') + (1979, "Monty Python's Life of Brian") + (1982, 'Monty Python Live at the Hollywood Bowl') + (1983, "Monty Python's The Meaning of Life") + +Each row is a two-item :class:`tuple` of ``(year, title)``, +matching the columns selected in the query. + +Finally, verify that the database has been written to disk +by calling :meth:`con.close() ` +to close the existing connection, opening a new one, +creating a new cursor, then querying the database: + +.. doctest:: - ('2006-01-05', 'BUY', 'RHAT', 100, 35.14) - ('2006-03-28', 'BUY', 'IBM', 1000, 45.0) - ('2006-04-06', 'SELL', 'IBM', 500, 53.0) - ('2006-04-05', 'BUY', 'MSFT', 1000, 72.0) + >>> con.close() + >>> new_con = sqlite3.connect("tutorial.db") + >>> new_cur = new_con.cursor() + >>> res = new_cur.execute("SELECT title, year FROM movie ORDER BY score DESC") + >>> title, year = res.fetchone() + >>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}') + The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975 -You've now created an SQLite database using the :mod:`!sqlite3` module. +You've now created an SQLite database using the :mod:`!sqlite3` module, +inserted data and retrieved values from it in multiple ways. .. _SQL injection attacks: https://en.wikipedia.org/wiki/SQL_injection +.. _The Schema Table: https://www.sqlite.org/schematab.html +.. _cursors: https://en.wikipedia.org/wiki/Cursor_(databases) +.. _flexible typing: https://www.sqlite.org/flextypegood.html +.. _sqlite_master: https://www.sqlite.org/schematab.html +.. _transactions: https://en.wikipedia.org/wiki/Database_transaction + +.. seealso:: + + * :ref:`sqlite3-howtos` for further reading: + + * :ref:`sqlite3-placeholders` + * :ref:`sqlite3-adapters` + * :ref:`sqlite3-converters` + * :ref:`sqlite3-connection-context-manager` + * :ref:`sqlite3-explanation` for in-depth background on transaction control. .. _sqlite3-reference: @@ -228,7 +343,9 @@ Module functions other than checking that there are no unclosed string literals and the statement is terminated by a semicolon. - For example:: + For example: + + .. doctest:: >>> sqlite3.complete_statement("SELECT foo FROM bar;") True @@ -252,22 +369,27 @@ Module functions to disable the feature again. Register an :func:`unraisable hook handler ` for an - improved debug experience:: + improved debug experience: + + .. testsetup:: sqlite3.trace + + import sqlite3 + + .. doctest:: sqlite3.trace - >>> import sqlite3 >>> sqlite3.enable_callback_tracebacks(True) - >>> cx = sqlite3.connect(":memory:") - >>> cx.set_trace_callback(lambda stmt: 5/0) - >>> cx.execute("select 1") - Exception ignored in: at 0x10b4e3ee0> - Traceback (most recent call last): - File "", line 1, in - ZeroDivisionError: division by zero + >>> con = sqlite3.connect(":memory:") + >>> def evil_trace(stmt): + ... 5/0 + >>> con.set_trace_callback(evil_trace) + >>> def debug(unraisable): + ... print(f"{unraisable.exc_value!r} in callback {unraisable.object.__name__}") + ... print(f"Error message: {unraisable.err_msg}") >>> import sys - >>> sys.unraisablehook = lambda unraisable: print(unraisable) - >>> cx.execute("select 1") - UnraisableHookArgs(exc_type=, exc_value=ZeroDivisionError('division by zero'), exc_traceback=, err_msg=None, object= at 0x10b4e3ee0>) - + >>> sys.unraisablehook = debug + >>> cur = con.execute("SELECT 1") + ZeroDivisionError('division by zero') in callback evil_trace + Error message: None .. function:: register_adapter(type, adapter, /) @@ -332,6 +454,17 @@ Module constants This flag may be combined with :const:`PARSE_COLNAMES` using the ``|`` (bitwise or) operator. +.. data:: SQLITE_OK + SQLITE_DENY + SQLITE_IGNORE + + Flags that should be returned by the *authorizer_callback* callable + passed to :meth:`Connection.set_authorizer`, to indicate whether: + + * Access is allowed (:const:`!SQLITE_OK`), + * The SQL statement should be aborted with an error (:const:`!SQLITE_DENY`) + * The column should be treated as a ``NULL`` value (:const:`!SQLITE_IGNORE`) + .. data:: apilevel String constant stating the supported DB-API level. Required by the DB-API. @@ -460,6 +593,80 @@ Connection objects .. versionadded:: 3.2 + .. attribute:: row_factory + + A callable that accepts two arguments, + a :class:`Cursor` object and the raw row results as a :class:`tuple`, + and returns a custom object representing an SQLite row. + + Example: + + .. doctest:: + + >>> def dict_factory(cursor, row): + ... col_names = [col[0] for col in cursor.description] + ... return {key: value for key, value in zip(col_names, row)} + >>> con = sqlite3.connect(":memory:") + >>> con.row_factory = dict_factory + >>> for row in con.execute("SELECT 1 AS a, 2 AS b"): + ... print(row) + {'a': 1, 'b': 2} + + If returning a tuple doesn't suffice and you want name-based access to + columns, you should consider setting :attr:`row_factory` to the + highly optimized :class:`sqlite3.Row` type. :class:`Row` provides both + index-based and case-insensitive name-based access to columns with almost no + memory overhead. It will probably be better than your own custom + dictionary-based approach or even a db_row based solution. + + .. XXX what's a db_row-based solution? + + .. attribute:: text_factory + + A callable that accepts a :class:`bytes` parameter and returns a text + representation of it. + The callable is invoked for SQLite values with the ``TEXT`` data type. + By default, this attribute is set to :class:`str`. + If you want to return ``bytes`` instead, set *text_factory* to ``bytes``. + + Example: + + .. testcode:: + + con = sqlite3.connect(":memory:") + cur = con.cursor() + + AUSTRIA = "Österreich" + + # by default, rows are returned as str + cur.execute("SELECT ?", (AUSTRIA,)) + row = cur.fetchone() + assert row[0] == AUSTRIA + + # but we can make sqlite3 always return bytestrings ... + con.text_factory = bytes + cur.execute("SELECT ?", (AUSTRIA,)) + row = cur.fetchone() + assert type(row[0]) is bytes + # the bytestrings will be encoded in UTF-8, unless you stored garbage in the + # database ... + assert row[0] == AUSTRIA.encode("utf-8") + + # we can also implement a custom text_factory ... + # here we implement one that appends "foo" to all strings + con.text_factory = lambda x: x.decode("utf-8") + "foo" + cur.execute("SELECT ?", ("bar",)) + row = cur.fetchone() + assert row[0] == "barfoo" + + con.close() + + .. attribute:: total_changes + + Return the total number of database rows that have been modified, inserted, or + deleted since the database connection was opened. + + .. method:: cursor(factory=Cursor) Create and return a :class:`Cursor` object. @@ -467,7 +674,7 @@ Connection objects supplied, this must be a callable returning an instance of :class:`Cursor` or its subclasses. - .. method:: blobopen(table, column, row, /, *, readonly=False, name="main") + .. method:: blobopen(table, column, row, /, \*, readonly=False, name="main") Open a :class:`Blob` handle to an existing :abbr:`BLOB (Binary Large OBject)`. @@ -537,7 +744,7 @@ Connection objects :meth:`~Cursor.executescript` on it with the given *sql_script*. Return the new cursor object. - .. method:: create_function(name, narg, func, *, deterministic=False) + .. method:: create_function(name, narg, func, \*, deterministic=False) Create or remove a user-defined SQL function. @@ -568,7 +775,16 @@ Connection objects Example: - .. literalinclude:: ../includes/sqlite3/md5func.py + .. doctest:: + + >>> import hashlib + >>> def md5sum(t): + ... return hashlib.md5(t).hexdigest() + >>> con = sqlite3.connect(":memory:") + >>> con.create_function("md5", 1, md5sum) + >>> for row in con.execute("SELECT md5(?)", (b"foo",)): + ... print(row) + ('acbd18db4cc2f85cedef654fccc4a4d8',) .. method:: create_aggregate(name, /, n_arg, aggregate_class) @@ -597,7 +813,32 @@ Connection objects Example: - .. literalinclude:: ../includes/sqlite3/mysumaggr.py + .. testcode:: + + class MySum: + def __init__(self): + self.count = 0 + + def step(self, value): + self.count += value + + def finalize(self): + return self.count + + con = sqlite3.connect(":memory:") + con.create_aggregate("mysum", 1, MySum) + cur = con.execute("CREATE TABLE test(i)") + cur.execute("INSERT INTO test(i) VALUES(1)") + cur.execute("INSERT INTO test(i) VALUES(2)") + cur.execute("SELECT mysum(i) FROM test") + print(cur.fetchone()[0]) + + con.close() + + .. testoutput:: + :hide: + + 3 .. method:: create_window_function(name, num_params, aggregate_class, /) @@ -635,8 +876,56 @@ Connection objects Example: - .. literalinclude:: ../includes/sqlite3/sumintwindow.py + .. testcode:: + + # Example taken from https://www.sqlite.org/windowfunctions.html#udfwinfunc + class WindowSumInt: + def __init__(self): + self.count = 0 + + def step(self, value): + """Add a row to the current window.""" + self.count += value + + def value(self): + """Return the current value of the aggregate.""" + return self.count + + def inverse(self, value): + """Remove a row from the current window.""" + self.count -= value + + def finalize(self): + """Return the final value of the aggregate. + Any clean-up actions should be placed here. + """ + return self.count + + + con = sqlite3.connect(":memory:") + cur = con.execute("CREATE TABLE test(x, y)") + values = [ + ("a", 4), + ("b", 5), + ("c", 3), + ("d", 8), + ("e", 1), + ] + cur.executemany("INSERT INTO test VALUES(?, ?)", values) + con.create_window_function("sumint", 1, WindowSumInt) + cur.execute(""" + SELECT x, sumint(y) OVER ( + ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) AS sum_y + FROM test ORDER BY x + """) + print(cur.fetchall()) + + .. testoutput:: + :hide: + + [('a', 9), ('b', 12), ('c', 16), ('d', 12), ('e', 9)] .. method:: create_collation(name, callable) @@ -650,7 +939,31 @@ Connection objects The following example shows a reverse sorting collation: - .. literalinclude:: ../includes/sqlite3/collation_reverse.py + .. testcode:: + + def collate_reverse(string1, string2): + if string1 == string2: + return 0 + elif string1 < string2: + return 1 + else: + return -1 + + con = sqlite3.connect(":memory:") + con.create_collation("reverse", collate_reverse) + + cur = con.execute("CREATE TABLE test(x)") + cur.executemany("INSERT INTO test(x) VALUES(?)", [("a",), ("b",)]) + cur.execute("SELECT x FROM test ORDER BY x COLLATE reverse") + for row in cur: + print(row) + con.close() + + .. testoutput:: + :hide: + + ('b',) + ('a',) Remove a collation function by setting *callable* to ``None``. @@ -670,10 +983,9 @@ Connection objects Register callable *authorizer_callback* to be invoked for each attempt to access a column of a table in the database. The callback should return - :const:`SQLITE_OK` if access is allowed, :const:`SQLITE_DENY` if the entire SQL - statement should be aborted with an error and :const:`SQLITE_IGNORE` if the - column should be treated as a NULL value. These constants are available in the - :mod:`!sqlite3` module. + one of :const:`SQLITE_OK`, :const:`SQLITE_DENY`, or :const:`SQLITE_IGNORE` + to signal how access to the column should be handled + by the underlying SQLite library. The first argument to the callback signifies what kind of operation is to be authorized. The second and third argument will be arguments or ``None`` @@ -717,7 +1029,7 @@ Connection objects 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 + :mod:`!sqlite3` module and the execution of triggers defined in the current database. Passing ``None`` as *trace_callback* will disable the trace callback. @@ -756,59 +1068,56 @@ Connection objects .. versionchanged:: 3.10 Added the ``sqlite3.enable_load_extension`` auditing event. - .. literalinclude:: ../includes/sqlite3/load_extension.py - - .. method:: load_extension(path, /) + .. testsetup:: sqlite3.loadext - Load an SQLite extension from a shared library located at *path*. - Enable extension loading with :meth:`enable_load_extension` before - calling this method. - - .. audit-event:: sqlite3.load_extension connection,path sqlite3.Connection.load_extension - - .. versionadded:: 3.2 - - .. versionchanged:: 3.10 - Added the ``sqlite3.load_extension`` auditing event. - - .. attribute:: row_factory + import sqlite3 + con = sqlite3.connect(":memory:") - A callable that accepts two arguments, - a :class:`Cursor` object and the raw row results as a :class:`tuple`, - and returns a custom object representing an SQLite row. + .. testcode:: sqlite3.loadext + :skipif: True # not testable at the moment - Example: + con.enable_load_extension(True) - .. literalinclude:: ../includes/sqlite3/row_factory.py + # Load the fulltext search extension + con.execute("select load_extension('./fts3.so')") - If returning a tuple doesn't suffice and you want name-based access to - columns, you should consider setting :attr:`row_factory` to the - highly optimized :class:`sqlite3.Row` type. :class:`Row` provides both - index-based and case-insensitive name-based access to columns with almost no - memory overhead. It will probably be better than your own custom - dictionary-based approach or even a db_row based solution. + # alternatively you can load the extension using an API call: + # con.load_extension("./fts3.so") - .. XXX what's a db_row-based solution? + # disable extension loading again + con.enable_load_extension(False) + # example from SQLite wiki + con.execute("CREATE VIRTUAL TABLE recipe USING fts3(name, ingredients)") + con.executescript(""" + INSERT INTO recipe (name, ingredients) VALUES('broccoli stew', 'broccoli peppers cheese tomatoes'); + INSERT INTO recipe (name, ingredients) VALUES('pumpkin stew', 'pumpkin onions garlic celery'); + INSERT INTO recipe (name, ingredients) VALUES('broccoli pie', 'broccoli cheese onions flour'); + INSERT INTO recipe (name, ingredients) VALUES('pumpkin pie', 'pumpkin sugar flour butter'); + """) + for row in con.execute("SELECT rowid, name, ingredients FROM recipe WHERE name MATCH 'pie'"): + print(row) - .. attribute:: text_factory + con.close() - A callable that accepts a :class:`bytes` parameter and returns a text - representation of it. - The callable is invoked for SQLite values with the ``TEXT`` data type. - By default, this attribute is set to :class:`str`. - If you want to return ``bytes`` instead, set *text_factory* to ``bytes``. + .. testoutput:: sqlite3.loadext + :hide: - Example: + (2, 'broccoli pie', 'broccoli cheese onions flour') + (3, 'pumpkin pie', 'pumpkin sugar flour butter') - .. literalinclude:: ../includes/sqlite3/text_factory.py + .. method:: load_extension(path, /) + Load an SQLite extension from a shared library located at *path*. + Enable extension loading with :meth:`enable_load_extension` before + calling this method. - .. attribute:: total_changes + .. audit-event:: sqlite3.load_extension connection,path sqlite3.Connection.load_extension - Return the total number of database rows that have been modified, inserted, or - deleted since the database connection was opened. + .. versionadded:: 3.2 + .. versionchanged:: 3.10 + Added the ``sqlite3.load_extension`` auditing event. .. method:: iterdump @@ -816,19 +1125,19 @@ Connection objects Useful when saving an in-memory database for later restoration. Similar to the ``.dump`` command in the :program:`sqlite3` shell. - Example:: + Example: - # Convert file existing_db.db to SQL dump file dump.sql - import sqlite3 + .. testcode:: - con = sqlite3.connect('existing_db.db') + # Convert file example.db to SQL dump file dump.sql + con = sqlite3.connect('example.db') with open('dump.sql', 'w') as f: for line in con.iterdump(): f.write('%s\n' % line) con.close() - .. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250) + .. method:: backup(target, \*, pages=-1, progress=None, name="main", sleep=0.250) Create a backup of an SQLite database. @@ -864,27 +1173,32 @@ Connection objects The number of seconds to sleep between successive attempts to back up remaining pages. - Example 1, copy an existing database into another:: + Example 1, copy an existing database into another: - import sqlite3 + .. testcode:: def progress(status, remaining, total): print(f'Copied {total-remaining} of {total} pages...') - con = sqlite3.connect('existing_db.db') - bck = sqlite3.connect('backup.db') - with bck: - con.backup(bck, pages=1, progress=progress) - bck.close() - con.close() + src = sqlite3.connect('example.db') + dst = sqlite3.connect('backup.db') + with dst: + src.backup(dst, pages=1, progress=progress) + dst.close() + src.close() - Example 2, copy an existing database into a transient copy:: + .. testoutput:: + :hide: - import sqlite3 + Copied 0 of 0 pages... + + Example 2, copy an existing database into a transient copy: - source = sqlite3.connect('existing_db.db') - dest = sqlite3.connect(':memory:') - source.backup(dest) + .. testcode:: + + src = sqlite3.connect('example.db') + dst = sqlite3.connect(':memory:') + src.backup(dst) .. versionadded:: 3.7 @@ -900,12 +1214,20 @@ Connection objects :raises ProgrammingError: If *category* is not recognised by the underlying SQLite library. - Example, query the maximum length of an SQL statement:: + Example, query the maximum length of an SQL statement + for :class:`Connection` ``con`` (the default is 1000000000): + + .. testsetup:: sqlite3.limits import sqlite3 con = sqlite3.connect(":memory:") - lim = con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) - print(f"SQLITE_LIMIT_SQL_LENGTH={lim}") + con.setlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH, 1_000_000_000) + con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 10) + + .. doctest:: sqlite3.limits + + >>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) + 1000000000 .. versionadded:: 3.11 @@ -929,18 +1251,22 @@ Connection objects :raises ProgrammingError: If *category* is not recognised by the underlying SQLite library. - Example, limit the number of attached databases to 1:: + Example, limit the number of attached databases to 1 + for :class:`Connection` ``con`` (the default limit is 10): - import sqlite3 - con = sqlite3.connect(":memory:") - con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1) + .. doctest:: sqlite3.limits + + >>> con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1) + 10 + >>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED) + 1 .. versionadded:: 3.11 .. _SQLite limit category: https://www.sqlite.org/c3ref/c_limit_attached.html - .. method:: serialize(*, name="main") + .. method:: serialize(\*, name="main") Serialize a database into a :class:`bytes` object. For an ordinary on-disk database file, the serialization is just a copy of the @@ -962,7 +1288,7 @@ Connection objects .. versionadded:: 3.11 - .. method:: deserialize(data, /, *, name="main") + .. method:: deserialize(data, /, \*, name="main") Deserialize a :meth:`serialized ` database into a :class:`Connection`. @@ -1009,11 +1335,25 @@ Cursor objects Cursor objects are :term:`iterators `, meaning that if you :meth:`~Cursor.execute` a ``SELECT`` query, - you can simply iterate over the cursor to fetch the resulting rows:: + you can simply iterate over the cursor to fetch the resulting rows: + + .. testsetup:: sqlite3.cursor + + import sqlite3 + con = sqlite3.connect(":memory:", isolation_level=None) + cur = con.execute("CREATE TABLE data(t)") + cur.execute("INSERT INTO data VALUES(1)") + + .. testcode:: sqlite3.cursor - for row in cur.execute("select * from data"): + for row in cur.execute("SELECT t FROM data"): print(row) + .. testoutput:: sqlite3.cursor + :hide: + + (1,) + .. _database cursor: https://en.wikipedia.org/wiki/Cursor_(databases) .. class:: Cursor @@ -1049,14 +1389,16 @@ Cursor objects :term:`iterator` yielding parameters instead of a sequence. Uses the same implicit transaction handling as :meth:`~Cursor.execute`. - Example:: + Example: + + .. testcode:: sqlite3.cursor - data = [ - ("row1",), - ("row2",), - ] - # cur is an sqlite3.Cursor object - cur.executemany("insert into t values(?)", data) + rows = [ + ("row1",), + ("row2",), + ] + # cur is an sqlite3.Cursor object + cur.executemany("INSERT INTO data VALUES(?)", rows) .. method:: executescript(sql_script, /) @@ -1068,15 +1410,17 @@ Cursor objects *sql_script* must be a :class:`string `. - Example:: + Example: + + .. testcode:: sqlite3.cursor # cur is an sqlite3.Cursor object cur.executescript(""" - begin; - create table person(firstname, lastname, age); - create table book(title, author, published); - create table publisher(name, address); - commit; + BEGIN; + CREATE TABLE person(firstname, lastname, age); + CREATE TABLE book(title, author, published); + CREATE TABLE publisher(name, address); + COMMIT; """) @@ -1124,13 +1468,32 @@ Cursor objects Required by the DB-API. Does nothing in :mod:`!sqlite3`. - .. attribute:: rowcount + .. attribute:: arraysize - Read-only attribute that provides the number of modified rows for - ``INSERT``, ``UPDATE``, ``DELETE``, and ``REPLACE`` statements; - is ``-1`` for other statements, - including :abbr:`CTE (Common Table Expression)` queries. - It is only updated by the :meth:`execute` and :meth:`executemany` methods. + Read/write attribute that controls the number of rows returned by :meth:`fetchmany`. + The default value is 1 which means a single row would be fetched per call. + + .. attribute:: connection + + Read-only attribute that provides the SQLite database :class:`Connection` + belonging to the cursor. A :class:`Cursor` object created by + calling :meth:`con.cursor() ` will have a + :attr:`connection` attribute that refers to *con*: + + .. doctest:: + + >>> con = sqlite3.connect(":memory:") + >>> cur = con.cursor() + >>> cur.connection == con + True + + .. attribute:: description + + Read-only attribute that provides the column names of the last query. To + remain compatible with the Python DB API, it returns a 7-tuple for each + column where the last six items of each tuple are ``None``. + + It is set for ``SELECT`` statements without any matching rows as well. .. attribute:: lastrowid @@ -1147,31 +1510,20 @@ Cursor objects .. versionchanged:: 3.6 Added support for the ``REPLACE`` statement. - .. attribute:: arraysize - - Read/write attribute that controls the number of rows returned by :meth:`fetchmany`. - The default value is 1 which means a single row would be fetched per call. - - .. attribute:: description - - Read-only attribute that provides the column names of the last query. To - remain compatible with the Python DB API, it returns a 7-tuple for each - column where the last six items of each tuple are ``None``. - - It is set for ``SELECT`` statements without any matching rows as well. + .. attribute:: rowcount - .. attribute:: connection + Read-only attribute that provides the number of modified rows for + ``INSERT``, ``UPDATE``, ``DELETE``, and ``REPLACE`` statements; + is ``-1`` for other statements, + including :abbr:`CTE (Common Table Expression)` queries. + It is only updated by the :meth:`execute` and :meth:`executemany` methods. - Read-only attribute that provides the SQLite database :class:`Connection` - belonging to the cursor. A :class:`Cursor` object created by - calling :meth:`con.cursor() ` will have a - :attr:`connection` attribute that refers to *con*:: - >>> con = sqlite3.connect(":memory:") - >>> cur = con.cursor() - >>> cur.connection == con - True +.. The sqlite3.Row example used to be a how-to. It has now been incorporated + into the Row reference. We keep the anchor here in order not to break + existing links. +.. _sqlite3-columns-by-name: .. _sqlite3-row-objects: Row objects @@ -1179,10 +1531,9 @@ Row objects .. class:: Row - A :class:`Row` instance serves as a highly optimized + A :class:`!Row` instance serves as a highly optimized :attr:`~Connection.row_factory` for :class:`Connection` objects. - It tries to mimic a :class:`tuple` in most of its features, - and supports iteration, :func:`repr`, equality testing, :func:`len`, + It supports iteration, equality testing, :func:`len`, and :term:`mapping` access by column name and index. Two row objects compare equal if have equal columns and equal members. @@ -1196,45 +1547,20 @@ Row objects .. versionchanged:: 3.5 Added support of slicing. -Let's assume we initialize a table as in the example given above:: + Example: - con = sqlite3.connect(":memory:") - cur = con.cursor() - cur.execute('''create table stocks - (date text, trans text, symbol text, - qty real, price real)''') - cur.execute("""insert into stocks - values ('2006-01-05','BUY','RHAT',100,35.14)""") - con.commit() - cur.close() + .. doctest:: -Now we plug :class:`Row` in:: - - >>> con.row_factory = sqlite3.Row - >>> cur = con.cursor() - >>> cur.execute('select * from stocks') - - >>> r = cur.fetchone() - >>> type(r) - - >>> tuple(r) - ('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14) - >>> len(r) - 5 - >>> r[2] - 'RHAT' - >>> r.keys() - ['date', 'trans', 'symbol', 'qty', 'price'] - >>> r['qty'] - 100.0 - >>> for member in r: - ... print(member) - ... - 2006-01-05 - BUY - RHAT - 100.0 - 35.14 + >>> con = sqlite3.connect(":memory:") + >>> con.row_factory = sqlite3.Row + >>> res = con.execute("SELECT 'Earth' AS name, 6378 AS radius") + >>> row = res.fetchone() + >>> row.keys() + ['name', 'radius'] + >>> row[0], row["name"] # Access by index and name. + ('Earth', 'Earth') + >>> row["RADIUS"] # Column names are case-insensitive. + 6378 .. _sqlite3-blob-objects: @@ -1254,7 +1580,30 @@ Blob objects Use the :class:`Blob` as a :term:`context manager` to ensure that the blob handle is closed after use. - .. literalinclude:: ../includes/sqlite3/blob.py + .. testcode:: + + con = sqlite3.connect(":memory:") + con.execute("CREATE TABLE test(blob_col blob)") + con.execute("INSERT INTO test(blob_col) VALUES(zeroblob(13))") + + # Write to our blob, using two write operations: + with con.blobopen("test", "blob_col", 1) as blob: + blob.write(b"hello, ") + blob.write(b"world.") + # Modify the first and last bytes of our blob + blob[0] = ord("H") + blob[-1] = ord("!") + + # Read the contents of our blob + with con.blobopen("test", "blob_col", 1) as blob: + greeting = blob.read() + + print(greeting) # outputs "b'Hello, world!'" + + .. testoutput:: + :hide: + + b'Hello, world!' .. method:: close() @@ -1443,6 +1792,41 @@ and you can let the :mod:`!sqlite3` module convert SQLite types to Python types via :ref:`converters `. +.. _sqlite3-default-converters: + +Default adapters and converters (deprecated) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + + The default adapters and converters are deprecated as of Python 3.12. + Instead, use the :ref:`sqlite3-adapter-converter-recipes` + and tailor them to your needs. + +The deprecated default adapters and converters consist of: + +* An adapter for :class:`datetime.date` objects to :class:`strings ` in + `ISO 8601`_ format. +* An adapter for :class:`datetime.datetime` objects to strings in + ISO 8601 format. +* A converter for :ref:`declared ` "date" types to + :class:`datetime.date` objects. +* A converter for declared "timestamp" types to + :class:`datetime.datetime` objects. + Fractional parts will be truncated to 6 digits (microsecond precision). + +.. 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`. + +.. deprecated:: 3.12 + +.. _ISO 8601: https://en.wikipedia.org/wiki/ISO_8601 + + .. _sqlite3-cli: Command-line interface @@ -1472,8 +1856,8 @@ How-to guides .. _sqlite3-placeholders: -Using placeholders to bind values in SQL queries -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +How to use placeholders to bind values in SQL queries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SQL operations usually need to use values from Python variables. However, beware of using Python's string operations to assemble queries, as they @@ -1497,13 +1881,36 @@ placeholders (named style). For the qmark style, ``parameters`` must be a keys for all named parameters. Any extra items are ignored. Here's an example of both styles: -.. literalinclude:: ../includes/sqlite3/execute_1.py +.. testcode:: + + con = sqlite3.connect(":memory:") + cur = con.execute("CREATE TABLE lang(name, first_appeared)") + + # This is the qmark style: + cur.execute("INSERT INTO lang VALUES(?, ?)", ("C", 1972)) + + # The qmark style used with executemany(): + lang_list = [ + ("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 first_appeared = :year", {"year": 1972}) + print(cur.fetchall()) + +.. testoutput:: + :hide: + + [('C', 1972)] .. _sqlite3-adapters: -Using adapters to store custom Python types in SQLite databases -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +How to adapt custom Python types to SQLite values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SQLite supports only a limited set of data types natively. To store custom Python types in SQLite databases, *adapt* them to one of the @@ -1520,10 +1927,10 @@ registering custom adapter functions. .. _sqlite3-conform: -Letting your object adapt itself -"""""""""""""""""""""""""""""""" +How to write adaptable objects +"""""""""""""""""""""""""""""" -Suppose we have a ``Point`` class that represents a pair of coordinates, +Suppose we have a :class:`!Point` class that represents a pair of coordinates, ``x`` and ``y``, in a Cartesian coordinate system. The coordinate pair will be stored as a text string in the database, using a semicolon to separate the coordinates. @@ -1531,41 +1938,80 @@ This can be implemented by adding a ``__conform__(self, protocol)`` method which returns the adapted value. The object passed to *protocol* will be of type :class:`PrepareProtocol`. -.. literalinclude:: ../includes/sqlite3/adapter_point_1.py +.. testcode:: + + class Point: + def __init__(self, x, y): + self.x, self.y = x, y + + def __conform__(self, protocol): + if protocol is sqlite3.PrepareProtocol: + return f"{self.x};{self.y}" + + con = sqlite3.connect(":memory:") + cur = con.cursor() + cur.execute("SELECT ?", (Point(4.0, -3.2),)) + print(cur.fetchone()[0]) -Registering an adapter callable -""""""""""""""""""""""""""""""" +.. testoutput:: + :hide: + + 4.0;-3.2 + + +How to register adapter callables +""""""""""""""""""""""""""""""""" The other possibility is to create a function that converts the Python object to an SQLite-compatible type. This function can then be registered using :func:`register_adapter`. -.. literalinclude:: ../includes/sqlite3/adapter_point_2.py +.. testcode:: + + class Point: + def __init__(self, x, y): + self.x, self.y = x, y + + def adapt_point(point): + return f"{point.x};{point.y}" + + sqlite3.register_adapter(Point, adapt_point) + + con = sqlite3.connect(":memory:") + cur = con.cursor() + + cur.execute("SELECT ?", (Point(1.0, 2.5),)) + print(cur.fetchone()[0]) + +.. testoutput:: + :hide: + + 1.0;2.5 .. _sqlite3-converters: -Converting SQLite values to custom Python types -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +How to convert SQLite values to custom Python types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Writing an adapter lets you convert *from* custom Python types *to* SQLite values. To be able to convert *from* SQLite values *to* custom Python types, we use *converters*. -Let's go back to the :class:`Point` class. We stored the x and y coordinates +Let's go back to the :class:`!Point` class. We stored the x and y coordinates separated via semicolons as strings in SQLite. First, we'll define a converter function that accepts the string as a parameter -and constructs a :class:`Point` object from it. +and constructs a :class:`!Point` object from it. .. note:: Converter functions are **always** passed a :class:`bytes` object, no matter the underlying SQLite data type. -:: +.. testcode:: def convert_point(s): x, y = map(float, s.split(b";")) @@ -1583,42 +2029,50 @@ of :func:`connect`. There are three options: The following example illustrates the implicit and explicit approaches: -.. literalinclude:: ../includes/sqlite3/converter_point.py +.. testcode:: + class Point: + def __init__(self, x, y): + self.x, self.y = x, y -.. _sqlite3-default-converters: + def __repr__(self): + return f"Point({self.x}, {self.y})" -Default adapters and converters (deprecated) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + def adapt_point(point): + return f"{point.x};{point.y}".encode("utf-8") -.. note:: + def convert_point(s): + x, y = list(map(float, s.split(b";"))) + return Point(x, y) - The default adapters and converters are deprecated as of Python 3.12. - Instead, use the :ref:`sqlite3-adapter-converter-recipes` - and tailor them to your needs. + # Register the adapter and converter + sqlite3.register_adapter(Point, adapt_point) + sqlite3.register_converter("point", convert_point) -The deprecated default adapters and converters consist of: + # 1) Parse using declared types + p = Point(4.0, -3.2) + con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES) + cur = con.execute("CREATE TABLE test(p point)") -* An adapter for :class:`datetime.date` objects to :class:`strings ` in - `ISO 8601`_ format. -* An adapter for :class:`datetime.datetime` objects to strings in - ISO 8601 format. -* A converter for :ref:`declared ` "date" types to - :class:`datetime.date` objects. -* A converter for declared "timestamp" types to - :class:`datetime.datetime` objects. - Fractional parts will be truncated to 6 digits (microsecond precision). + cur.execute("INSERT INTO test(p) VALUES(?)", (p,)) + cur.execute("SELECT p FROM test") + print("with declared types:", cur.fetchone()[0]) + cur.close() + con.close() -.. note:: + # 2) Parse using column names + con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES) + cur = con.execute("CREATE TABLE test(p)") - 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`. + cur.execute("INSERT INTO test(p) VALUES(?)", (p,)) + cur.execute('SELECT p AS "p [point]" FROM test') + print("with column names:", cur.fetchone()[0]) -.. deprecated:: 3.12 +.. testoutput:: + :hide: -.. _ISO 8601: https://en.wikipedia.org/wiki/ISO_8601 + with declared types: Point(4.0, -3.2) + with column names: Point(4.0, -3.2) .. _sqlite3-adapter-converter-recipes: @@ -1628,7 +2082,7 @@ Adapter and converter recipes This section shows recipes for common adapters and converters. -.. code-block:: +.. testcode:: import datetime import sqlite3 @@ -1641,7 +2095,7 @@ This section shows recipes for common adapters and converters. """Adapt datetime.datetime to timezone-naive ISO 8601 date.""" return val.isoformat() - def adapt_datetime_epoch(val) + def adapt_datetime_epoch(val): """Adapt datetime.datetime to Unix timestamp.""" return int(val.timestamp()) @@ -1668,8 +2122,8 @@ This section shows recipes for common adapters and converters. .. _sqlite3-connection-shortcuts: -Using connection shortcut methods -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +How to use connection shortcut methods +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Using the :meth:`~Connection.execute`, :meth:`~Connection.executemany`, and :meth:`~Connection.executescript` @@ -1680,26 +2134,38 @@ objects are created implicitly and these shortcut methods return the cursor objects. This way, you can execute a ``SELECT`` statement and iterate over it directly using only a single call on the :class:`Connection` object. -.. literalinclude:: ../includes/sqlite3/shortcut_methods.py +.. testcode:: + # Create and fill the table. + con = sqlite3.connect(":memory:") + con.execute("CREATE TABLE lang(name, first_appeared)") + data = [ + ("C++", 1985), + ("Objective-C", 1984), + ] + con.executemany("INSERT INTO lang(name, first_appeared) VALUES(?, ?)", data) -.. _sqlite3-columns-by-name: + # Print the table contents + for row in con.execute("SELECT name, first_appeared FROM lang"): + print(row) -Accessing columns by name instead of by index -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + print("I just deleted", con.execute("DELETE FROM lang").rowcount, "rows") -One useful feature of the :mod:`!sqlite3` module is the built-in -:class:`sqlite3.Row` class designed to be used as a row factory. + # close() is not a shortcut method and it's not called automatically; + # the connection object should be closed manually + con.close() -Rows wrapped with this class can be accessed both by index (like tuples) and -case-insensitively by name: +.. testoutput:: + :hide: -.. literalinclude:: ../includes/sqlite3/rowclass.py + ('C++', 1985) + ('Objective-C', 1984) + I just deleted 2 rows .. _sqlite3-connection-context-manager: -Using the connection as a context manager +How to use the connection context manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A :class:`Connection` object can be used as a context manager that @@ -1719,33 +2185,72 @@ the context manager is a no-op. The context manager neither implicitly opens a new transaction nor closes the connection. -.. literalinclude:: ../includes/sqlite3/ctx_manager.py +.. testcode:: + + con = sqlite3.connect(":memory:") + 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 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 lang(name) VALUES(?)", ("Python",)) + except sqlite3.IntegrityError: + 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 + con.close() + +.. testoutput:: + :hide: + + couldn't add Python twice .. _sqlite3-uri-tricks: -Working with SQLite URIs -^^^^^^^^^^^^^^^^^^^^^^^^ +How to work with SQLite URIs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some useful URI tricks include: -* Open a database in read-only mode:: +* Open a database in read-only mode: - con = sqlite3.connect("file:template.db?mode=ro", uri=True) +.. doctest:: + + >>> con = sqlite3.connect("file:tutorial.db?mode=ro", uri=True) + >>> con.execute("CREATE TABLE readonly(data)") + Traceback (most recent call last): + OperationalError: attempt to write a readonly database * Do not implicitly create a new database file if it does not already exist; - will raise :exc:`~sqlite3.OperationalError` if unable to create a new file:: + will raise :exc:`~sqlite3.OperationalError` if unable to create a new file: + +.. doctest:: + + >>> con = sqlite3.connect("file:nosuchdb.db?mode=rw", uri=True) + Traceback (most recent call last): + OperationalError: unable to open database file + + +* Create a shared named in-memory database: - con = sqlite3.connect("file:nosuchdb.db?mode=rw", uri=True) +.. testcode:: -* Create a shared named in-memory database:: + db = "file:mem1?mode=memory&cache=shared" + con1 = sqlite3.connect(db, uri=True) + con2 = sqlite3.connect(db, uri=True) + with con1: + con1.execute("CREATE TABLE shared(data)") + con1.execute("INSERT INTO shared VALUES(28)") + res = con2.execute("SELECT data FROM shared") + assert res.fetchone() == (28,) - con1 = sqlite3.connect("file:mem1?mode=memory&cache=shared", uri=True) - con2 = sqlite3.connect("file:mem1?mode=memory&cache=shared", uri=True) - con1.execute("create table t(t)") - con1.execute("insert into t values(28)") - con1.commit() - rows = con2.execute("select * from t").fetchall() More information about this feature, including a list of parameters, can be found in the `SQLite URI documentation`_. diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index bf869903c0f84e4..c3f9c1f5239e8b0 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -104,7 +104,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:`correlation` Pearson and Spearman's correlation coefficients. :func:`linear_regression` Slope and intercept for simple linear regression. ========================= ===================================================== @@ -648,31 +648,57 @@ However, for reading convenience, most of the examples show sorted sequences. .. versionadded:: 3.10 -.. function:: correlation(x, y, /) +.. function:: correlation(x, y, /, *, method='linear') Return the `Pearson's correlation coefficient `_ for two inputs. Pearson's correlation coefficient *r* takes values - between -1 and +1. It measures the strength and direction of the linear - relationship, where +1 means very strong, positive linear relationship, - -1 very strong, negative linear relationship, and 0 no linear relationship. + between -1 and +1. It measures the strength and direction of a linear + relationship. + + If *method* is "ranked", computes `Spearman's rank correlation coefficient + `_ + for two inputs. The data is replaced by ranks. Ties are averaged so that + equal values receive the same rank. The resulting coefficient measures the + strength of a monotonic relationship. + + Spearman's correlation coefficient is appropriate for ordinal data or for + continuous data that doesn't meet the linear proportion requirement for + Pearson's correlation coefficient. Both inputs must be of the same length (no less than two), and need not to be constant, otherwise :exc:`StatisticsError` is raised. - Examples: + Example with `Kepler's laws of planetary motion + `_: .. doctest:: - >>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9] - >>> y = [9, 8, 7, 6, 5, 4, 3, 2, 1] - >>> correlation(x, x) + >>> # Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune + >>> orbital_period = [88, 225, 365, 687, 4331, 10_756, 30_687, 60_190] # days + >>> dist_from_sun = [58, 108, 150, 228, 778, 1_400, 2_900, 4_500] # million km + + >>> # Show that a perfect monotonic relationship exists + >>> correlation(orbital_period, dist_from_sun, method='ranked') + 1.0 + + >>> # Observe that a linear relationship is imperfect + >>> round(correlation(orbital_period, dist_from_sun), 4) + 0.9882 + + >>> # Demonstrate Kepler's third law: There is a linear correlation + >>> # between the square of the orbital period and the cube of the + >>> # distance from the sun. + >>> period_squared = [p * p for p in orbital_period] + >>> dist_cubed = [d * d * d for d in dist_from_sun] + >>> round(correlation(period_squared, dist_cubed), 4) 1.0 - >>> correlation(x, y) - -1.0 .. versionadded:: 3.10 + .. versionchanged:: 3.12 + Added support for Spearman's rank correlation coefficient. + .. function:: linear_regression(x, y, /, *, proportional=False) Return the slope and intercept of `simple linear regression diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 2480e71dded321a..9595a00779ba160 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2548,9 +2548,10 @@ data and are closely related to string objects in a variety of other ways. If you want to make the hex string easier to read, you can specify a single character separator *sep* parameter to include in the output. - By default between each byte. A second optional *bytes_per_sep* - parameter controls the spacing. Positive values calculate the - separator position from the right, negative values from the left. + By default, this separator will be included between each byte. + A second optional *bytes_per_sep* parameter controls the spacing. + Positive values calculate the separator position from the right, + negative values from the left. >>> value = b'\xf0\xf1\xf2' >>> value.hex('-') @@ -4693,7 +4694,9 @@ values are hashable, so that ``(key, value)`` pairs are unique and hashable, then the items view is also set-like. (Values views are not treated as set-like since the entries are generally not unique.) For set-like views, all of the operations defined for the abstract base class :class:`collections.abc.Set` are -available (for example, ``==``, ``<``, or ``^``). +available (for example, ``==``, ``<``, or ``^``). While using set operators, +set-like views accept any iterable as the other operand, unlike sets which only +accept sets as the input. An example of dictionary view usage:: @@ -4725,6 +4728,8 @@ An example of dictionary view usage:: {'bacon'} >>> keys ^ {'sausage', 'juice'} {'juice', 'sausage', 'bacon', 'spam'} + >>> keys | ['juice', 'juice', 'juice'] + {'juice', 'sausage', 'bacon', 'spam', 'eggs'} >>> # get back a read-only proxy for the original dictionary >>> values.mapping @@ -5455,6 +5460,165 @@ types, where they are relevant. Some of these are not reported by the [] +.. _int_max_str_digits: + +Integer string conversion length limitation +=========================================== + +CPython has a global limit for converting between :class:`int` and :class:`str` +to mitigate denial of service attacks. This limit *only* applies to decimal or +other non-power-of-two number bases. Hexadecimal, octal, and binary conversions +are unlimited. The limit can be configured. + +The :class:`int` type in CPython is an abitrary length number stored in binary +form (commonly known as a "bignum"). There exists no algorithm that can convert +a string to a binary integer or a binary integer to a string in linear time, +*unless* the base is a power of 2. Even the best known algorithms for base 10 +have sub-quadratic complexity. Converting a large value such as ``int('1' * +500_000)`` can take over a second on a fast CPU. + +Limiting conversion size offers a practical way to avoid `CVE-2020-10735 +`_. + +The limit is applied to the number of digit characters in the input or output +string when a non-linear conversion algorithm would be involved. Underscores +and the sign are not counted towards the limit. + +When an operation would exceed the limit, a :exc:`ValueError` is raised: + +.. doctest:: + + >>> import sys + >>> sys.set_int_max_str_digits(4300) # Illustrative, this is the default. + >>> _ = int('2' * 5432) + Traceback (most recent call last): + ... + ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits. + >>> i = int('2' * 4300) + >>> len(str(i)) + 4300 + >>> i_squared = i*i + >>> len(str(i_squared)) + Traceback (most recent call last): + ... + ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits. + >>> len(hex(i_squared)) + 7144 + >>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited. + +The default limit is 4300 digits as provided in +:data:`sys.int_info.default_max_str_digits `. +The lowest limit that can be configured is 640 digits as provided in +:data:`sys.int_info.str_digits_check_threshold `. + +Verification: + +.. doctest:: + + >>> import sys + >>> assert sys.int_info.default_max_str_digits == 4300, sys.int_info + >>> assert sys.int_info.str_digits_check_threshold == 640, sys.int_info + >>> msg = int('578966293710682886880994035146873798396722250538762761564' + ... '9252925514383915483333812743580549779436104706260696366600' + ... '571186405732').to_bytes(53, 'big') + ... + +.. versionadded:: 3.12 + +Affected APIs +------------- + +The limitation only applies to potentially slow conversions between :class:`int` +and :class:`str` or :class:`bytes`: + +* ``int(string)`` with default base 10. +* ``int(string, base)`` for all bases that are not a power of 2. +* ``str(integer)``. +* ``repr(integer)`` +* any other string conversion to base 10, for example ``f"{integer}"``, + ``"{}".format(integer)``, or ``b"%d" % integer``. + +The limitations do not apply to functions with a linear algorithm: + +* ``int(string, base)`` with base 2, 4, 8, 16, or 32. +* :func:`int.from_bytes` and :func:`int.to_bytes`. +* :func:`hex`, :func:`oct`, :func:`bin`. +* :ref:`formatspec` for hex, octal, and binary numbers. +* :class:`str` to :class:`float`. +* :class:`str` to :class:`decimal.Decimal`. + +Configuring the limit +--------------------- + +Before Python starts up you can use an environment variable or an interpreter +command line flag to configure the limit: + +* :envvar:`PYTHONINTMAXSTRDIGITS`, e.g. + ``PYTHONINTMAXSTRDIGITS=640 python3`` to set the limit to 640 or + ``PYTHONINTMAXSTRDIGITS=0 python3`` to disable the limitation. +* :option:`-X int_max_str_digits <-X>`, e.g. + ``python3 -X int_max_str_digits=640`` +* :data:`sys.flags.int_max_str_digits` contains the value of + :envvar:`PYTHONINTMAXSTRDIGITS` or :option:`-X int_max_str_digits <-X>`. + If both the env var and the ``-X`` option are set, the ``-X`` option takes + precedence. A value of *-1* indicates that both were unset, thus a value of + :data:`sys.int_info.default_max_str_digits` was used during initilization. + +From code, you can inspect the current limit and set a new one using these +:mod:`sys` APIs: + +* :func:`sys.get_int_max_str_digits` and :func:`sys.set_int_max_str_digits` are + a getter and setter for the interpreter-wide limit. Subinterpreters have + their own limit. + +Information about the default and minimum can be found in :attr:`sys.int_info`: + +* :data:`sys.int_info.default_max_str_digits ` is the compiled-in + default limit. +* :data:`sys.int_info.str_digits_check_threshold ` is the lowest + accepted value for the limit (other than 0 which disables it). + +.. versionadded:: 3.12 + +.. caution:: + + Setting a low limit *can* lead to problems. While rare, code exists that + contains integer constants in decimal in their source that exceed the + minimum threshold. A consequence of setting the limit is that Python source + code containing decimal integer literals longer than the limit will + encounter an error during parsing, usually at startup time or import time or + even at installation time - anytime an up to date ``.pyc`` does not already + exist for the code. A workaround for source that contains such large + constants is to convert them to ``0x`` hexadecimal form as it has no limit. + + Test your application thoroughly if you use a low limit. Ensure your tests + run with the limit set early via the environment or flag so that it applies + during startup and even during any installation step that may invoke Python + to precompile ``.py`` sources to ``.pyc`` files. + +Recommended configuration +------------------------- + +The default :data:`sys.int_info.default_max_str_digits` is expected to be +reasonable for most applications. If your application requires a different +limit, set it from your main entry point using Python version agnostic code as +these APIs were added in security patch releases in versions before 3.12. + +Example:: + + >>> import sys + >>> if hasattr(sys, "set_int_max_str_digits"): + ... upper_bound = 68000 + ... lower_bound = 4004 + ... current_limit = sys.get_int_max_str_digits() + ... if current_limit == 0 or current_limit > upper_bound: + ... sys.set_int_max_str_digits(upper_bound) + ... elif current_limit < lower_bound: + ... sys.set_int_max_str_digits(lower_bound) + +If you need to disable it entirely, set it to ``0``. + + .. rubric:: Footnotes .. [1] Additional information on these special methods may be found in the Python diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 43db4baf62dfb33..cc41b996d2dad5f 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -502,9 +502,9 @@ always available. The :term:`named tuple` *flags* exposes the status of command line flags. The attributes are read only. - ============================= ================================================================ + ============================= ============================================================================================================== attribute flag - ============================= ================================================================ + ============================= ============================================================================================================== :const:`debug` :option:`-d` :const:`inspect` :option:`-i` :const:`interactive` :option:`-i` @@ -521,7 +521,8 @@ always available. :const:`dev_mode` :option:`-X dev <-X>` (:ref:`Python Development Mode `) :const:`utf8_mode` :option:`-X utf8 <-X>` :const:`safe_path` :option:`-P` - ============================= ================================================================ + :const:`int_max_str_digits` :option:`-X int_max_str_digits <-X>` (:ref:`integer string conversion length limitation `) + ============================= ============================================================================================================== .. versionchanged:: 3.2 Added ``quiet`` attribute for the new :option:`-q` flag. @@ -543,6 +544,9 @@ always available. .. versionchanged:: 3.11 Added the ``safe_path`` attribute for :option:`-P` option. + .. versionchanged:: 3.12 + Added the ``int_max_str_digits`` attribute. + .. data:: float_info @@ -723,6 +727,13 @@ always available. .. versionadded:: 3.6 +.. function:: get_int_max_str_digits() + + Returns the current value for the :ref:`integer string conversion length + limitation `. See also :func:`set_int_max_str_digits`. + + .. versionadded:: 3.12 + .. function:: getrefcount(object) Return the reference count of the *object*. The count returned is generally one @@ -996,19 +1007,31 @@ always available. .. tabularcolumns:: |l|L| - +-------------------------+----------------------------------------------+ - | Attribute | Explanation | - +=========================+==============================================+ - | :const:`bits_per_digit` | number of bits held in each digit. Python | - | | integers are stored internally in base | - | | ``2**int_info.bits_per_digit`` | - +-------------------------+----------------------------------------------+ - | :const:`sizeof_digit` | size in bytes of the C type used to | - | | represent a digit | - +-------------------------+----------------------------------------------+ + +----------------------------------------+-----------------------------------------------+ + | Attribute | Explanation | + +========================================+===============================================+ + | :const:`bits_per_digit` | number of bits held in each digit. Python | + | | integers are stored internally in base | + | | ``2**int_info.bits_per_digit`` | + +----------------------------------------+-----------------------------------------------+ + | :const:`sizeof_digit` | size in bytes of the C type used to | + | | represent a digit | + +----------------------------------------+-----------------------------------------------+ + | :const:`default_max_str_digits` | default value for | + | | :func:`sys.get_int_max_str_digits` when it | + | | is not otherwise explicitly configured. | + +----------------------------------------+-----------------------------------------------+ + | :const:`str_digits_check_threshold` | minimum non-zero value for | + | | :func:`sys.set_int_max_str_digits`, | + | | :envvar:`PYTHONINTMAXSTRDIGITS`, or | + | | :option:`-X int_max_str_digits <-X>`. | + +----------------------------------------+-----------------------------------------------+ .. versionadded:: 3.1 + .. versionchanged:: 3.12 + Added ``default_max_str_digits`` and ``str_digits_check_threshold``. + .. data:: __interactivehook__ @@ -1308,6 +1331,14 @@ always available. .. availability:: Unix. +.. function:: set_int_max_str_digits(n) + + Set the :ref:`integer string conversion length limitation + ` used by this interpreter. See also + :func:`get_int_max_str_digits`. + + .. versionadded:: 3.12 + .. function:: setprofile(profilefunc) .. index:: diff --git a/Doc/library/test.rst b/Doc/library/test.rst index e255952d4570ef0..eff375132318a96 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -794,6 +794,12 @@ The :mod:`test.support` module defines the following functions: Decorator for only running the test if :data:`HAVE_DOCSTRINGS`. +.. decorator:: requires_limited_api + + Decorator for only running the test if :ref:`Limited C API ` + is available. + + .. decorator:: cpython_only Decorator for tests only applicable to CPython. @@ -1005,6 +1011,16 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.10 +.. function:: adjust_int_max_str_digits(max_digits) + + This function returns a context manager that will change the global + :func:`sys.set_int_max_str_digits` setting for the duration of the + context to allow execution of test code that needs a different limit + on the number of digits when converting between an integer and string. + + .. versionadded:: 3.12 + + The :mod:`test.support` module defines the following classes: diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index a8851dd15052ef7..b352125551fa79e 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -9,11 +9,23 @@ -------------- This module constructs higher-level threading interfaces on top of the lower -level :mod:`_thread` module. See also the :mod:`queue` module. +level :mod:`_thread` module. .. versionchanged:: 3.7 This module used to be optional, it is now always available. +.. seealso:: + + :class:`concurrent.futures.ThreadPoolExecutor` offers a higher level interface + to push tasks to a background thread without blocking execution of the + calling thread, while still being able to retrieve their results when needed. + + :mod:`queue` provides a thread-safe interface for exchanging data between + running threads. + + :mod:`asyncio` offers an alternative approach to achieving task level + concurrency without requiring the use of multiple operating system threads. + .. note:: In the Python 2.x series, this module contained ``camelCase`` names @@ -146,6 +158,15 @@ This module defines the following functions: The *func* will be passed to :func:`sys.settrace` for each thread, before its :meth:`~Thread.run` method is called. +.. function:: settrace_all_threads(func) + + Set a trace function for all threads started from the :mod:`threading` module + and all Python threads that are currently executing. + + The *func* will be passed to :func:`sys.settrace` for each thread, before its + :meth:`~Thread.run` method is called. + + .. versionadded:: 3.12 .. function:: gettrace() @@ -166,6 +187,15 @@ This module defines the following functions: The *func* will be passed to :func:`sys.setprofile` for each thread, before its :meth:`~Thread.run` method is called. +.. function:: setprofile_all_threads(func) + + Set a profile function for all threads started from the :mod:`threading` module + and all Python threads that are currently executing. + + The *func* will be passed to :func:`sys.setprofile` for each thread, before its + :meth:`~Thread.run` method is called. + + .. versionadded:: 3.12 .. function:: getprofile() diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index 8cb6af9bc840b59..f8c1eabadacf9f2 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -429,9 +429,9 @@ exception and traceback: import sys, traceback def lumberjack(): - bright_side_of_death() + bright_side_of_life() - def bright_side_of_death(): + def bright_side_of_life(): return tuple()[0] try: @@ -441,9 +441,7 @@ exception and traceback: print("*** print_tb:") traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) print("*** print_exception:") - # exc_type below is ignored on 3.5 and later - traceback.print_exception(exc_type, exc_value, exc_traceback, - limit=2, file=sys.stdout) + traceback.print_exception(exc_value, limit=2, file=sys.stdout) print("*** print_exc:") traceback.print_exc(limit=2, file=sys.stdout) print("*** format_exc, first and last line:") @@ -451,9 +449,7 @@ exception and traceback: print(formatted_lines[0]) print(formatted_lines[-1]) print("*** format_exception:") - # exc_type below is ignored on 3.5 and later - print(repr(traceback.format_exception(exc_type, exc_value, - exc_traceback))) + print(repr(traceback.format_exception(exc_value))) print("*** extract_tb:") print(repr(traceback.extract_tb(exc_traceback))) print("*** format_tb:") @@ -473,14 +469,14 @@ The output for the example would look similar to this: File "", line 10, in lumberjack() File "", line 4, in lumberjack - bright_side_of_death() + bright_side_of_life() IndexError: tuple index out of range *** print_exc: Traceback (most recent call last): File "", line 10, in lumberjack() File "", line 4, in lumberjack - bright_side_of_death() + bright_side_of_life() IndexError: tuple index out of range *** format_exc, first and last line: Traceback (most recent call last): @@ -488,17 +484,17 @@ The output for the example would look similar to this: *** format_exception: ['Traceback (most recent call last):\n', ' File "", line 10, in \n lumberjack()\n', - ' File "", line 4, in lumberjack\n bright_side_of_death()\n', - ' File "", line 7, in bright_side_of_death\n return tuple()[0]\n ~~~~~~~^^^\n', + ' File "", line 4, in lumberjack\n bright_side_of_life()\n', + ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n', 'IndexError: tuple index out of range\n'] *** extract_tb: [, line 10 in >, , line 4 in lumberjack>, - , line 7 in bright_side_of_death>] + , line 7 in bright_side_of_life>] *** format_tb: [' File "", line 10, in \n lumberjack()\n', - ' File "", line 4, in lumberjack\n bright_side_of_death()\n', - ' File "", line 7, in bright_side_of_death\n return tuple()[0]\n ~~~~~~~^^^\n'] + ' File "", line 4, in lumberjack\n bright_side_of_life()\n', + ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n'] *** tb_lineno: 10 diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c6dd6976f236064..0939973cf24e621 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1305,20 +1305,25 @@ These are not used in annotations. They are building blocks for creating generic T = TypeVar('T') Ts = TypeVarTuple('Ts') - def remove_first_element(tup: tuple[T, *Ts]) -> tuple[*Ts]: - return tup[1:] + def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]: + return (*tup[1:], tup[0]) # T is bound to int, Ts is bound to () - # Return value is (), which has type tuple[()] - remove_first_element(tup=(1,)) + # Return value is (1,), which has type tuple[int] + move_first_element_to_last(tup=(1,)) # T is bound to int, Ts is bound to (str,) - # Return value is ('spam',), which has type tuple[str] - remove_first_element(tup=(1, 'spam')) + # Return value is ('spam', 1), which has type tuple[str, int] + move_first_element_to_last(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) - # Return value is ('spam', 3.0), which has type tuple[str, float] - remove_first_element(tup=(1, 'spam', 3.0)) + # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int] + move_first_element_to_last(tup=(1, 'spam', 3.0)) + + # This fails to type check (and fails at runtime) + # because tuple[()] is not compatible with tuple[T, *Ts] + # (at least one element is required) + move_first_element_to_last(tup=()) Note the use of the unpacking operator ``*`` in ``tuple[T, *Ts]``. Conceptually, you can think of ``Ts`` as a tuple of type variables diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 93c1720220f0439..751c7c2dbcf2573 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -1122,7 +1122,7 @@ subject value: These classes accept a single positional argument, and the pattern there is matched against the whole object rather than an attribute. For example ``int(0|1)`` matches - the value ``0``, but not the values ``0.0`` or ``False``. + the value ``0``, but not the value ``0.0``. In simple terms ``CLS(P1, attr=P2)`` matches only if the following happens: diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index b76b4688413eee3..8fd8d70426a8b48 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -552,7 +552,7 @@ Standard C. The recognized escape sequences are: +-----------------+---------------------------------+-------+ | Escape Sequence | Meaning | Notes | +=================+=================================+=======+ -| ``\newline`` | Backslash and newline ignored | | +| ``\``\ | Backslash and newline ignored | \(1) | +-----------------+---------------------------------+-------+ | ``\\`` | Backslash (``\``) | | +-----------------+---------------------------------+-------+ @@ -574,10 +574,10 @@ Standard C. The recognized escape sequences are: +-----------------+---------------------------------+-------+ | ``\v`` | ASCII Vertical Tab (VT) | | +-----------------+---------------------------------+-------+ -| ``\ooo`` | Character with octal value | (1,3) | +| ``\ooo`` | Character with octal value | (2,4) | | | *ooo* | | +-----------------+---------------------------------+-------+ -| ``\xhh`` | Character with hex value *hh* | (2,3) | +| ``\xhh`` | Character with hex value *hh* | (3,4) | +-----------------+---------------------------------+-------+ Escape sequences only recognized in string literals are: @@ -585,19 +585,30 @@ Escape sequences only recognized in string literals are: +-----------------+---------------------------------+-------+ | Escape Sequence | Meaning | Notes | +=================+=================================+=======+ -| ``\N{name}`` | Character named *name* in the | \(4) | +| ``\N{name}`` | Character named *name* in the | \(5) | | | Unicode database | | +-----------------+---------------------------------+-------+ -| ``\uxxxx`` | Character with 16-bit hex value | \(5) | +| ``\uxxxx`` | Character with 16-bit hex value | \(6) | | | *xxxx* | | +-----------------+---------------------------------+-------+ -| ``\Uxxxxxxxx`` | Character with 32-bit hex value | \(6) | +| ``\Uxxxxxxxx`` | Character with 32-bit hex value | \(7) | | | *xxxxxxxx* | | +-----------------+---------------------------------+-------+ Notes: (1) + A backslash can be added at the end of a line to ignore the newline:: + + >>> 'This string will not include \ + ... backslashes or newline characters.' + 'This string will not include backslashes or newline characters.' + + The same result can be achieved using :ref:`triple-quoted strings `, + or parentheses and :ref:`string literal concatenation `. + + +(2) As in Standard C, up to three octal digits are accepted. .. versionchanged:: 3.11 @@ -605,22 +616,22 @@ Notes: In a future Python version they will be a :exc:`SyntaxWarning` and eventually a :exc:`SyntaxError`. -(2) +(3) Unlike in Standard C, exactly two hex digits are required. -(3) +(4) In a bytes literal, hexadecimal and octal escapes denote the byte with the given value. In a string literal, these escapes denote a Unicode character with the given value. -(4) +(5) .. versionchanged:: 3.3 Support for name aliases [#]_ has been added. -(5) +(6) Exactly four hex digits are required. -(6) +(7) Any Unicode character can be encoded this way. Exactly eight hex digits are required. diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index f5986fe292fb1b1..12b00be3793e148 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -106,7 +106,7 @@ An example that uses most of the list methods:: 0 >>> fruits.index('banana') 3 - >>> fruits.index('banana', 4) # Find next banana starting a position 4 + >>> fruits.index('banana', 4) # Find next banana starting at position 4 6 >>> fruits.reverse() >>> fruits diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 5f7010cb12e9e7a..dbe2d7fc09927e2 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -17,7 +17,7 @@ the set are: reference material about types, functions, and the modules in the standard library. The standard Python distribution includes a *lot* of additional code. There are modules to read Unix mailboxes, retrieve documents via HTTP, generate - random numbers, parse command-line options, write CGI programs, compress data, + random numbers, parse command-line options, compress data, and many other tasks. Skimming through the Library Reference will give you an idea of what's available. diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 6678d476fa831b7..6a33d98a059a09c 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -505,6 +505,9 @@ Miscellaneous options stored in a traceback of a trace. Use ``-X tracemalloc=NFRAME`` to start tracing with a traceback limit of *NFRAME* frames. See the :func:`tracemalloc.start` for more information. + * ``-X int_max_str_digits`` configures the :ref:`integer string conversion + length limitation `. See also + :envvar:`PYTHONINTMAXSTRDIGITS`. * ``-X importtime`` to show how long each import takes. It shows module name, cumulative time (including nested imports) and self time (excluding nested imports). Note that its output may be broken in multi-threaded @@ -535,6 +538,12 @@ Miscellaneous options development (running from the source tree) then the default is "off". Note that the "importlib_bootstrap" and "importlib_bootstrap_external" frozen modules are always used, even if this flag is set to "off". + * ``-X perf`` to activate compatibility mode with the ``perf`` profiler. + When this option is activated, the Linux ``perf`` profiler will be able to + report Python calls. This option is only available on some platforms and + will do nothing if is not supported on the current system. The default value + is "off". See also :envvar:`PYTHONPERFSUPPORT` and :ref:`perf_profiling` + for more information. It also allows passing arbitrary values and retrieving them through the :data:`sys._xoptions` dictionary. @@ -576,6 +585,11 @@ Miscellaneous options .. versionadded:: 3.11 The ``-X frozen_modules`` option. + .. versionadded:: 3.12 + The ``-X int_max_str_digits`` option. + + .. versionadded:: 3.12 + The ``-X perf`` option. Options you shouldn't use @@ -755,6 +769,13 @@ conflict. .. versionadded:: 3.2.3 +.. envvar:: PYTHONINTMAXSTRDIGITS + + If this variable is set to an integer, it is used to configure the + interpreter's global :ref:`integer string conversion length limitation + `. + + .. versionadded:: 3.12 .. envvar:: PYTHONIOENCODING @@ -1025,6 +1046,13 @@ conflict. .. versionadded:: 3.11 +.. envvar:: PYTHONPERFSUPPORT + + If this variable is set to a nonzero value, it activates compatibility mode + with the ``perf`` profiler so Python calls can be detected by it. See the + :ref:`perf_profiling` section for more information. + + .. versionadded:: 3.12 Debug-mode variables diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 4e50e73a11b817e..cd5540320c4f855 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -191,7 +191,8 @@ Performance options ------------------- Configuring Python using ``--enable-optimizations --with-lto`` (PGO + LTO) is -recommended for best performance. +recommended for best performance. The experimental ``--enable-bolt`` flag can +also be used to improve performance. .. cmdoption:: --enable-optimizations @@ -231,6 +232,24 @@ recommended for best performance. .. versionadded:: 3.11 To use ThinLTO feature, use ``--with-lto=thin`` on Clang. +.. cmdoption:: --enable-bolt + + Enable usage of the `BOLT post-link binary optimizer + `_ (disabled by + default). + + BOLT is part of the LLVM project but is not always included in their binary + distributions. This flag requires that ``llvm-bolt`` and ``merge-fdata`` + are available. + + BOLT is still a fairly new project so this flag should be considered + experimental for now. Because this tool operates on machine code its success + is dependent on a combination of the build environment + the other + optimization configure args + the CPU architecture, and not all combinations + are supported. + + .. versionadded:: 3.12 + .. cmdoption:: --with-computed-gotos Enable computed gotos in evaluation loop (enabled by default on supported diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 3832fdfbe82b943..0f6490e6a7cbcd6 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -369,6 +369,28 @@ PEP 563 May Not Be the Future that was planned for this release has been indefinitely postponed. See `this message `_ for more information. +Windows py.exe launcher improvements +------------------------------------ + +The copy of :ref:`launcher` included with Python 3.11 has been significantly +updated. It now supports company/tag syntax as defined in :pep:`514` using the +``-V:/`` argument instead of the limited ``-x.y`` argument. This +allows launching distributions other than ``PythonCore``, which is the one +obtained from `python.org `_. + +When using ``-V:`` selectors, either company or tag can be omitted, but all +installs will be searched. For example, ``-V:OtherPython/`` will select the +"best" tag registered for ``OtherPython``, while ``-V:3.11`` or ``-V:/3.11`` +will select the "best" distribution with tag ``3.11``. + +When using legacy ``-x``, ``-x.y``, ``-x-ZZ`` or ``-x.y-ZZ`` arguments, all +existing behaviour should be preserved from past versions. Only releases from +``PythonCore`` will be selected. However, the ``-64`` suffix now implies "not +32-bit", as there are multiple supported 64-bit platforms. 32-bit runtimes are +detected by checking its tag for a ``-32`` suffix. All releases of Python +since 3.5 have included this in their 32-bit builds. + + Other Language Changes ====================== @@ -825,6 +847,20 @@ time it had a resolution of 1 millisecond (10\ :sup:`-3` seconds). (Contributed by Benjamin Szőke, Dong-hee Na, Eryk Sun and Victor Stinner in :issue:`21302` and :issue:`45429`.) + +traceback +--------- + +* Add :func:`traceback.StackSummary.format_frame_summary` to allow users + to override which frames appear in the traceback, and how they are + formatted. + (Contributed by Ammar Askar in :issue:`44569`.) + +* Add :func:`traceback.TracebackException.print`, which prints the + formatted :exc:`~traceback.TracebackException` instance to a file. + (Contributed by Irit Katriel in :issue:`33809`.) + + typing ------ @@ -1605,7 +1641,8 @@ Changes in the Python API Build Changes ============= -* Building Python now requires a C11 compiler without optional C11 features. +* Building Python now requires a C11 compiler. Optional C11 features are not + required. (Contributed by Victor Stinner in :issue:`46656`.) * Building Python now requires support of IEEE 754 floating point numbers. @@ -2122,5 +2159,30 @@ Removed API). (Contributed by Victor Stinner in :issue:`45412`.) +* Remove the :c:type:`Py_UNICODE` encoder APIs, + as they have been deprecated since Python 3.3, + are little used + and are inefficient relative to the recommended alternatives. + + The removed functions are: + + * :func:`!PyUnicode_Encode` + * :func:`!PyUnicode_EncodeASCII` + * :func:`!PyUnicode_EncodeLatin1` + * :func:`!PyUnicode_EncodeUTF7` + * :func:`!PyUnicode_EncodeUTF8` + * :func:`!PyUnicode_EncodeUTF16` + * :func:`!PyUnicode_EncodeUTF32` + * :func:`!PyUnicode_EncodeUnicodeEscape` + * :func:`!PyUnicode_EncodeRawUnicodeEscape` + * :func:`!PyUnicode_EncodeCharmap` + * :func:`!PyUnicode_TranslateCharmap` + * :func:`!PyUnicode_EncodeDecimal` + * :func:`!PyUnicode_TransformDecimalToASCII` + + See :pep:`624` for details and + :pep:`migration guidance <624#alternative-apis>`. + (Contributed by Inada Naoki in :issue:`44029`.) + .. _libb2: https://www.blake2.net/ diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 5926205ce5c07d6..70a1104127e9a88 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -83,6 +83,17 @@ Other Language Changes mapping is hashable. (Contributed by Serhiy Storchaka in :gh:`87995`.) +* Converting between :class:`int` and :class:`str` in bases other than 2 + (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) + now raises a :exc:`ValueError` if the number of digits in string form is + above a limit to avoid potential denial of service attacks due to the + algorithmic complexity. This is a mitigation for `CVE-2020-10735 + `_. + This limit can be configured or disabled by environment variable, command + line flag, or :mod:`sys` APIs. See the :ref:`integer string conversion + length limitation ` documentation. The default limit + is 4300 digits in string form. + New Modules =========== @@ -133,6 +144,10 @@ Optimizations It reduces object size by 8 or 16 bytes on 64bit platform. (:pep:`623`) (Contributed by Inada Naoki in :gh:`92536`.) +* Added experimental support for using the BOLT binary optimizer in the build + process, which improves performance by 1-5%. + (Contributed by Kevin Modzelewski in :gh:`90536`.) + CPython bytecode changes ======================== @@ -450,6 +465,11 @@ New Features inherit the ``Py_TPFLAGS_HAVE_VECTORCALL`` flag. (Contributed by Petr Viktorin in :gh:`93274`.) + The :const:`Py_TPFLAGS_MANAGED_DICT` and :const:`Py_TPFLAGS_MANAGED_WEAKREF` + flags have been added. This allows extensions classes to support object + ``__dict__`` and weakrefs with less bookkeeping, + using less memory and with faster access. + Porting to Python 3.12 ---------------------- @@ -486,6 +506,18 @@ Porting to Python 3.12 :c:func:`PyUnicode_FromFormatV`. (Contributed by Philip Georgi in :gh:`95504`.) +* Extension classes wanting to add a ``__dict__`` or weak reference slot + should use :const:`Py_TPFLAGS_MANAGED_DICT` and + :const:`Py_TPFLAGS_MANAGED_WEAKREF` instead of ``tp_dictoffset`` and + ``tp_weaklistoffset``, respectively. + The use of ``tp_dictoffset`` and ``tp_weaklistoffset`` is still + supported, but does not fully support multiple inheritance + (:gh: `95589`), and performance may be worse. + Classes declaring :const:`Py_TPFLAGS_MANAGED_DICT` should call + :c:func:`_PyObject_VisitManagedDict` and :c:func:`_PyObject_ClearManagedDict` + to traverse and clear their instance's dictionaries. + To clear weakrefs, call :c:func:`PyObject_ClearWeakRefs`, as before. + Deprecated ---------- diff --git a/Grammar/python.gram b/Grammar/python.gram index d4df78b679a4aca..51f846a57f404bb 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -412,7 +412,9 @@ try_stmt[stmt_ty]: | invalid_try_stmt | 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) } | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) } - | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] { _PyAST_TryStar(b, ex, el, f, EXTRA) } + | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] { + CHECK_VERSION(stmt_ty, 11, "Exception groups are", + _PyAST_TryStar(b, ex, el, f, EXTRA)) } # Except statement diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index 9d4eeafb427eb28..74665c9fa10580b 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -3,8 +3,10 @@ #endif PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); +PyAPI_FUNC(void) PyEval_SetProfileAllThreads(Py_tracefunc, PyObject *); PyAPI_DATA(int) _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); +PyAPI_FUNC(void) PyEval_SetTraceAllThreads(Py_tracefunc, PyObject *); PyAPI_FUNC(int) _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg); /* Helper to look up a builtin object */ diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 3b6d59389f26b9d..c6057a4c3ed9454 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -142,6 +142,7 @@ typedef struct PyConfig { unsigned long hash_seed; int faulthandler; int tracemalloc; + int perf_profiling; int import_time; int code_debug_ranges; int show_ref_count; diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 1b999301938c591..4914948c6ca744f 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -65,6 +65,27 @@ extern PyObject* _PyEval_BuiltinsFromGlobals( PyThreadState *tstate, PyObject *globals); +// Trampoline API + +typedef struct { + // Callback to initialize the trampoline state + void* (*init_state)(void); + // Callback to register every trampoline being created + void (*write_state)(void* state, const void *code_addr, + unsigned int code_size, PyCodeObject* code); + // Callback to free the trampoline state + int (*free_state)(void* state); +} _PyPerf_Callbacks; + +extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *); +extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *); +extern int _PyPerfTrampoline_Init(int activate); +extern int _PyPerfTrampoline_Fini(void); +extern int _PyIsPerfTrampolineActive(void); +extern PyStatus _PyPerfTrampoline_AfterFork_Child(void); +#ifdef PY_HAVE_PERF_TRAMPOLINE +extern _PyPerf_Callbacks _Py_perfmap_callbacks; +#endif static inline PyObject* _PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int throwflag) @@ -133,6 +154,9 @@ extern struct _PyInterpreterFrame* _PyEval_GetFrame(void); extern PyObject* _Py_MakeCoro(PyFunctionObject *func); +extern int _Py_HandlePending(PyThreadState *tstate); + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 61e40eb8a94c248..7d5fe941fcb4d06 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -118,6 +118,7 @@ struct callable_cache { PyObject *isinstance; PyObject *len; PyObject *list_append; + PyObject *object__getattribute__; }; /* "Locals plus" for a code object is the set of locals + cell vars + diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h index 06a6082cddae6a3..1a628a08ca4ebf4 100644 --- a/Include/internal/pycore_compile.h +++ b/Include/internal/pycore_compile.h @@ -38,6 +38,11 @@ extern int _PyAST_Optimize( struct _arena *arena, _PyASTOptimizeState *state); +/* Access compiler internals for unit testing */ +PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg( + PyObject *instructions, + PyObject *consts); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index c831c4ccbd0cb66..464092996cae005 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -62,7 +62,7 @@ extern Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); */ extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr); -extern Py_ssize_t _PyDict_GetItemHint(PyDictObject *, PyObject *, Py_ssize_t, PyObject **); +extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *); extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key); extern PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); @@ -141,17 +141,8 @@ struct _dictvalues { #define DK_LOG_SIZE(dk) ((dk)->dk_log2_size) #if SIZEOF_VOID_P > 4 #define DK_SIZE(dk) (((int64_t)1)<dk_kind == DICT_KEYS_GENERAL), \ diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 994c205c3d1644c..5bd0a7f2f517eff 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -47,7 +47,7 @@ enum _frameowner { typedef struct _PyInterpreterFrame { /* "Specials" section */ - PyFunctionObject *f_func; /* Strong reference */ + PyObject *f_funcobj; /* Strong reference */ PyObject *f_globals; /* Borrowed reference */ PyObject *f_builtins; /* Borrowed reference */ PyObject *f_locals; /* Strong reference, may be NULL */ @@ -101,7 +101,7 @@ _PyFrame_InitializeSpecials( _PyInterpreterFrame *frame, PyFunctionObject *func, PyObject *locals, PyCodeObject *code) { - frame->f_func = func; + frame->f_funcobj = (PyObject *)func; frame->f_code = (PyCodeObject *)Py_NewRef(code); frame->f_builtins = func->func_builtins; frame->f_globals = func->func_globals; @@ -190,11 +190,16 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame); void _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear); - static inline bool _PyThreadState_HasStackSpace(PyThreadState *tstate, int size) { - return tstate->datastack_top + size < tstate->datastack_limit; + assert( + (tstate->datastack_top == NULL && tstate->datastack_limit == NULL) + || + (tstate->datastack_top != NULL && tstate->datastack_limit != NULL) + ); + return tstate->datastack_top != NULL && + size < tstate->datastack_limit - tstate->datastack_top; } extern _PyInterpreterFrame * diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 98673d4efcedcc3..82e89db7b1b7507 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -45,6 +45,8 @@ struct _Py_global_objects { _PyGC_Head_UNUSED _tuple_empty_gc_not_used; PyTupleObject tuple_empty; } singletons; + + PyObject *interned; }; diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 418c6b017f5496e..121453459215763 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -298,6 +298,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(code) STRUCT_FOR_ID(command) STRUCT_FOR_ID(comment_factory) + STRUCT_FOR_ID(consts) STRUCT_FOR_ID(context) STRUCT_FOR_ID(cookie) STRUCT_FOR_ID(copy) @@ -409,6 +410,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(input) STRUCT_FOR_ID(insert_comments) STRUCT_FOR_ID(insert_pis) + STRUCT_FOR_ID(instructions) STRUCT_FOR_ID(intern) STRUCT_FOR_ID(intersection) STRUCT_FOR_ID(isatty) @@ -452,6 +454,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(mapping) STRUCT_FOR_ID(match) STRUCT_FOR_ID(max_length) + STRUCT_FOR_ID(maxdigits) STRUCT_FOR_ID(maxevents) STRUCT_FOR_ID(maxmem) STRUCT_FOR_ID(maxsplit) @@ -527,6 +530,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(protocol) STRUCT_FOR_ID(ps1) STRUCT_FOR_ID(ps2) + STRUCT_FOR_ID(query) STRUCT_FOR_ID(quotetabs) STRUCT_FOR_ID(r) STRUCT_FOR_ID(raw) diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index 69f88d7d1d46b8e..6e491261d55ca60 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -170,6 +170,8 @@ extern void _Py_DumpPathConfig(PyThreadState *tstate); PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void); +extern int _Py_global_config_int_max_str_digits; // TODO(gpshead): move this into PyConfig in 3.12 after the backports ship. + /* --- Function used for testing ---------------------------------- */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index d71386953a0dd0a..a5ddcf2d72f051e 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -176,6 +176,8 @@ struct _is { struct types_state types; struct callable_cache callable_cache; + int int_max_str_digits; + /* The following fields are here to avoid allocation during init. The data is exposed through PyInterpreterState pointer fields. These fields should not be accessed directly outside of init. diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 67dd5c3b13ec594..30c97b7edc98e15 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -11,6 +11,41 @@ extern "C" { #include "pycore_global_objects.h" // _PY_NSMALLNEGINTS #include "pycore_runtime.h" // _PyRuntime +/* + * Default int base conversion size limitation: Denial of Service prevention. + * + * Chosen such that this isn't wildly slow on modern hardware and so that + * everyone's existing deployed numpy test suite passes before + * https://github.com/numpy/numpy/issues/22098 is widely available. + * + * $ python -m timeit -s 's = "1"*4300' 'int(s)' + * 2000 loops, best of 5: 125 usec per loop + * $ python -m timeit -s 's = "1"*4300; v = int(s)' 'str(v)' + * 1000 loops, best of 5: 311 usec per loop + * (zen2 cloud VM) + * + * 4300 decimal digits fits a ~14284 bit number. + */ +#define _PY_LONG_DEFAULT_MAX_STR_DIGITS 4300 +/* + * Threshold for max digits check. For performance reasons int() and + * int.__str__() don't checks values that are smaller than this + * threshold. Acts as a guaranteed minimum size limit for bignums that + * applications can expect from CPython. + * + * % python -m timeit -s 's = "1"*640; v = int(s)' 'str(int(s))' + * 20000 loops, best of 5: 12 usec per loop + * + * "640 digits should be enough for anyone." - gps + * fits a ~2126 bit decimal number. + */ +#define _PY_LONG_MAX_STR_DIGITS_THRESHOLD 640 + +#if ((_PY_LONG_DEFAULT_MAX_STR_DIGITS != 0) && \ + (_PY_LONG_DEFAULT_MAX_STR_DIGITS < _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) +# error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold." +#endif + /* runtime lifecycle */ diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 90bf5bbd1baa02e..15925511cc1f413 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -23,10 +23,10 @@ static const uint32_t _PyOpcode_RelativeJump[9] = { 536870912U, 135118848U, 4163U, - 122880U, 0U, 0U, - 1008U, + 0U, + 48U, }; static const uint32_t _PyOpcode_Jump[9] = { 0U, @@ -34,10 +34,10 @@ static const uint32_t _PyOpcode_Jump[9] = { 536870912U, 135118848U, 4163U, - 122880U, 0U, 0U, - 1008U, + 0U, + 48U, }; const uint8_t _PyOpcode_Caches[256] = { @@ -104,6 +104,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [CALL_PY_WITH_DEFAULTS] = CALL, [CHECK_EG_MATCH] = CHECK_EG_MATCH, [CHECK_EXC_MATCH] = CHECK_EXC_MATCH, + [CLEANUP_THROW] = CLEANUP_THROW, [COMPARE_OP] = COMPARE_OP, [COMPARE_OP_ADAPTIVE] = COMPARE_OP, [COMPARE_OP_FLOAT_JUMP] = COMPARE_OP, @@ -152,6 +153,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [LOAD_ATTR] = LOAD_ATTR, [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, [LOAD_ATTR_CLASS] = LOAD_ATTR, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = LOAD_ATTR, [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, @@ -185,14 +187,10 @@ const uint8_t _PyOpcode_Deopt[256] = { [MATCH_SEQUENCE] = MATCH_SEQUENCE, [NOP] = NOP, [POP_EXCEPT] = POP_EXCEPT, - [POP_JUMP_BACKWARD_IF_FALSE] = POP_JUMP_BACKWARD_IF_FALSE, - [POP_JUMP_BACKWARD_IF_NONE] = POP_JUMP_BACKWARD_IF_NONE, - [POP_JUMP_BACKWARD_IF_NOT_NONE] = POP_JUMP_BACKWARD_IF_NOT_NONE, - [POP_JUMP_BACKWARD_IF_TRUE] = POP_JUMP_BACKWARD_IF_TRUE, - [POP_JUMP_FORWARD_IF_FALSE] = POP_JUMP_FORWARD_IF_FALSE, - [POP_JUMP_FORWARD_IF_NONE] = POP_JUMP_FORWARD_IF_NONE, - [POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE, - [POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE, + [POP_JUMP_IF_FALSE] = POP_JUMP_IF_FALSE, + [POP_JUMP_IF_NONE] = POP_JUMP_IF_NONE, + [POP_JUMP_IF_NOT_NONE] = POP_JUMP_IF_NOT_NONE, + [POP_JUMP_IF_TRUE] = POP_JUMP_IF_TRUE, [POP_TOP] = POP_TOP, [PREP_RERAISE_STAR] = PREP_RERAISE_STAR, [PRINT_EXPR] = PRINT_EXPR, @@ -241,7 +239,7 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_TABLES #ifdef Py_DEBUG -static const char *const _PyOpcode_OpName[267] = { +static const char *const _PyOpcode_OpName[263] = { [CACHE] = "CACHE", [POP_TOP] = "POP_TOP", [PUSH_NULL] = "PUSH_NULL", @@ -297,38 +295,38 @@ static const char *const _PyOpcode_OpName[267] = { [BEFORE_ASYNC_WITH] = "BEFORE_ASYNC_WITH", [BEFORE_WITH] = "BEFORE_WITH", [END_ASYNC_FOR] = "END_ASYNC_FOR", + [CLEANUP_THROW] = "CLEANUP_THROW", [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1", [COMPARE_OP_ADAPTIVE] = "COMPARE_OP_ADAPTIVE", [COMPARE_OP_FLOAT_JUMP] = "COMPARE_OP_FLOAT_JUMP", [COMPARE_OP_INT_JUMP] = "COMPARE_OP_INT_JUMP", - [COMPARE_OP_STR_JUMP] = "COMPARE_OP_STR_JUMP", [STORE_SUBSCR] = "STORE_SUBSCR", [DELETE_SUBSCR] = "DELETE_SUBSCR", + [COMPARE_OP_STR_JUMP] = "COMPARE_OP_STR_JUMP", [EXTENDED_ARG_QUICK] = "EXTENDED_ARG_QUICK", [FOR_ITER_ADAPTIVE] = "FOR_ITER_ADAPTIVE", [FOR_ITER_LIST] = "FOR_ITER_LIST", [FOR_ITER_RANGE] = "FOR_ITER_RANGE", [JUMP_BACKWARD_QUICK] = "JUMP_BACKWARD_QUICK", - [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [GET_ITER] = "GET_ITER", [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [PRINT_EXPR] = "PRINT_EXPR", [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", + [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS", - [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", [RETURN_GENERATOR] = "RETURN_GENERATOR", + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", + [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY", [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", - [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", - [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", [LIST_TO_TUPLE] = "LIST_TO_TUPLE", [RETURN_VALUE] = "RETURN_VALUE", [IMPORT_STAR] = "IMPORT_STAR", [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", - [LOAD_ATTR_METHOD_WITH_DICT] = "LOAD_ATTR_METHOD_WITH_DICT", + [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", [ASYNC_GEN_WRAP] = "ASYNC_GEN_WRAP", [PREP_RERAISE_STAR] = "PREP_RERAISE_STAR", [POP_EXCEPT] = "POP_EXCEPT", @@ -355,23 +353,23 @@ static const char *const _PyOpcode_OpName[267] = { [JUMP_FORWARD] = "JUMP_FORWARD", [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", - [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", - [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", - [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", + [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", + [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE", + [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", [IS_OP] = "IS_OP", [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", + [LOAD_ATTR_METHOD_WITH_DICT] = "LOAD_ATTR_METHOD_WITH_DICT", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", [STORE_FAST] = "STORE_FAST", [DELETE_FAST] = "DELETE_FAST", [LOAD_FAST_CHECK] = "LOAD_FAST_CHECK", - [POP_JUMP_FORWARD_IF_NOT_NONE] = "POP_JUMP_FORWARD_IF_NOT_NONE", - [POP_JUMP_FORWARD_IF_NONE] = "POP_JUMP_FORWARD_IF_NONE", + [POP_JUMP_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE", + [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE", [RAISE_VARARGS] = "RAISE_VARARGS", [GET_AWAITABLE] = "GET_AWAITABLE", [MAKE_FUNCTION] = "MAKE_FUNCTION", @@ -383,9 +381,9 @@ static const char *const _PyOpcode_OpName[267] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", + [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", + [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", @@ -395,36 +393,36 @@ static const char *const _PyOpcode_OpName[267] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", + [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [RESUME_QUICK] = "RESUME_QUICK", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", - [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", - [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", - [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", - [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", - [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", - [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", + [181] = "<181>", + [182] = "<182>", [183] = "<183>", [184] = "<184>", [185] = "<185>", @@ -504,15 +502,13 @@ static const char *const _PyOpcode_OpName[267] = { [POP_BLOCK] = "POP_BLOCK", [JUMP] = "JUMP", [JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT", - [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE", - [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE", - [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE", - [POP_JUMP_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE", [LOAD_METHOD] = "LOAD_METHOD", }; #endif #define EXTRA_CASES \ + case 181: \ + case 182: \ case 183: \ case 184: \ case 185: \ diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 51d119c23e731ba..3d6d400f74dd1de 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -85,13 +85,14 @@ _PyThreadState_GET(void) return _PyRuntimeState_GetThreadState(&_PyRuntime); } -PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalError_TstateNULL(const char *func); - static inline void _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate) { if (tstate == NULL) { - _Py_FatalError_TstateNULL(func); + _Py_FatalErrorFunc(func, + "the function must be called with the GIL held, " + "after Python initialization and before Python finalization, " + "but the GIL is released (the current Python thread state is NULL)"); } } diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index c14d25941348bfe..621d5cc864255d2 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -113,10 +113,12 @@ extern "C" { ._ ## NAME = _PyASCIIObject_INIT(LITERAL) #define INIT_ID(NAME) \ ._ ## NAME = _PyASCIIObject_INIT(#NAME) -#define _PyUnicode_LATIN1_INIT(LITERAL) \ +#define _PyUnicode_LATIN1_INIT(LITERAL, UTF8) \ { \ ._latin1 = { \ ._base = _PyUnicode_ASCII_BASE_INIT((LITERAL), 0), \ + .utf8 = (UTF8), \ + .utf8_length = sizeof(UTF8) - 1, \ }, \ ._data = (LITERAL), \ } diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 0951131f94dddc2..37110c2e8d955f0 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -807,6 +807,7 @@ extern "C" { INIT_ID(code), \ INIT_ID(command), \ INIT_ID(comment_factory), \ + INIT_ID(consts), \ INIT_ID(context), \ INIT_ID(cookie), \ INIT_ID(copy), \ @@ -918,6 +919,7 @@ extern "C" { INIT_ID(input), \ INIT_ID(insert_comments), \ INIT_ID(insert_pis), \ + INIT_ID(instructions), \ INIT_ID(intern), \ INIT_ID(intersection), \ INIT_ID(isatty), \ @@ -961,6 +963,7 @@ extern "C" { INIT_ID(mapping), \ INIT_ID(match), \ INIT_ID(max_length), \ + INIT_ID(maxdigits), \ INIT_ID(maxevents), \ INIT_ID(maxmem), \ INIT_ID(maxsplit), \ @@ -1036,6 +1039,7 @@ extern "C" { INIT_ID(protocol), \ INIT_ID(ps1), \ INIT_ID(ps2), \ + INIT_ID(query), \ INIT_ID(quotetabs), \ INIT_ID(r), \ INIT_ID(raw), \ @@ -1287,134 +1291,134 @@ extern "C" { _PyASCIIObject_INIT("\x7f"), \ }, \ .latin1 = { \ - _PyUnicode_LATIN1_INIT("\x80"), \ - _PyUnicode_LATIN1_INIT("\x81"), \ - _PyUnicode_LATIN1_INIT("\x82"), \ - _PyUnicode_LATIN1_INIT("\x83"), \ - _PyUnicode_LATIN1_INIT("\x84"), \ - _PyUnicode_LATIN1_INIT("\x85"), \ - _PyUnicode_LATIN1_INIT("\x86"), \ - _PyUnicode_LATIN1_INIT("\x87"), \ - _PyUnicode_LATIN1_INIT("\x88"), \ - _PyUnicode_LATIN1_INIT("\x89"), \ - _PyUnicode_LATIN1_INIT("\x8a"), \ - _PyUnicode_LATIN1_INIT("\x8b"), \ - _PyUnicode_LATIN1_INIT("\x8c"), \ - _PyUnicode_LATIN1_INIT("\x8d"), \ - _PyUnicode_LATIN1_INIT("\x8e"), \ - _PyUnicode_LATIN1_INIT("\x8f"), \ - _PyUnicode_LATIN1_INIT("\x90"), \ - _PyUnicode_LATIN1_INIT("\x91"), \ - _PyUnicode_LATIN1_INIT("\x92"), \ - _PyUnicode_LATIN1_INIT("\x93"), \ - _PyUnicode_LATIN1_INIT("\x94"), \ - _PyUnicode_LATIN1_INIT("\x95"), \ - _PyUnicode_LATIN1_INIT("\x96"), \ - _PyUnicode_LATIN1_INIT("\x97"), \ - _PyUnicode_LATIN1_INIT("\x98"), \ - _PyUnicode_LATIN1_INIT("\x99"), \ - _PyUnicode_LATIN1_INIT("\x9a"), \ - _PyUnicode_LATIN1_INIT("\x9b"), \ - _PyUnicode_LATIN1_INIT("\x9c"), \ - _PyUnicode_LATIN1_INIT("\x9d"), \ - _PyUnicode_LATIN1_INIT("\x9e"), \ - _PyUnicode_LATIN1_INIT("\x9f"), \ - _PyUnicode_LATIN1_INIT("\xa0"), \ - _PyUnicode_LATIN1_INIT("\xa1"), \ - _PyUnicode_LATIN1_INIT("\xa2"), \ - _PyUnicode_LATIN1_INIT("\xa3"), \ - _PyUnicode_LATIN1_INIT("\xa4"), \ - _PyUnicode_LATIN1_INIT("\xa5"), \ - _PyUnicode_LATIN1_INIT("\xa6"), \ - _PyUnicode_LATIN1_INIT("\xa7"), \ - _PyUnicode_LATIN1_INIT("\xa8"), \ - _PyUnicode_LATIN1_INIT("\xa9"), \ - _PyUnicode_LATIN1_INIT("\xaa"), \ - _PyUnicode_LATIN1_INIT("\xab"), \ - _PyUnicode_LATIN1_INIT("\xac"), \ - _PyUnicode_LATIN1_INIT("\xad"), \ - _PyUnicode_LATIN1_INIT("\xae"), \ - _PyUnicode_LATIN1_INIT("\xaf"), \ - _PyUnicode_LATIN1_INIT("\xb0"), \ - _PyUnicode_LATIN1_INIT("\xb1"), \ - _PyUnicode_LATIN1_INIT("\xb2"), \ - _PyUnicode_LATIN1_INIT("\xb3"), \ - _PyUnicode_LATIN1_INIT("\xb4"), \ - _PyUnicode_LATIN1_INIT("\xb5"), \ - _PyUnicode_LATIN1_INIT("\xb6"), \ - _PyUnicode_LATIN1_INIT("\xb7"), \ - _PyUnicode_LATIN1_INIT("\xb8"), \ - _PyUnicode_LATIN1_INIT("\xb9"), \ - _PyUnicode_LATIN1_INIT("\xba"), \ - _PyUnicode_LATIN1_INIT("\xbb"), \ - _PyUnicode_LATIN1_INIT("\xbc"), \ - _PyUnicode_LATIN1_INIT("\xbd"), \ - _PyUnicode_LATIN1_INIT("\xbe"), \ - _PyUnicode_LATIN1_INIT("\xbf"), \ - _PyUnicode_LATIN1_INIT("\xc0"), \ - _PyUnicode_LATIN1_INIT("\xc1"), \ - _PyUnicode_LATIN1_INIT("\xc2"), \ - _PyUnicode_LATIN1_INIT("\xc3"), \ - _PyUnicode_LATIN1_INIT("\xc4"), \ - _PyUnicode_LATIN1_INIT("\xc5"), \ - _PyUnicode_LATIN1_INIT("\xc6"), \ - _PyUnicode_LATIN1_INIT("\xc7"), \ - _PyUnicode_LATIN1_INIT("\xc8"), \ - _PyUnicode_LATIN1_INIT("\xc9"), \ - _PyUnicode_LATIN1_INIT("\xca"), \ - _PyUnicode_LATIN1_INIT("\xcb"), \ - _PyUnicode_LATIN1_INIT("\xcc"), \ - _PyUnicode_LATIN1_INIT("\xcd"), \ - _PyUnicode_LATIN1_INIT("\xce"), \ - _PyUnicode_LATIN1_INIT("\xcf"), \ - _PyUnicode_LATIN1_INIT("\xd0"), \ - _PyUnicode_LATIN1_INIT("\xd1"), \ - _PyUnicode_LATIN1_INIT("\xd2"), \ - _PyUnicode_LATIN1_INIT("\xd3"), \ - _PyUnicode_LATIN1_INIT("\xd4"), \ - _PyUnicode_LATIN1_INIT("\xd5"), \ - _PyUnicode_LATIN1_INIT("\xd6"), \ - _PyUnicode_LATIN1_INIT("\xd7"), \ - _PyUnicode_LATIN1_INIT("\xd8"), \ - _PyUnicode_LATIN1_INIT("\xd9"), \ - _PyUnicode_LATIN1_INIT("\xda"), \ - _PyUnicode_LATIN1_INIT("\xdb"), \ - _PyUnicode_LATIN1_INIT("\xdc"), \ - _PyUnicode_LATIN1_INIT("\xdd"), \ - _PyUnicode_LATIN1_INIT("\xde"), \ - _PyUnicode_LATIN1_INIT("\xdf"), \ - _PyUnicode_LATIN1_INIT("\xe0"), \ - _PyUnicode_LATIN1_INIT("\xe1"), \ - _PyUnicode_LATIN1_INIT("\xe2"), \ - _PyUnicode_LATIN1_INIT("\xe3"), \ - _PyUnicode_LATIN1_INIT("\xe4"), \ - _PyUnicode_LATIN1_INIT("\xe5"), \ - _PyUnicode_LATIN1_INIT("\xe6"), \ - _PyUnicode_LATIN1_INIT("\xe7"), \ - _PyUnicode_LATIN1_INIT("\xe8"), \ - _PyUnicode_LATIN1_INIT("\xe9"), \ - _PyUnicode_LATIN1_INIT("\xea"), \ - _PyUnicode_LATIN1_INIT("\xeb"), \ - _PyUnicode_LATIN1_INIT("\xec"), \ - _PyUnicode_LATIN1_INIT("\xed"), \ - _PyUnicode_LATIN1_INIT("\xee"), \ - _PyUnicode_LATIN1_INIT("\xef"), \ - _PyUnicode_LATIN1_INIT("\xf0"), \ - _PyUnicode_LATIN1_INIT("\xf1"), \ - _PyUnicode_LATIN1_INIT("\xf2"), \ - _PyUnicode_LATIN1_INIT("\xf3"), \ - _PyUnicode_LATIN1_INIT("\xf4"), \ - _PyUnicode_LATIN1_INIT("\xf5"), \ - _PyUnicode_LATIN1_INIT("\xf6"), \ - _PyUnicode_LATIN1_INIT("\xf7"), \ - _PyUnicode_LATIN1_INIT("\xf8"), \ - _PyUnicode_LATIN1_INIT("\xf9"), \ - _PyUnicode_LATIN1_INIT("\xfa"), \ - _PyUnicode_LATIN1_INIT("\xfb"), \ - _PyUnicode_LATIN1_INIT("\xfc"), \ - _PyUnicode_LATIN1_INIT("\xfd"), \ - _PyUnicode_LATIN1_INIT("\xfe"), \ - _PyUnicode_LATIN1_INIT("\xff"), \ + _PyUnicode_LATIN1_INIT("\x80", "\xc2\x80"), \ + _PyUnicode_LATIN1_INIT("\x81", "\xc2\x81"), \ + _PyUnicode_LATIN1_INIT("\x82", "\xc2\x82"), \ + _PyUnicode_LATIN1_INIT("\x83", "\xc2\x83"), \ + _PyUnicode_LATIN1_INIT("\x84", "\xc2\x84"), \ + _PyUnicode_LATIN1_INIT("\x85", "\xc2\x85"), \ + _PyUnicode_LATIN1_INIT("\x86", "\xc2\x86"), \ + _PyUnicode_LATIN1_INIT("\x87", "\xc2\x87"), \ + _PyUnicode_LATIN1_INIT("\x88", "\xc2\x88"), \ + _PyUnicode_LATIN1_INIT("\x89", "\xc2\x89"), \ + _PyUnicode_LATIN1_INIT("\x8a", "\xc2\x8a"), \ + _PyUnicode_LATIN1_INIT("\x8b", "\xc2\x8b"), \ + _PyUnicode_LATIN1_INIT("\x8c", "\xc2\x8c"), \ + _PyUnicode_LATIN1_INIT("\x8d", "\xc2\x8d"), \ + _PyUnicode_LATIN1_INIT("\x8e", "\xc2\x8e"), \ + _PyUnicode_LATIN1_INIT("\x8f", "\xc2\x8f"), \ + _PyUnicode_LATIN1_INIT("\x90", "\xc2\x90"), \ + _PyUnicode_LATIN1_INIT("\x91", "\xc2\x91"), \ + _PyUnicode_LATIN1_INIT("\x92", "\xc2\x92"), \ + _PyUnicode_LATIN1_INIT("\x93", "\xc2\x93"), \ + _PyUnicode_LATIN1_INIT("\x94", "\xc2\x94"), \ + _PyUnicode_LATIN1_INIT("\x95", "\xc2\x95"), \ + _PyUnicode_LATIN1_INIT("\x96", "\xc2\x96"), \ + _PyUnicode_LATIN1_INIT("\x97", "\xc2\x97"), \ + _PyUnicode_LATIN1_INIT("\x98", "\xc2\x98"), \ + _PyUnicode_LATIN1_INIT("\x99", "\xc2\x99"), \ + _PyUnicode_LATIN1_INIT("\x9a", "\xc2\x9a"), \ + _PyUnicode_LATIN1_INIT("\x9b", "\xc2\x9b"), \ + _PyUnicode_LATIN1_INIT("\x9c", "\xc2\x9c"), \ + _PyUnicode_LATIN1_INIT("\x9d", "\xc2\x9d"), \ + _PyUnicode_LATIN1_INIT("\x9e", "\xc2\x9e"), \ + _PyUnicode_LATIN1_INIT("\x9f", "\xc2\x9f"), \ + _PyUnicode_LATIN1_INIT("\xa0", "\xc2\xa0"), \ + _PyUnicode_LATIN1_INIT("\xa1", "\xc2\xa1"), \ + _PyUnicode_LATIN1_INIT("\xa2", "\xc2\xa2"), \ + _PyUnicode_LATIN1_INIT("\xa3", "\xc2\xa3"), \ + _PyUnicode_LATIN1_INIT("\xa4", "\xc2\xa4"), \ + _PyUnicode_LATIN1_INIT("\xa5", "\xc2\xa5"), \ + _PyUnicode_LATIN1_INIT("\xa6", "\xc2\xa6"), \ + _PyUnicode_LATIN1_INIT("\xa7", "\xc2\xa7"), \ + _PyUnicode_LATIN1_INIT("\xa8", "\xc2\xa8"), \ + _PyUnicode_LATIN1_INIT("\xa9", "\xc2\xa9"), \ + _PyUnicode_LATIN1_INIT("\xaa", "\xc2\xaa"), \ + _PyUnicode_LATIN1_INIT("\xab", "\xc2\xab"), \ + _PyUnicode_LATIN1_INIT("\xac", "\xc2\xac"), \ + _PyUnicode_LATIN1_INIT("\xad", "\xc2\xad"), \ + _PyUnicode_LATIN1_INIT("\xae", "\xc2\xae"), \ + _PyUnicode_LATIN1_INIT("\xaf", "\xc2\xaf"), \ + _PyUnicode_LATIN1_INIT("\xb0", "\xc2\xb0"), \ + _PyUnicode_LATIN1_INIT("\xb1", "\xc2\xb1"), \ + _PyUnicode_LATIN1_INIT("\xb2", "\xc2\xb2"), \ + _PyUnicode_LATIN1_INIT("\xb3", "\xc2\xb3"), \ + _PyUnicode_LATIN1_INIT("\xb4", "\xc2\xb4"), \ + _PyUnicode_LATIN1_INIT("\xb5", "\xc2\xb5"), \ + _PyUnicode_LATIN1_INIT("\xb6", "\xc2\xb6"), \ + _PyUnicode_LATIN1_INIT("\xb7", "\xc2\xb7"), \ + _PyUnicode_LATIN1_INIT("\xb8", "\xc2\xb8"), \ + _PyUnicode_LATIN1_INIT("\xb9", "\xc2\xb9"), \ + _PyUnicode_LATIN1_INIT("\xba", "\xc2\xba"), \ + _PyUnicode_LATIN1_INIT("\xbb", "\xc2\xbb"), \ + _PyUnicode_LATIN1_INIT("\xbc", "\xc2\xbc"), \ + _PyUnicode_LATIN1_INIT("\xbd", "\xc2\xbd"), \ + _PyUnicode_LATIN1_INIT("\xbe", "\xc2\xbe"), \ + _PyUnicode_LATIN1_INIT("\xbf", "\xc2\xbf"), \ + _PyUnicode_LATIN1_INIT("\xc0", "\xc3\x80"), \ + _PyUnicode_LATIN1_INIT("\xc1", "\xc3\x81"), \ + _PyUnicode_LATIN1_INIT("\xc2", "\xc3\x82"), \ + _PyUnicode_LATIN1_INIT("\xc3", "\xc3\x83"), \ + _PyUnicode_LATIN1_INIT("\xc4", "\xc3\x84"), \ + _PyUnicode_LATIN1_INIT("\xc5", "\xc3\x85"), \ + _PyUnicode_LATIN1_INIT("\xc6", "\xc3\x86"), \ + _PyUnicode_LATIN1_INIT("\xc7", "\xc3\x87"), \ + _PyUnicode_LATIN1_INIT("\xc8", "\xc3\x88"), \ + _PyUnicode_LATIN1_INIT("\xc9", "\xc3\x89"), \ + _PyUnicode_LATIN1_INIT("\xca", "\xc3\x8a"), \ + _PyUnicode_LATIN1_INIT("\xcb", "\xc3\x8b"), \ + _PyUnicode_LATIN1_INIT("\xcc", "\xc3\x8c"), \ + _PyUnicode_LATIN1_INIT("\xcd", "\xc3\x8d"), \ + _PyUnicode_LATIN1_INIT("\xce", "\xc3\x8e"), \ + _PyUnicode_LATIN1_INIT("\xcf", "\xc3\x8f"), \ + _PyUnicode_LATIN1_INIT("\xd0", "\xc3\x90"), \ + _PyUnicode_LATIN1_INIT("\xd1", "\xc3\x91"), \ + _PyUnicode_LATIN1_INIT("\xd2", "\xc3\x92"), \ + _PyUnicode_LATIN1_INIT("\xd3", "\xc3\x93"), \ + _PyUnicode_LATIN1_INIT("\xd4", "\xc3\x94"), \ + _PyUnicode_LATIN1_INIT("\xd5", "\xc3\x95"), \ + _PyUnicode_LATIN1_INIT("\xd6", "\xc3\x96"), \ + _PyUnicode_LATIN1_INIT("\xd7", "\xc3\x97"), \ + _PyUnicode_LATIN1_INIT("\xd8", "\xc3\x98"), \ + _PyUnicode_LATIN1_INIT("\xd9", "\xc3\x99"), \ + _PyUnicode_LATIN1_INIT("\xda", "\xc3\x9a"), \ + _PyUnicode_LATIN1_INIT("\xdb", "\xc3\x9b"), \ + _PyUnicode_LATIN1_INIT("\xdc", "\xc3\x9c"), \ + _PyUnicode_LATIN1_INIT("\xdd", "\xc3\x9d"), \ + _PyUnicode_LATIN1_INIT("\xde", "\xc3\x9e"), \ + _PyUnicode_LATIN1_INIT("\xdf", "\xc3\x9f"), \ + _PyUnicode_LATIN1_INIT("\xe0", "\xc3\xa0"), \ + _PyUnicode_LATIN1_INIT("\xe1", "\xc3\xa1"), \ + _PyUnicode_LATIN1_INIT("\xe2", "\xc3\xa2"), \ + _PyUnicode_LATIN1_INIT("\xe3", "\xc3\xa3"), \ + _PyUnicode_LATIN1_INIT("\xe4", "\xc3\xa4"), \ + _PyUnicode_LATIN1_INIT("\xe5", "\xc3\xa5"), \ + _PyUnicode_LATIN1_INIT("\xe6", "\xc3\xa6"), \ + _PyUnicode_LATIN1_INIT("\xe7", "\xc3\xa7"), \ + _PyUnicode_LATIN1_INIT("\xe8", "\xc3\xa8"), \ + _PyUnicode_LATIN1_INIT("\xe9", "\xc3\xa9"), \ + _PyUnicode_LATIN1_INIT("\xea", "\xc3\xaa"), \ + _PyUnicode_LATIN1_INIT("\xeb", "\xc3\xab"), \ + _PyUnicode_LATIN1_INIT("\xec", "\xc3\xac"), \ + _PyUnicode_LATIN1_INIT("\xed", "\xc3\xad"), \ + _PyUnicode_LATIN1_INIT("\xee", "\xc3\xae"), \ + _PyUnicode_LATIN1_INIT("\xef", "\xc3\xaf"), \ + _PyUnicode_LATIN1_INIT("\xf0", "\xc3\xb0"), \ + _PyUnicode_LATIN1_INIT("\xf1", "\xc3\xb1"), \ + _PyUnicode_LATIN1_INIT("\xf2", "\xc3\xb2"), \ + _PyUnicode_LATIN1_INIT("\xf3", "\xc3\xb3"), \ + _PyUnicode_LATIN1_INIT("\xf4", "\xc3\xb4"), \ + _PyUnicode_LATIN1_INIT("\xf5", "\xc3\xb5"), \ + _PyUnicode_LATIN1_INIT("\xf6", "\xc3\xb6"), \ + _PyUnicode_LATIN1_INIT("\xf7", "\xc3\xb7"), \ + _PyUnicode_LATIN1_INIT("\xf8", "\xc3\xb8"), \ + _PyUnicode_LATIN1_INIT("\xf9", "\xc3\xb9"), \ + _PyUnicode_LATIN1_INIT("\xfa", "\xc3\xba"), \ + _PyUnicode_LATIN1_INIT("\xfb", "\xc3\xbb"), \ + _PyUnicode_LATIN1_INIT("\xfc", "\xc3\xbc"), \ + _PyUnicode_LATIN1_INIT("\xfd", "\xc3\xbd"), \ + _PyUnicode_LATIN1_INIT("\xfe", "\xc3\xbe"), \ + _PyUnicode_LATIN1_INIT("\xff", "\xc3\xbf"), \ }, \ }, \ \ @@ -1919,6 +1923,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(comment_factory); PyUnicode_InternInPlace(&string); + string = &_Py_ID(consts); + PyUnicode_InternInPlace(&string); string = &_Py_ID(context); PyUnicode_InternInPlace(&string); string = &_Py_ID(cookie); @@ -2141,6 +2147,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(insert_pis); PyUnicode_InternInPlace(&string); + string = &_Py_ID(instructions); + PyUnicode_InternInPlace(&string); string = &_Py_ID(intern); PyUnicode_InternInPlace(&string); string = &_Py_ID(intersection); @@ -2227,6 +2235,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(max_length); PyUnicode_InternInPlace(&string); + string = &_Py_ID(maxdigits); + PyUnicode_InternInPlace(&string); string = &_Py_ID(maxevents); PyUnicode_InternInPlace(&string); string = &_Py_ID(maxmem); @@ -2377,6 +2387,8 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(ps2); PyUnicode_InternInPlace(&string); + string = &_Py_ID(query); + PyUnicode_InternInPlace(&string); string = &_Py_ID(quotetabs); PyUnicode_InternInPlace(&string); string = &_Py_ID(r); @@ -5764,6 +5776,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(comment_factory)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(consts)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(consts)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(context)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(context)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -6208,6 +6224,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(insert_pis)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(instructions)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(instructions)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(intern)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(intern)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -6380,6 +6400,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(max_length)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(maxdigits)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(maxdigits)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(maxevents)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(maxevents)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); @@ -6680,6 +6704,10 @@ _PyStaticObjects_CheckRefcnt(void) { _PyObject_Dump((PyObject *)&_Py_ID(ps2)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); }; + if (Py_REFCNT((PyObject *)&_Py_ID(query)) < _PyObject_IMMORTAL_REFCNT) { + _PyObject_Dump((PyObject *)&_Py_ID(query)); + Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); + }; if (Py_REFCNT((PyObject *)&_Py_ID(quotetabs)) < _PyObject_IMMORTAL_REFCNT) { _PyObject_Dump((PyObject *)&_Py_ID(quotetabs)); Py_FatalError("immortal object has less refcnt than expected _PyObject_IMMORTAL_REFCNT"); diff --git a/Include/internal/pycore_typeobject.h b/Include/internal/pycore_typeobject.h index 4eb0efcedb5e0d3..2efe388100716c8 100644 --- a/Include/internal/pycore_typeobject.h +++ b/Include/internal/pycore_typeobject.h @@ -75,6 +75,9 @@ extern void _PyStaticType_ClearWeakRefs(PyTypeObject *type); extern void _PyStaticType_Dealloc(PyTypeObject *type); +PyObject *_Py_slot_tp_getattro(PyObject *self, PyObject *name); +PyObject *_Py_slot_tp_getattr_hook(PyObject *self, PyObject *name); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 4bee2419fbd98ac..63bf04b3e1b872c 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -19,7 +19,6 @@ extern PyStatus _PyUnicode_InitGlobalObjects(PyInterpreterState *); extern PyStatus _PyUnicode_InitTypes(PyInterpreterState *); extern void _PyUnicode_Fini(PyInterpreterState *); extern void _PyUnicode_FiniTypes(PyInterpreterState *); -extern void _PyStaticUnicode_Dealloc(PyObject *); extern PyTypeObject _PyUnicodeASCIIIter_Type; diff --git a/Include/object.h b/Include/object.h index 21d3a75834eba5e..75624fe8c77a514 100644 --- a/Include/object.h +++ b/Include/object.h @@ -511,11 +511,11 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *); static inline void Py_INCREF(PyObject *op) { - _Py_INCREF_STAT_INC(); #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 // Stable ABI for Python 3.10 built in debug mode. _Py_IncRef(op); #else + _Py_INCREF_STAT_INC(); // Non-limited C API and limited C API for Python 3.9 and older access // directly PyObject.ob_refcnt. #ifdef Py_REF_DEBUG diff --git a/Include/opcode.h b/Include/opcode.h index f90ebb1d6e01cb6..42825df6217b463 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -32,6 +32,7 @@ extern "C" { #define BEFORE_ASYNC_WITH 52 #define BEFORE_WITH 53 #define END_ASYNC_FOR 54 +#define CLEANUP_THROW 55 #define STORE_SUBSCR 60 #define DELETE_SUBSCR 61 #define GET_ITER 68 @@ -71,8 +72,8 @@ extern "C" { #define JUMP_FORWARD 110 #define JUMP_IF_FALSE_OR_POP 111 #define JUMP_IF_TRUE_OR_POP 112 -#define POP_JUMP_FORWARD_IF_FALSE 114 -#define POP_JUMP_FORWARD_IF_TRUE 115 +#define POP_JUMP_IF_FALSE 114 +#define POP_JUMP_IF_TRUE 115 #define LOAD_GLOBAL 116 #define IS_OP 117 #define CONTAINS_OP 118 @@ -84,8 +85,8 @@ extern "C" { #define STORE_FAST 125 #define DELETE_FAST 126 #define LOAD_FAST_CHECK 127 -#define POP_JUMP_FORWARD_IF_NOT_NONE 128 -#define POP_JUMP_FORWARD_IF_NONE 129 +#define POP_JUMP_IF_NOT_NONE 128 +#define POP_JUMP_IF_NONE 129 #define RAISE_VARARGS 130 #define GET_AWAITABLE 131 #define MAKE_FUNCTION 132 @@ -116,10 +117,6 @@ extern "C" { #define DICT_UPDATE 165 #define CALL 171 #define KW_NAMES 172 -#define POP_JUMP_BACKWARD_IF_NOT_NONE 173 -#define POP_JUMP_BACKWARD_IF_NONE 174 -#define POP_JUMP_BACKWARD_IF_FALSE 175 -#define POP_JUMP_BACKWARD_IF_TRUE 176 #define MIN_PSEUDO_OPCODE 256 #define SETUP_FINALLY 256 #define SETUP_CLEANUP 257 @@ -127,12 +124,8 @@ extern "C" { #define POP_BLOCK 259 #define JUMP 260 #define JUMP_NO_INTERRUPT 261 -#define POP_JUMP_IF_FALSE 262 -#define POP_JUMP_IF_TRUE 263 -#define POP_JUMP_IF_NONE 264 -#define POP_JUMP_IF_NOT_NONE 265 -#define LOAD_METHOD 266 -#define MAX_PSEUDO_OPCODE 266 +#define LOAD_METHOD 262 +#define MAX_PSEUDO_OPCODE 262 #define BINARY_OP_ADAPTIVE 3 #define BINARY_OP_ADD_FLOAT 4 #define BINARY_OP_ADD_INT 5 @@ -164,56 +157,53 @@ extern "C" { #define CALL_NO_KW_METHOD_DESCRIPTOR_O 46 #define CALL_NO_KW_STR_1 47 #define CALL_NO_KW_TUPLE_1 48 -#define CALL_NO_KW_TYPE_1 55 -#define COMPARE_OP_ADAPTIVE 56 -#define COMPARE_OP_FLOAT_JUMP 57 -#define COMPARE_OP_INT_JUMP 58 -#define COMPARE_OP_STR_JUMP 59 -#define EXTENDED_ARG_QUICK 62 -#define FOR_ITER_ADAPTIVE 63 -#define FOR_ITER_LIST 64 -#define FOR_ITER_RANGE 65 -#define JUMP_BACKWARD_QUICK 66 -#define LOAD_ATTR_ADAPTIVE 67 -#define LOAD_ATTR_CLASS 72 -#define LOAD_ATTR_INSTANCE_VALUE 73 -#define LOAD_ATTR_MODULE 76 -#define LOAD_ATTR_PROPERTY 77 -#define LOAD_ATTR_SLOT 78 -#define LOAD_ATTR_WITH_HINT 79 -#define LOAD_ATTR_METHOD_LAZY_DICT 80 -#define LOAD_ATTR_METHOD_NO_DICT 81 -#define LOAD_ATTR_METHOD_WITH_DICT 86 -#define LOAD_ATTR_METHOD_WITH_VALUES 113 -#define LOAD_CONST__LOAD_FAST 121 -#define LOAD_FAST__LOAD_CONST 141 -#define LOAD_FAST__LOAD_FAST 143 -#define LOAD_GLOBAL_ADAPTIVE 153 -#define LOAD_GLOBAL_BUILTIN 154 -#define LOAD_GLOBAL_MODULE 158 -#define RESUME_QUICK 159 -#define STORE_ATTR_ADAPTIVE 160 -#define STORE_ATTR_INSTANCE_VALUE 161 -#define STORE_ATTR_SLOT 166 -#define STORE_ATTR_WITH_HINT 167 -#define STORE_FAST__LOAD_FAST 168 -#define STORE_FAST__STORE_FAST 169 -#define STORE_SUBSCR_ADAPTIVE 170 -#define STORE_SUBSCR_DICT 177 -#define STORE_SUBSCR_LIST_INT 178 -#define UNPACK_SEQUENCE_ADAPTIVE 179 -#define UNPACK_SEQUENCE_LIST 180 -#define UNPACK_SEQUENCE_TUPLE 181 -#define UNPACK_SEQUENCE_TWO_TUPLE 182 +#define CALL_NO_KW_TYPE_1 56 +#define COMPARE_OP_ADAPTIVE 57 +#define COMPARE_OP_FLOAT_JUMP 58 +#define COMPARE_OP_INT_JUMP 59 +#define COMPARE_OP_STR_JUMP 62 +#define EXTENDED_ARG_QUICK 63 +#define FOR_ITER_ADAPTIVE 64 +#define FOR_ITER_LIST 65 +#define FOR_ITER_RANGE 66 +#define JUMP_BACKWARD_QUICK 67 +#define LOAD_ATTR_ADAPTIVE 72 +#define LOAD_ATTR_CLASS 73 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 76 +#define LOAD_ATTR_INSTANCE_VALUE 77 +#define LOAD_ATTR_MODULE 78 +#define LOAD_ATTR_PROPERTY 79 +#define LOAD_ATTR_SLOT 80 +#define LOAD_ATTR_WITH_HINT 81 +#define LOAD_ATTR_METHOD_LAZY_DICT 86 +#define LOAD_ATTR_METHOD_NO_DICT 113 +#define LOAD_ATTR_METHOD_WITH_DICT 121 +#define LOAD_ATTR_METHOD_WITH_VALUES 141 +#define LOAD_CONST__LOAD_FAST 143 +#define LOAD_FAST__LOAD_CONST 153 +#define LOAD_FAST__LOAD_FAST 154 +#define LOAD_GLOBAL_ADAPTIVE 158 +#define LOAD_GLOBAL_BUILTIN 159 +#define LOAD_GLOBAL_MODULE 160 +#define RESUME_QUICK 161 +#define STORE_ATTR_ADAPTIVE 166 +#define STORE_ATTR_INSTANCE_VALUE 167 +#define STORE_ATTR_SLOT 168 +#define STORE_ATTR_WITH_HINT 169 +#define STORE_FAST__LOAD_FAST 170 +#define STORE_FAST__STORE_FAST 173 +#define STORE_SUBSCR_ADAPTIVE 174 +#define STORE_SUBSCR_DICT 175 +#define STORE_SUBSCR_LIST_INT 176 +#define UNPACK_SEQUENCE_ADAPTIVE 177 +#define UNPACK_SEQUENCE_LIST 178 +#define UNPACK_SEQUENCE_TUPLE 179 +#define UNPACK_SEQUENCE_TWO_TUPLE 180 #define DO_TRACING 255 #define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\ || ((op) == JUMP) \ || ((op) == JUMP_NO_INTERRUPT) \ - || ((op) == POP_JUMP_IF_FALSE) \ - || ((op) == POP_JUMP_IF_TRUE) \ - || ((op) == POP_JUMP_IF_NONE) \ - || ((op) == POP_JUMP_IF_NOT_NONE) \ || ((op) == LOAD_METHOD) \ ) diff --git a/Lib/argparse.py b/Lib/argparse.py index 02e98bbf920cf1d..d2dcfdf5682f7c1 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -2477,9 +2477,11 @@ def _get_values(self, action, arg_strings): not action.option_strings): if action.default is not None: value = action.default + self._check_value(action, value) else: + # since arg_strings is always [] at this point + # there is no need to use self._check_value(action, value) value = arg_strings - self._check_value(action, value) # single argument or optional argument produces a single value elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: @@ -2521,7 +2523,6 @@ def _get_value(self, action, arg_string): # ArgumentTypeErrors indicate errors except ArgumentTypeError as err: - name = getattr(action.type, '__name__', repr(action.type)) msg = str(err) raise ArgumentError(action, msg) diff --git a/Lib/ast.py b/Lib/ast.py index ebf4529f79b0609..8adb61fed453884 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -40,13 +40,13 @@ def parse(source, filename='', mode='exec', *, flags = PyCF_ONLY_AST if type_comments: flags |= PyCF_TYPE_COMMENTS - if isinstance(feature_version, tuple): + if feature_version is None: + feature_version = -1 + elif isinstance(feature_version, tuple): major, minor = feature_version # Should be a 2-tuple. if major != 3: raise ValueError(f"Unsupported major version: {major}") feature_version = minor - elif feature_version is None: - feature_version = -1 # Else it should be an int giving the minor version for 3.x. return compile(source, filename, mode, flags, _feature_version=feature_version) @@ -853,7 +853,7 @@ def visit_Import(self, node): def visit_ImportFrom(self, node): self.fill("from ") - self.write("." * node.level) + self.write("." * (node.level or 0)) if node.module: self.write(node.module) self.write(" import ") diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index fa00bf9a2ca0906..a675fff1688d27e 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -980,7 +980,8 @@ async def create_connection( local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, - happy_eyeballs_delay=None, interleave=None): + happy_eyeballs_delay=None, interleave=None, + all_errors=False): """Connect to a TCP server. Create a streaming transport connection to a given internet host and @@ -1069,6 +1070,8 @@ async def create_connection( if sock is None: exceptions = [exc for sub in exceptions for exc in sub] + if all_errors: + raise ExceptionGroup("create_connection failed", exceptions) if len(exceptions) == 1: raise exceptions[0] else: diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 9a169035de8865f..c4d837a1170819d 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -2,6 +2,7 @@ 'StreamReader', 'StreamWriter', 'StreamReaderProtocol', 'open_connection', 'start_server') +import collections import socket import sys import weakref @@ -128,7 +129,7 @@ def __init__(self, loop=None): else: self._loop = loop self._paused = False - self._drain_waiter = None + self._drain_waiters = collections.deque() self._connection_lost = False def pause_writing(self): @@ -143,38 +144,34 @@ def resume_writing(self): if self._loop.get_debug(): logger.debug("%r resumes writing", self) - waiter = self._drain_waiter - if waiter is not None: - self._drain_waiter = None + for waiter in self._drain_waiters: if not waiter.done(): waiter.set_result(None) def connection_lost(self, exc): self._connection_lost = True - # Wake up the writer if currently paused. + # Wake up the writer(s) if currently paused. if not self._paused: return - waiter = self._drain_waiter - if waiter is None: - return - self._drain_waiter = None - if waiter.done(): - return - if exc is None: - waiter.set_result(None) - else: - waiter.set_exception(exc) + + for waiter in self._drain_waiters: + if not waiter.done(): + if exc is None: + waiter.set_result(None) + else: + waiter.set_exception(exc) async def _drain_helper(self): if self._connection_lost: raise ConnectionResetError('Connection lost') if not self._paused: return - waiter = self._drain_waiter - assert waiter is None or waiter.cancelled() waiter = self._loop.create_future() - self._drain_waiter = waiter - await waiter + self._drain_waiters.append(waiter) + try: + await waiter + finally: + self._drain_waiters.remove(waiter) def _get_close_waiter(self, stream): raise NotImplementedError @@ -205,6 +202,7 @@ def __init__(self, stream_reader, client_connected_cb=None, loop=None): self._strong_reader = stream_reader self._reject_connection = False self._stream_writer = None + self._task = None self._transport = None self._client_connected_cb = client_connected_cb self._over_ssl = False @@ -247,7 +245,7 @@ def connection_made(self, transport): res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): - self._loop.create_task(res) + self._task = self._loop.create_task(res) self._strong_reader = None def connection_lost(self, exc): @@ -265,6 +263,7 @@ def connection_lost(self, exc): super().connection_lost(exc) self._stream_reader_wr = None self._stream_writer = None + self._task = None self._transport = None def data_received(self, data): diff --git a/Lib/bdb.py b/Lib/bdb.py index 75d6113576372e9..81fbb8514acb6f4 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -805,15 +805,18 @@ def checkfuncname(b, frame): return True -# Determines if there is an effective (active) breakpoint at this -# line of code. Returns breakpoint number or 0 if none def effective(file, line, frame): - """Determine which breakpoint for this file:line is to be acted upon. + """Return (active breakpoint, delete temporary flag) or (None, None) as + breakpoint to act upon. - Called only if we know there is a breakpoint at this location. Return - the breakpoint that was triggered and a boolean that indicates if it is - ok to delete a temporary breakpoint. Return (None, None) if there is no - matching breakpoint. + The "active breakpoint" is the first entry in bplist[line, file] (which + must exist) that is enabled, for which checkfuncname is True, and that + has neither a False condition nor a positive ignore count. The flag, + meaning that a temporary breakpoint should be deleted, is False only + when the condiion cannot be evaluated (in which case, ignore count is + ignored). + + If no such entry exists, then (None, None) is returned. """ possibles = Breakpoint.bplist[file, line] for b in possibles: diff --git a/Lib/csv.py b/Lib/csv.py index bfc850ee96dab6f..0de5656a4eed7ba 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -81,6 +81,8 @@ class unix_dialect(Dialect): class DictReader: def __init__(self, f, fieldnames=None, restkey=None, restval=None, dialect="excel", *args, **kwds): + if fieldnames is not None and iter(fieldnames) is fieldnames: + fieldnames = list(fieldnames) self._fieldnames = fieldnames # list of keys for the dict self.restkey = restkey # key to catch long rows self.restval = restval # default value for short rows @@ -133,6 +135,8 @@ def __next__(self): class DictWriter: def __init__(self, f, fieldnames, restval="", extrasaction="raise", dialect="excel", *args, **kwds): + if fieldnames is not None and iter(fieldnames) is fieldnames: + fieldnames = list(fieldnames) self.fieldnames = fieldnames # list of keys for the dict self.restval = restval # for writing short dicts if extrasaction.lower() not in ("raise", "ignore"): diff --git a/Lib/datetime.py b/Lib/datetime.py index 00ded32cc3e3cb0..007114ae6220313 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -179,7 +179,7 @@ def _format_time(hh, mm, ss, us, timespec='auto'): else: return fmt.format(hh, mm, ss, us) -def _format_offset(off): +def _format_offset(off, sep=':'): s = '' if off is not None: if off.days < 0: @@ -189,9 +189,9 @@ def _format_offset(off): sign = "+" hh, mm = divmod(off, timedelta(hours=1)) mm, ss = divmod(mm, timedelta(minutes=1)) - s += "%s%02d:%02d" % (sign, hh, mm) + s += "%s%02d%s%02d" % (sign, hh, sep, mm) if ss or ss.microseconds: - s += ":%02d" % ss.seconds + s += "%s%02d" % (sep, ss.seconds) if ss.microseconds: s += '.%06d' % ss.microseconds @@ -202,9 +202,10 @@ def _wrap_strftime(object, format, timetuple): # Don't call utcoffset() or tzname() unless actually needed. freplace = None # the string to use for %f zreplace = None # the string to use for %z + colonzreplace = None # the string to use for %:z Zreplace = None # the string to use for %Z - # Scan format for %z and %Z escapes, replacing as needed. + # Scan format for %z, %:z and %Z escapes, replacing as needed. newformat = [] push = newformat.append i, n = 0, len(format) @@ -222,26 +223,28 @@ def _wrap_strftime(object, format, timetuple): newformat.append(freplace) elif ch == 'z': if zreplace is None: - zreplace = "" if hasattr(object, "utcoffset"): - offset = object.utcoffset() - if offset is not None: - sign = '+' - if offset.days < 0: - offset = -offset - sign = '-' - h, rest = divmod(offset, timedelta(hours=1)) - m, rest = divmod(rest, timedelta(minutes=1)) - s = rest.seconds - u = offset.microseconds - if u: - zreplace = '%c%02d%02d%02d.%06d' % (sign, h, m, s, u) - elif s: - zreplace = '%c%02d%02d%02d' % (sign, h, m, s) - else: - zreplace = '%c%02d%02d' % (sign, h, m) + zreplace = _format_offset(object.utcoffset(), sep="") + else: + zreplace = "" assert '%' not in zreplace newformat.append(zreplace) + elif ch == ':': + if i < n: + ch2 = format[i] + i += 1 + if ch2 == 'z': + if colonzreplace is None: + if hasattr(object, "utcoffset"): + colonzreplace = _format_offset(object.utcoffset(), sep=":") + else: + colonzreplace = "" + assert '%' not in colonzreplace + newformat.append(colonzreplace) + else: + push('%') + push(ch) + push(ch2) elif ch == 'Z': if Zreplace is None: Zreplace = "" diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py index 01d5331a63069b1..a22a5d094d76786 100644 --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -323,7 +323,7 @@ def finalize_options(self): self.config_vars['userbase'] = self.install_userbase self.config_vars['usersite'] = self.install_usersite - if sysconfig.is_python_build(True): + if sysconfig.is_python_build(): self.config_vars['srcdir'] = sysconfig.get_config_var('srcdir') self.expand_basedirs() diff --git a/Lib/enum.py b/Lib/enum.py index 8ef69589a14699d..e7375e1eae691f9 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1887,7 +1887,7 @@ def _test_simple_enum(checked_enum, simple_enum): else: checked_value = checked_dict[key] simple_value = simple_dict[key] - if callable(checked_value): + if callable(checked_value) or isinstance(checked_value, bltns.property): continue if key == '__doc__': # remove all spaces/tabs diff --git a/Lib/fractions.py b/Lib/fractions.py index 738a0d4c301d43e..75c7df14e1b9c77 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -4,6 +4,7 @@ """Fraction, infinite-precision, rational numbers.""" from decimal import Decimal +import functools import math import numbers import operator @@ -20,13 +21,46 @@ # _PyHASH_MODULUS. _PyHASH_INF = sys.hash_info.inf +@functools.lru_cache(maxsize = 1 << 14) +def _hash_algorithm(numerator, denominator): + + # To make sure that the hash of a Fraction agrees with the hash + # of a numerically equal integer, float or Decimal instance, we + # follow the rules for numeric hashes outlined in the + # documentation. (See library docs, 'Built-in Types'). + + try: + dinv = pow(denominator, -1, _PyHASH_MODULUS) + except ValueError: + # ValueError means there is no modular inverse. + hash_ = _PyHASH_INF + else: + # The general algorithm now specifies that the absolute value of + # the hash is + # (|N| * dinv) % P + # where N is self._numerator and P is _PyHASH_MODULUS. That's + # optimized here in two ways: first, for a non-negative int i, + # hash(i) == i % P, but the int hash implementation doesn't need + # to divide, and is faster than doing % P explicitly. So we do + # hash(|N| * dinv) + # instead. Second, N is unbounded, so its product with dinv may + # be arbitrarily expensive to compute. The final answer is the + # same if we use the bounded |N| % P instead, which can again + # be done with an int hash() call. If 0 <= i < P, hash(i) == i, + # so this nested hash() call wastes a bit of time making a + # redundant copy when |N| < P, but can save an arbitrarily large + # amount of computation for large |N|. + hash_ = hash(hash(abs(numerator)) * dinv) + result = hash_ if numerator >= 0 else -hash_ + return -2 if result == -1 else result + _RATIONAL_FORMAT = re.compile(r""" \A\s* # optional whitespace at the start, (?P[-+]?) # an optional sign, then (?=\d|\.\d) # lookahead for digit or .digit (?P\d*|\d+(_\d+)*) # numerator (possibly empty) (?: # followed by - (?:/(?P\d+(_\d+)*))? # an optional denominator + (?:\s*/\s*(?P\d+(_\d+)*))? # an optional denominator | # or (?:\.(?Pd*|\d+(_\d+)*))? # an optional fractional part (?:E(?P[-+]?\d+(_\d+)*))? # and optional exponent @@ -646,36 +680,7 @@ def __round__(self, ndigits=None): def __hash__(self): """hash(self)""" - - # To make sure that the hash of a Fraction agrees with the hash - # of a numerically equal integer, float or Decimal instance, we - # follow the rules for numeric hashes outlined in the - # documentation. (See library docs, 'Built-in Types'). - - try: - dinv = pow(self._denominator, -1, _PyHASH_MODULUS) - except ValueError: - # ValueError means there is no modular inverse. - hash_ = _PyHASH_INF - else: - # The general algorithm now specifies that the absolute value of - # the hash is - # (|N| * dinv) % P - # where N is self._numerator and P is _PyHASH_MODULUS. That's - # optimized here in two ways: first, for a non-negative int i, - # hash(i) == i % P, but the int hash implementation doesn't need - # to divide, and is faster than doing % P explicitly. So we do - # hash(|N| * dinv) - # instead. Second, N is unbounded, so its product with dinv may - # be arbitrarily expensive to compute. The final answer is the - # same if we use the bounded |N| % P instead, which can again - # be done with an int hash() call. If 0 <= i < P, hash(i) == i, - # so this nested hash() call wastes a bit of time making a - # redundant copy when |N| < P, but can save an arbitrarily large - # amount of computation for large |N|. - hash_ = hash(hash(abs(self._numerator)) * dinv) - result = hash_ if self._numerator >= 0 else -hash_ - return -2 if result == -1 else result + return _hash_algorithm(self._numerator, self._denominator) def __eq__(a, b): """a == b""" diff --git a/Lib/html/parser.py b/Lib/html/parser.py index bef0f4fe4bf776c..13c95c34e505c89 100644 --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -89,6 +89,7 @@ def __init__(self, *, convert_charrefs=True): If convert_charrefs is True (the default), all character references are automatically converted to the corresponding Unicode characters. """ + super().__init__() self.convert_charrefs = convert_charrefs self.reset() @@ -98,7 +99,7 @@ def reset(self): self.lasttag = '???' self.interesting = interesting_normal self.cdata_elem = None - _markupbase.ParserBase.reset(self) + super().reset() def feed(self, data): r"""Feed data to the parser. diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index cd2885dc7757b45..e093a1fec4dffca 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -31,6 +31,26 @@ def __new__(cls, value, phrase, description=''): obj.description = description return obj + @property + def is_informational(self): + return 100 <= self <= 199 + + @property + def is_success(self): + return 200 <= self <= 299 + + @property + def is_redirection(self): + return 300 <= self <= 399 + + @property + def is_client_error(self): + return 400 <= self <= 499 + + @property + def is_server_error(self): + return 500 <= self <= 599 + # informational CONTINUE = 100, 'Continue', 'Request received, please continue' SWITCHING_PROTOCOLS = (101, 'Switching Protocols', diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index af5cbd5a5ba4c3e..722406b81a8ae6c 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -113,9 +113,9 @@

Table of Contents

  • Setting preferences
  • IDLE on macOS
  • Extensions
  • -
  • idlelib
  • +
  • idlelib
  • @@ -1002,18 +1002,19 @@

    Extensions -

    idlelib¶

    +

    idlelib¶

    Source code: Lib/idlelib

    -

    The Lib/idlelib package implements the IDLE application. See the top -of this file or content listing on the left for how to use IDLE.

    +
    +

    The Lib/idlelib package implements the IDLE application. See the rest +of this page for how to use IDLE.

    The files in idlelib are described in idlelib/README.txt. Access it either in idlelib or click Help => About IDLE on the IDLE menu. This file also maps IDLE menu items to the code that implements the item. Except for files listed under ‘Startup’, the idlelib code is ‘private’ in sense that feature changes can be backported (see PEP 434).

    - @@ -1066,9 +1067,9 @@

    Table of Contents

  • Setting preferences
  • IDLE on macOS
  • Extensions
  • -
  • idlelib
  • +
  • idlelib
  • @@ -1166,7 +1167,7 @@

    Navigation



    - Last updated on Aug 07, 2022. + Last updated on Sep 03, 2022. Found a bug?
    diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py index 290e037fe727a1a..049531e66a414e0 100644 --- a/Lib/idlelib/idle_test/test_sidebar.py +++ b/Lib/idlelib/idle_test/test_sidebar.py @@ -6,6 +6,7 @@ import unittest import unittest.mock from test.support import requires, swap_attr +from test import support import tkinter as tk from idlelib.idle_test.tkinter_testing_utils import run_in_tk_mainloop @@ -612,7 +613,8 @@ def test_interrupt_recall_undo_redo(self): @run_in_tk_mainloop() def test_very_long_wrapped_line(self): - with swap_attr(self.shell, 'squeezer', None): + with support.adjust_int_max_str_digits(11_111), \ + swap_attr(self.shell, 'squeezer', None): self.do_input('x = ' + '1'*10_000 + '\n') yield self.assertEqual(self.get_sidebar_lines(), ['>>>']) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 82d204257ed7a3b..b3c31b9659d849a 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -411,10 +411,11 @@ def _write_atomic(path, data, mode=0o666): # Python 3.12a1 3505 (Specialization/Cache for FOR_ITER) # Python 3.12a1 3506 (Add BINARY_SLICE and STORE_SLICE instructions) # Python 3.12a1 3507 (Set lineno of module's RESUME to 0) +# Python 3.12a1 3508 (Add CLEANUP_THROW) +# Python 3.12a1 3509 (Conditional jumps only jump forward) # Python 3.13 will start with 3550 -# # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). @@ -424,7 +425,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3507).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3509).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/inspect.py b/Lib/inspect.py index cbc0632484b8326..498ee7ab9eaf8a2 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -946,6 +946,9 @@ def getsourcefile(object): elif any(filename.endswith(s) for s in importlib.machinery.EXTENSION_SUFFIXES): return None + # return a filename found in the linecache even if it doesn't exist on disk + if filename in linecache.cache: + return filename if os.path.exists(filename): return filename # only return a non-existent filename if the module has a PEP 302 loader @@ -954,9 +957,6 @@ def getsourcefile(object): return filename elif getattr(getattr(module, "__spec__", None), "loader", None) is not None: return filename - # or it is in the linecache - elif filename in linecache.cache: - return filename def getabsfile(object, _filename=None): """Return an absolute path to the source or compiled file for an object. diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index e4c21daaf3e47f5..d775fb1c11071d2 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -97,7 +97,7 @@ """ __version__ = '2.0.9' __all__ = [ - 'dump', 'dumps', 'load', 'loads', + 'dump', 'dumps', 'load', 'loads', 'AttrDict', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', ] @@ -357,3 +357,53 @@ def loads(s, *, cls=None, object_hook=None, parse_float=None, if parse_constant is not None: kw['parse_constant'] = parse_constant return cls(**kw).decode(s) + +class AttrDict(dict): + """Dict like object that supports attribute style dotted access. + + This class is intended for use with the *object_hook* in json.loads(): + + >>> from json import loads, AttrDict + >>> json_string = '{"mercury": 88, "venus": 225, "earth": 365, "mars": 687}' + >>> orbital_period = loads(json_string, object_hook=AttrDict) + >>> orbital_period['earth'] # Dict style lookup + 365 + >>> orbital_period.earth # Attribute style lookup + 365 + >>> orbital_period.keys() # All dict methods are present + dict_keys(['mercury', 'venus', 'earth', 'mars']) + + Attribute style access only works for keys that are valid attribute names. + In contrast, dictionary style access works for all keys. + For example, ``d.two words`` contains a space and is not syntactically + valid Python, so ``d["two words"]`` should be used instead. + + If a key has the same name as dictionary method, then a dictionary + lookup finds the key and an attribute lookup finds the method: + + >>> d = AttrDict(items=50) + >>> d['items'] # Lookup the key + 50 + >>> d.items() # Call the method + dict_items([('items', 50)]) + + """ + __slots__ = () + + def __getattr__(self, attr): + try: + return self[attr] + except KeyError: + raise AttributeError(attr) from None + + def __setattr__(self, attr, value): + self[attr] = value + + def __delattr__(self, attr): + try: + del self[attr] + except KeyError: + raise AttributeError(attr) from None + + def __dir__(self): + return list(self) + dir(type(self)) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index afb5234a077295c..86e1efe6e653acc 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -340,7 +340,7 @@ def __init__(self, name, level, pathname, lineno, self.lineno = lineno self.funcName = func self.created = ct - self.msecs = (ct - int(ct)) * 1000 + self.msecs = int((ct - int(ct)) * 1000) + 0.0 # see gh-89047 self.relativeCreated = (self.created - _startTime) * 1000 if logThreads: self.thread = threading.get_ident() @@ -1828,6 +1828,25 @@ def getChild(self, suffix): suffix = '.'.join((self.name, suffix)) return self.manager.getLogger(suffix) + def getChildren(self): + + def _hierlevel(logger): + if logger is logger.manager.root: + return 0 + return 1 + logger.name.count('.') + + d = self.manager.loggerDict + _acquireLock() + try: + # exclude PlaceHolders - the last check is to ensure that lower-level + # descendants aren't returned - if there are placeholders, a logger's + # parent field might point to a grandparent or ancestor thereof. + return set(item for item in d.values() + if isinstance(item, Logger) and item.parent is self and + _hierlevel(item) == 1 + _hierlevel(item.parent)) + finally: + _releaseLock() + def __repr__(self): level = getLevelName(self.getEffectiveLevel()) return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level) diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 2b9d90c3ed5b79e..7cd16c643e9dadf 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -869,6 +869,7 @@ def configure_logger(self, name, config, incremental=False): """Configure a non-root logger from a dictionary.""" logger = logging.getLogger(name) self.common_logger_config(logger, config, incremental) + logger.disabled = False propagate = config.get('propagate', None) if propagate is not None: logger.propagate = propagate diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 1c8226c18163222..b4c5c1304b97529 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -348,11 +348,15 @@ 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: + # See #89564: Never rollover anything other than regular files + if os.path.exists(self.baseFilename) and not os.path.isfile(self.baseFilename): + # The file is not a regular file, so do not rollover, but do + # set the next rollover time to avoid repeated checks. + self.rolloverAt = self.computeRollover(t) + return False + return True return False @@ -1107,7 +1111,16 @@ def __init__(self, appname, dllname=None, logtype="Application"): dllname = os.path.join(dllname[0], r'win32service.pyd') self.dllname = dllname self.logtype = logtype - self._welu.AddSourceToRegistry(appname, dllname, logtype) + # Administrative privileges are required to add a source to the registry. + # This may not be available for a user that just wants to add to an + # existing source - handle this specific case. + try: + self._welu.AddSourceToRegistry(appname, dllname, logtype) + except Exception as e: + # This will probably be a pywintypes.error. Only raise if it's not + # an "access denied" error, else let it pass + if getattr(e, 'winerror', None) != 5: # not access denied + raise self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE self.typemap = { logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE, diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 959bcd098311867..d9582f4087433e4 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -732,9 +732,8 @@ def realpath(path, *, strict=False): return path -# Win9x family and earlier have no Unicode filename support. -supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and - sys.getwindowsversion()[3] >= 2) +# All supported version have Unicode filename support. +supports_unicode_filenames = True def relpath(path, start=None): """Return a relative version of a path""" diff --git a/Lib/numbers.py b/Lib/numbers.py index 8e37d79fa755ad3..a2913e32cfada76 100644 --- a/Lib/numbers.py +++ b/Lib/numbers.py @@ -313,7 +313,7 @@ def __float__(self): so that ratios of huge integers convert without overflowing. """ - return self.numerator / self.denominator + return int(self.numerator) / int(self.denominator) class Integral(Rational): diff --git a/Lib/opcode.py b/Lib/opcode.py index 8a07fb75b2e97c1..690923061418bdf 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -104,6 +104,7 @@ def pseudo_op(name, op, real_ops): def_op('BEFORE_ASYNC_WITH', 52) def_op('BEFORE_WITH', 53) def_op('END_ASYNC_FOR', 54) +def_op('CLEANUP_THROW', 55) def_op('STORE_SUBSCR', 60) def_op('DELETE_SUBSCR', 61) @@ -152,8 +153,8 @@ def pseudo_op(name, op, real_ops): jrel_op('JUMP_FORWARD', 110) # Number of words to skip jrel_op('JUMP_IF_FALSE_OR_POP', 111) # Number of words to skip jrel_op('JUMP_IF_TRUE_OR_POP', 112) # "" -jrel_op('POP_JUMP_FORWARD_IF_FALSE', 114) -jrel_op('POP_JUMP_FORWARD_IF_TRUE', 115) +jrel_op('POP_JUMP_IF_FALSE', 114) +jrel_op('POP_JUMP_IF_TRUE', 115) name_op('LOAD_GLOBAL', 116) # Index in name list def_op('IS_OP', 117) def_op('CONTAINS_OP', 118) @@ -169,8 +170,8 @@ def pseudo_op(name, op, real_ops): haslocal.append(126) def_op('LOAD_FAST_CHECK', 127) # Local variable number haslocal.append(127) -jrel_op('POP_JUMP_FORWARD_IF_NOT_NONE', 128) -jrel_op('POP_JUMP_FORWARD_IF_NONE', 129) +jrel_op('POP_JUMP_IF_NOT_NONE', 128) +jrel_op('POP_JUMP_IF_NONE', 129) def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3) def_op('GET_AWAITABLE', 131) def_op('MAKE_FUNCTION', 132) # Flags @@ -215,10 +216,6 @@ def pseudo_op(name, op, real_ops): def_op('KW_NAMES', 172) hasconst.append(172) -jrel_op('POP_JUMP_BACKWARD_IF_NOT_NONE', 173) -jrel_op('POP_JUMP_BACKWARD_IF_NONE', 174) -jrel_op('POP_JUMP_BACKWARD_IF_FALSE', 175) -jrel_op('POP_JUMP_BACKWARD_IF_TRUE', 176) hasarg.extend([op for op in opmap.values() if op >= HAVE_ARGUMENT]) @@ -234,11 +231,8 @@ def pseudo_op(name, op, real_ops): pseudo_op('JUMP', 260, ['JUMP_FORWARD', 'JUMP_BACKWARD']) pseudo_op('JUMP_NO_INTERRUPT', 261, ['JUMP_FORWARD', 'JUMP_BACKWARD_NO_INTERRUPT']) -pseudo_op('POP_JUMP_IF_FALSE', 262, ['POP_JUMP_FORWARD_IF_FALSE', 'POP_JUMP_BACKWARD_IF_FALSE']) -pseudo_op('POP_JUMP_IF_TRUE', 263, ['POP_JUMP_FORWARD_IF_TRUE', 'POP_JUMP_BACKWARD_IF_TRUE']) -pseudo_op('POP_JUMP_IF_NONE', 264, ['POP_JUMP_FORWARD_IF_NONE', 'POP_JUMP_BACKWARD_IF_NONE']) -pseudo_op('POP_JUMP_IF_NOT_NONE', 265, ['POP_JUMP_FORWARD_IF_NOT_NONE', 'POP_JUMP_BACKWARD_IF_NOT_NONE']) -pseudo_op('LOAD_METHOD', 266, ['LOAD_ATTR']) + +pseudo_op('LOAD_METHOD', 262, ['LOAD_ATTR']) MAX_PSEUDO_OPCODE = MIN_PSEUDO_OPCODE + len(_pseudo_ops) - 1 @@ -338,6 +332,7 @@ def pseudo_op(name, op, real_ops): "LOAD_ATTR_ADAPTIVE", # These potentially push [NULL, bound method] onto the stack. "LOAD_ATTR_CLASS", + "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN", "LOAD_ATTR_INSTANCE_VALUE", "LOAD_ATTR_MODULE", "LOAD_ATTR_PROPERTY", diff --git a/Lib/pdb.py b/Lib/pdb.py index e6ed814acbe19a7..b0acb1f571d3f64 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -131,7 +131,7 @@ def __repr__(self): return self -class ScriptTarget(str): +class _ScriptTarget(str): def __new__(cls, val): # Mutate self to be the "real path". res = super().__new__(cls, os.path.realpath(val)) @@ -167,7 +167,7 @@ def code(self): return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))" -class ModuleTarget(str): +class _ModuleTarget(str): def check(self): try: self._details @@ -1625,7 +1625,7 @@ def lookupmodule(self, filename): return fullname return None - def _run(self, target: Union[ModuleTarget, ScriptTarget]): + def _run(self, target: Union[_ModuleTarget, _ScriptTarget]): # When bdb sets tracing, a number of call and line events happen # BEFORE debugger even reaches user's code (and the exact sequence of # events depends on python version). Take special measures to @@ -1789,7 +1789,7 @@ def main(): commands = [optarg for opt, optarg in opts if opt in ['-c', '--command']] module_indicated = any(opt in ['-m'] for opt, optarg in opts) - cls = ModuleTarget if module_indicated else ScriptTarget + cls = _ModuleTarget if module_indicated else _ScriptTarget target = cls(args[0]) target.check() diff --git a/Lib/platform.py b/Lib/platform.py index df8faac88ca88a1..9f5b317287530bd 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -309,34 +309,52 @@ def _syscmd_ver(system='', release='', version='', version = _norm_version(version) return system, release, version -_WIN32_CLIENT_RELEASES = { - (5, 0): "2000", - (5, 1): "XP", - # Strictly, 5.2 client is XP 64-bit, but platform.py historically - # has always called it 2003 Server - (5, 2): "2003Server", - (5, None): "post2003", - - (6, 0): "Vista", - (6, 1): "7", - (6, 2): "8", - (6, 3): "8.1", - (6, None): "post8.1", - - (10, 0): "10", - (10, None): "post10", -} - -# Server release name lookup will default to client names if necessary -_WIN32_SERVER_RELEASES = { - (5, 2): "2003Server", - - (6, 0): "2008Server", - (6, 1): "2008ServerR2", - (6, 2): "2012Server", - (6, 3): "2012ServerR2", - (6, None): "post2012ServerR2", -} +try: + import _wmi +except ImportError: + def _wmi_query(*keys): + raise OSError("not supported") +else: + def _wmi_query(table, *keys): + table = { + "OS": "Win32_OperatingSystem", + "CPU": "Win32_Processor", + }[table] + data = _wmi.exec_query("SELECT {} FROM {}".format( + ",".join(keys), + table, + )).split("\0") + split_data = (i.partition("=") for i in data) + dict_data = {i[0]: i[2] for i in split_data} + return (dict_data[k] for k in keys) + + +_WIN32_CLIENT_RELEASES = [ + ((10, 1, 0), "post11"), + ((10, 0, 22000), "11"), + ((6, 4, 0), "10"), + ((6, 3, 0), "8.1"), + ((6, 2, 0), "8"), + ((6, 1, 0), "7"), + ((6, 0, 0), "Vista"), + ((5, 2, 3790), "XP64"), + ((5, 2, 0), "XPMedia"), + ((5, 1, 0), "XP"), + ((5, 0, 0), "2000"), +] + +_WIN32_SERVER_RELEASES = [ + ((10, 1, 0), "post2022Server"), + ((10, 0, 20348), "2022Server"), + ((10, 0, 17763), "2019Server"), + ((6, 4, 0), "2016Server"), + ((6, 3, 0), "2012ServerR2"), + ((6, 2, 0), "2012Server"), + ((6, 1, 0), "2008ServerR2"), + ((6, 0, 0), "2008Server"), + ((5, 2, 0), "2003Server"), + ((5, 0, 0), "2000Server"), +] def win32_is_iot(): return win32_edition() in ('IoTUAP', 'NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS') @@ -359,22 +377,40 @@ def win32_edition(): return None -def win32_ver(release='', version='', csd='', ptype=''): +def _win32_ver(version, csd, ptype): + # Try using WMI first, as this is the canonical source of data + try: + (version, product_type, ptype, spmajor, spminor) = _wmi_query( + 'OS', + 'Version', + 'ProductType', + 'BuildType', + 'ServicePackMajorVersion', + 'ServicePackMinorVersion', + ) + is_client = (int(product_type) == 1) + if spminor and spminor != '0': + csd = f'SP{spmajor}.{spminor}' + else: + csd = f'SP{spmajor}' + return version, csd, ptype, is_client + except OSError: + pass + + # Fall back to a combination of sys.getwindowsversion and "ver" try: from sys import getwindowsversion except ImportError: - return release, version, csd, ptype + return version, csd, ptype, True winver = getwindowsversion() + is_client = (getattr(winver, 'product_type', 1) == 1) try: - major, minor, build = map(int, _syscmd_ver()[2].split('.')) + version = _syscmd_ver()[2] + major, minor, build = map(int, version.split('.')) except ValueError: major, minor, build = winver.platform_version or winver[:3] - version = '{0}.{1}.{2}'.format(major, minor, build) - - release = (_WIN32_CLIENT_RELEASES.get((major, minor)) or - _WIN32_CLIENT_RELEASES.get((major, None)) or - release) + version = '{0}.{1}.{2}'.format(major, minor, build) # getwindowsversion() reflect the compatibility mode Python is # running under, and so the service pack value is only going to be @@ -386,12 +422,6 @@ def win32_ver(release='', version='', csd='', ptype=''): if csd[:13] == 'Service Pack ': csd = 'SP' + csd[13:] - # VER_NT_SERVER = 3 - if getattr(winver, 'product_type', None) == 3: - release = (_WIN32_SERVER_RELEASES.get((major, minor)) or - _WIN32_SERVER_RELEASES.get((major, None)) or - release) - try: try: import winreg @@ -407,6 +437,18 @@ def win32_ver(release='', version='', csd='', ptype=''): except OSError: pass + return version, csd, ptype, is_client + +def win32_ver(release='', version='', csd='', ptype=''): + is_client = False + + version, csd, ptype, is_client = _win32_ver(version, csd, ptype) + + if version: + intversion = tuple(map(int, version.split('.'))) + releases = _WIN32_CLIENT_RELEASES if is_client else _WIN32_SERVER_RELEASES + release = next((r for v, r in releases if v <= intversion), release) + return release, version, csd, ptype @@ -725,6 +767,21 @@ def _get_machine_win32(): # http://www.geocities.com/rick_lively/MANUALS/ENV/MSWIN/PROCESSI.HTM # WOW64 processes mask the native architecture + try: + [arch, *_] = _wmi_query('CPU', 'Architecture') + except OSError: + pass + else: + try: + arch = ['x86', 'MIPS', 'Alpha', 'PowerPC', None, + 'ARM', 'ia64', None, None, + 'AMD64', None, None, 'ARM64', + ][int(arch)] + except (ValueError, IndexError): + pass + else: + if arch: + return arch return ( os.environ.get('PROCESSOR_ARCHITEW6432', '') or os.environ.get('PROCESSOR_ARCHITECTURE', '') @@ -738,7 +795,12 @@ def get(cls): return func() or '' def get_win32(): - return os.environ.get('PROCESSOR_IDENTIFIER', _get_machine_win32()) + try: + manufacturer, caption = _wmi_query('CPU', 'Manufacturer', 'Caption') + except OSError: + return os.environ.get('PROCESSOR_IDENTIFIER', _get_machine_win32()) + else: + return f'{caption}, {manufacturer}' def get_OpenVMS(): try: diff --git a/Lib/socket.py b/Lib/socket.py index 0ed86afb4a9ea5f..1c8cef6ce658102 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -255,17 +255,18 @@ def __repr__(self): self.type, self.proto) if not closed: + # getsockname and getpeername may not be available on WASI. try: laddr = self.getsockname() if laddr: s += ", laddr=%s" % str(laddr) - except error: + except (error, AttributeError): pass try: raddr = self.getpeername() if raddr: s += ", raddr=%s" % str(raddr) - except error: + except (error, AttributeError): pass s += '>' return s diff --git a/Lib/statistics.py b/Lib/statistics.py index c78d64518853e77..b4adabd3f05ae81 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -134,11 +134,11 @@ from fractions import Fraction from decimal import Decimal -from itertools import groupby, repeat +from itertools import count, groupby, repeat from bisect import bisect_left, bisect_right from math import hypot, sqrt, fabs, exp, erf, tau, log, fsum from functools import reduce -from operator import mul +from operator import mul, itemgetter from collections import Counter, namedtuple, defaultdict _SQRT2 = sqrt(2.0) @@ -356,6 +356,60 @@ def _fail_neg(values, errmsg='negative value'): yield x +def _rank(data, /, *, key=None, reverse=False, ties='average', start=1) -> list[float]: + """Rank order a dataset. The lowest value has rank 1. + + Ties are averaged so that equal values receive the same rank: + + >>> data = [31, 56, 31, 25, 75, 18] + >>> _rank(data) + [3.5, 5.0, 3.5, 2.0, 6.0, 1.0] + + The operation is idempotent: + + >>> _rank([3.5, 5.0, 3.5, 2.0, 6.0, 1.0]) + [3.5, 5.0, 3.5, 2.0, 6.0, 1.0] + + It is possible to rank the data in reverse order so that the + highest value has rank 1. Also, a key-function can extract + the field to be ranked: + + >>> goals = [('eagles', 45), ('bears', 48), ('lions', 44)] + >>> _rank(goals, key=itemgetter(1), reverse=True) + [2.0, 1.0, 3.0] + + Ranks are conventionally numbered starting from one; however, + setting *start* to zero allows the ranks to be used as array indices: + + >>> prize = ['Gold', 'Silver', 'Bronze', 'Certificate'] + >>> scores = [8.1, 7.3, 9.4, 8.3] + >>> [prize[int(i)] for i in _rank(scores, start=0, reverse=True)] + ['Bronze', 'Certificate', 'Gold', 'Silver'] + + """ + # If this function becomes public at some point, more thought + # needs to be given to the signature. A list of ints is + # plausible when ties is "min" or "max". When ties is "average", + # either list[float] or list[Fraction] is plausible. + + # Default handling of ties matches scipy.stats.mstats.spearmanr. + if ties != 'average': + raise ValueError(f'Unknown tie resolution method: {ties!r}') + if key is not None: + data = map(key, data) + val_pos = sorted(zip(data, count()), reverse=reverse) + i = start - 1 + result = [0] * len(val_pos) + for _, g in groupby(val_pos, key=itemgetter(0)): + group = list(g) + size = len(group) + rank = i + (size + 1) / 2 + for value, orig_pos in group: + result[orig_pos] = rank + i += size + return result + + def _integer_sqrt_of_frac_rto(n: int, m: int) -> int: """Square root of n/m, rounded to the nearest integer using round-to-odd.""" # Reference: https://www.lri.fr/~melquion/doc/05-imacs17_1-expose.pdf @@ -988,14 +1042,12 @@ def covariance(x, y, /): return sxy / (n - 1) -def correlation(x, y, /): +def correlation(x, y, /, *, method='linear'): """Pearson's correlation coefficient Return the Pearson's correlation coefficient for two inputs. Pearson's - correlation coefficient *r* takes values between -1 and +1. It measures the - strength and direction of the linear relationship, where +1 means very - strong, positive linear relationship, -1 very strong, negative linear - relationship, and 0 no linear relationship. + correlation coefficient *r* takes values between -1 and +1. It measures + the strength and direction of a linear relationship. >>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> y = [9, 8, 7, 6, 5, 4, 3, 2, 1] @@ -1004,12 +1056,26 @@ def correlation(x, y, /): >>> correlation(x, y) -1.0 + If *method* is "ranked", computes Spearman's rank correlation coefficient + for two inputs. The data is replaced by ranks. Ties are averaged + so that equal values receive the same rank. The resulting coefficient + measures the strength of a monotonic relationship. + + Spearman's rank correlation coefficient is appropriate for ordinal + data or for continuous data that doesn't meet the linear proportion + requirement for Pearson's correlation coefficient. """ n = len(x) if len(y) != n: 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') + if method not in {'linear', 'ranked'}: + raise ValueError(f'Unknown method: {method!r}') + if method == 'ranked': + start = (n - 1) / -2 # Center rankings around zero + x = _rank(x, start=start) + y = _rank(y, start=start) xbar = fsum(x) / n ybar = fsum(y) / n sxy = fsum((xi - xbar) * (yi - ybar) for xi, yi in zip(x, y)) diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index 4efe1497445422d..beeb1bfdeb2875d 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -419,6 +419,17 @@ def hook(event, args): sys._getframe() +def test_wmi_exec_query(): + import _wmi + + def hook(event, args): + if event.startswith("_wmi."): + print(event, args[0]) + + sys.addaudithook(hook) + _wmi.exec_query("SELECT * FROM Win32_OperatingSystem") + + def test_syslog(): import syslog diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 7e7f4f33d6e57c2..bba96698e9e2ebe 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1463,8 +1463,8 @@ def test_strftime(self): # test that unicode input is allowed (issue 2782) self.assertEqual(t.strftime("%m"), "03") - # A naive object replaces %z and %Z w/ empty strings. - self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") + # A naive object replaces %z, %:z and %Z w/ empty strings. + self.assertEqual(t.strftime("'%z' '%:z' '%Z'"), "'' '' ''") #make sure that invalid format specifiers are handled correctly #self.assertRaises(ValueError, t.strftime, "%e") @@ -1528,7 +1528,7 @@ def strftime(self, format_spec): for fmt in ["m:%m d:%d y:%y", "m:%m d:%d y:%y H:%H M:%M S:%S", - "%z %Z", + "%z %:z %Z", ]: self.assertEqual(dt.__format__(fmt), dt.strftime(fmt)) self.assertEqual(a.__format__(fmt), dt.strftime(fmt)) @@ -2134,7 +2134,7 @@ def strftime(self, format_spec): for fmt in ["m:%m d:%d y:%y", "m:%m d:%d y:%y H:%H M:%M S:%S", - "%z %Z", + "%z %:z %Z", ]: self.assertEqual(dt.__format__(fmt), dt.strftime(fmt)) self.assertEqual(a.__format__(fmt), dt.strftime(fmt)) @@ -2777,6 +2777,7 @@ def test_more_strftime(self): tz = timezone(-timedelta(hours=2, seconds=s, microseconds=us)) t = t.replace(tzinfo=tz) self.assertEqual(t.strftime("%z"), "-0200" + z) + self.assertEqual(t.strftime("%:z"), "-02:00:" + z) # bpo-34482: Check that surrogates don't cause a crash. try: @@ -3515,8 +3516,8 @@ def test_1653736(self): def test_strftime(self): t = self.theclass(1, 2, 3, 4) self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004") - # A naive object replaces %z and %Z with empty strings. - self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") + # A naive object replaces %z, %:z and %Z with empty strings. + self.assertEqual(t.strftime("'%z' '%:z' '%Z'"), "'' '' ''") # bpo-34482: Check that surrogates don't cause a crash. try: @@ -3934,10 +3935,10 @@ def test_zones(self): self.assertEqual(repr(t4), d + "(0, 0, 0, 40)") self.assertEqual(repr(t5), d + "(0, 0, 0, 40, tzinfo=utc)") - self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z"), - "07:47:00 %Z=EST %z=-0500") - self.assertEqual(t2.strftime("%H:%M:%S %Z %z"), "12:47:00 UTC +0000") - self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100") + self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z %%:z=%:z"), + "07:47:00 %Z=EST %z=-0500 %:z=-05:00") + self.assertEqual(t2.strftime("%H:%M:%S %Z %z %:z"), "12:47:00 UTC +0000 +00:00") + self.assertEqual(t3.strftime("%H:%M:%S %Z %z %:z"), "13:47:00 MET +0100 +01:00") yuck = FixedOffset(-1439, "%z %Z %%z%%Z") t1 = time(23, 59, tzinfo=yuck) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index c51a1f26f29a6b2..573dce52ca474a0 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -46,6 +46,7 @@ "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "skip_if_buggy_ucrt_strfptime", "check_disallow_instantiation", "check_sanitizer", "skip_if_sanitizer", + "requires_limited_api", # sys "is_jython", "is_android", "is_emscripten", "is_wasi", "check_impl_detail", "unix_shell", "setswitchinterval", @@ -1069,6 +1070,15 @@ def refcount_test(test): return no_tracing(cpython_only(test)) +def requires_limited_api(test): + try: + import _testcapi + except ImportError: + return unittest.skip('needs _testcapi module')(test) + return unittest.skipUnless( + _testcapi.LIMITED_API_AVAILABLE, 'needs Limited API support')(test) + + def _filter_suite(suite, pred): """Recursively filter test cases in a suite based on a predicate.""" newtests = [] @@ -2331,3 +2341,14 @@ def sleeping_retry(timeout, err_msg=None, /, time.sleep(delay) delay = min(delay * 2, max_delay) + + +@contextlib.contextmanager +def adjust_int_max_str_digits(max_digits): + """Temporarily change the integer string conversion length limit.""" + current = sys.get_int_max_str_digits() + try: + sys.set_int_max_str_digits(max_digits) + yield + finally: + sys.set_int_max_str_digits(current) diff --git a/Lib/test/support/bytecode_helper.py b/Lib/test/support/bytecode_helper.py index 471d4a68f915aab..05b54911e3f25a9 100644 --- a/Lib/test/support/bytecode_helper.py +++ b/Lib/test/support/bytecode_helper.py @@ -3,6 +3,7 @@ import unittest import dis import io +from _testinternalcapi import optimize_cfg _UNSPECIFIED = object() @@ -40,3 +41,95 @@ def assertNotInBytecode(self, x, opname, argval=_UNSPECIFIED): msg = '(%s,%r) occurs in bytecode:\n%s' msg = msg % (opname, argval, disassembly) self.fail(msg) + + +class CfgOptimizationTestCase(unittest.TestCase): + + HAS_ARG = set(dis.hasarg) + HAS_TARGET = set(dis.hasjrel + dis.hasjabs + dis.hasexc) + HAS_ARG_OR_TARGET = HAS_ARG.union(HAS_TARGET) + + def setUp(self): + self.last_label = 0 + + def Label(self): + self.last_label += 1 + return self.last_label + + def complete_insts_info(self, insts): + # fill in omitted fields in location, and oparg 0 for ops with no arg. + instructions = [] + for item in insts: + if isinstance(item, int): + instructions.append(item) + else: + assert isinstance(item, tuple) + inst = list(reversed(item)) + opcode = dis.opmap[inst.pop()] + oparg = inst.pop() if opcode in self.HAS_ARG_OR_TARGET else 0 + loc = inst + [-1] * (4 - len(inst)) + instructions.append((opcode, oparg, *loc)) + return instructions + + def normalize_insts(self, insts): + """ Map labels to instruction index. + Remove labels which are not used as jump targets. + """ + labels_map = {} + targets = set() + idx = 1 + for item in insts: + assert isinstance(item, (int, tuple)) + if isinstance(item, tuple): + opcode, oparg, *_ = item + if dis.opmap.get(opcode, opcode) in self.HAS_TARGET: + targets.add(oparg) + idx += 1 + elif isinstance(item, int): + assert item not in labels_map, "label reused" + labels_map[item] = idx + + res = [] + for item in insts: + if isinstance(item, int) and item in targets: + if not res or labels_map[item] != res[-1]: + res.append(labels_map[item]) + elif isinstance(item, tuple): + opcode, oparg, *loc = item + opcode = dis.opmap.get(opcode, opcode) + if opcode in self.HAS_TARGET: + arg = labels_map[oparg] + else: + arg = oparg if opcode in self.HAS_TARGET else None + opcode = dis.opname[opcode] + res.append((opcode, arg, *loc)) + return res + + def get_optimized(self, insts, consts): + insts = self.complete_insts_info(insts) + insts = optimize_cfg(insts, consts) + return insts, consts + + def compareInstructions(self, actual_, expected_): + # get two lists where each entry is a label or + # an instruction tuple. Compare them, while mapping + # each actual label to a corresponding expected label + # based on their locations. + + self.assertIsInstance(actual_, list) + self.assertIsInstance(expected_, list) + + actual = self.normalize_insts(actual_) + expected = self.normalize_insts(expected_) + self.assertEqual(len(actual), len(expected)) + + # compare instructions + for act, exp in zip(actual, expected): + if isinstance(act, int): + self.assertEqual(exp, act) + continue + self.assertIsInstance(exp, tuple) + self.assertIsInstance(act, tuple) + # pad exp with -1's (if location info is incomplete) + exp += (-1,) * (len(act) - len(exp)) + self.assertEqual(exp, act) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 425b6bb3e0b4ee6..2b7f008d38564bc 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -5230,6 +5230,13 @@ def test_mixed(self): self.assertEqual(NS(v=3, spam=True, badger="B"), args) self.assertEqual(["C", "--foo", "4"], extras) + def test_zero_or_more_optional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x', nargs='*', choices=('x', 'y')) + args = parser.parse_args([]) + self.assertEqual(NS(x=[]), args) + + # =========================== # parse_intermixed_args tests # =========================== diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 4cfefe4ac3dd1d6..c97d16132f472d7 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -771,6 +771,15 @@ def test_assignment_expression_feature_version(self): with self.assertRaises(SyntaxError): ast.parse('(x := 0)', feature_version=(3, 7)) + def test_exception_groups_feature_version(self): + code = dedent(''' + try: ... + except* Exception: ... + ''') + ast.parse(code) + with self.assertRaises(SyntaxError): + ast.parse(code, feature_version=(3, 10)) + def test_invalid_major_feature_version(self): with self.assertRaises(ValueError): ast.parse('pass', feature_version=(2, 7)) @@ -1136,6 +1145,14 @@ def test_literal_eval(self): self.assertRaises(ValueError, ast.literal_eval, '+True') self.assertRaises(ValueError, ast.literal_eval, '2+3') + def test_literal_eval_str_int_limit(self): + with support.adjust_int_max_str_digits(4000): + ast.literal_eval('3'*4000) # no error + with self.assertRaises(SyntaxError) as err_ctx: + ast.literal_eval('3'*4001) + self.assertIn('Exceeds the limit ', str(err_ctx.exception)) + self.assertIn(' Consider hexadecimal ', str(err_ctx.exception)) + def test_literal_eval_complex(self): # Issue #4907 self.assertEqual(ast.literal_eval('6j'), 6j) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 063174adacfa37f..2dcb20c1cec7f96 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1109,6 +1109,15 @@ def _socket(*args, **kw): self.assertEqual(str(cm.exception), 'Multiple exceptions: err1, err2') + idx = -1 + coro = self.loop.create_connection(MyProto, 'example.com', 80, all_errors=True) + with self.assertRaises(ExceptionGroup) as cm: + self.loop.run_until_complete(coro) + + self.assertIsInstance(cm.exception, ExceptionGroup) + for e in cm.exception.exceptions: + self.assertIsInstance(e, OSError) + @patch_socket def test_create_connection_timeout(self, m_socket): # Ensure that the socket is closed on timeout @@ -1228,6 +1237,14 @@ def getaddrinfo_task(*args, **kwds): self.assertRaises( OSError, self.loop.run_until_complete, coro) + coro = self.loop.create_connection(MyProto, 'example.com', 80, all_errors=True) + with self.assertRaises(ExceptionGroup) as cm: + self.loop.run_until_complete(coro) + + self.assertIsInstance(cm.exception, ExceptionGroup) + self.assertEqual(len(cm.exception.exceptions), 1) + self.assertIsInstance(cm.exception.exceptions[0], OSError) + def test_create_connection_multiple(self): async def getaddrinfo(*args, **kw): return [(2, 1, 6, '', ('0.0.0.1', 80)), @@ -1245,6 +1262,15 @@ def getaddrinfo_task(*args, **kwds): with self.assertRaises(OSError): self.loop.run_until_complete(coro) + coro = self.loop.create_connection( + MyProto, 'example.com', 80, family=socket.AF_INET, all_errors=True) + with self.assertRaises(ExceptionGroup) as cm: + self.loop.run_until_complete(coro) + + self.assertIsInstance(cm.exception, ExceptionGroup) + for e in cm.exception.exceptions: + self.assertIsInstance(e, OSError) + @patch_socket def test_create_connection_multiple_errors_local_addr(self, m_socket): @@ -1276,6 +1302,16 @@ def getaddrinfo_task(*args, **kwds): self.assertTrue(str(cm.exception).startswith('Multiple exceptions: ')) self.assertTrue(m_socket.socket.return_value.close.called) + coro = self.loop.create_connection( + MyProto, 'example.com', 80, family=socket.AF_INET, + local_addr=(None, 8080), all_errors=True) + with self.assertRaises(ExceptionGroup) as cm: + self.loop.run_until_complete(coro) + + self.assertIsInstance(cm.exception, ExceptionGroup) + for e in cm.exception.exceptions: + self.assertIsInstance(e, OSError) + def _test_create_connection_ip_addr(self, m_socket, allow_inet_pton): # Test the fallback code, even if this system has inet_pton. if not allow_inet_pton: diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index 098a0da344d0fb0..0c49099bc499a58 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -864,6 +864,25 @@ def test_streamreaderprotocol_constructor_use_global_loop(self): self.assertEqual(cm.filename, __file__) self.assertIs(protocol._loop, self.loop) + def test_multiple_drain(self): + # See https://github.com/python/cpython/issues/74116 + drained = 0 + + async def drainer(stream): + nonlocal drained + await stream._drain_helper() + drained += 1 + + async def main(): + loop = asyncio.get_running_loop() + stream = asyncio.streams.FlowControlMixin(loop) + stream.pause_writing() + loop.call_later(0.1, stream.resume_writing) + await asyncio.gather(*[drainer(stream) for _ in range(10)]) + self.assertEqual(drained, 10) + + self.loop.run_until_complete(main()) + def test_drain_raises(self): # See http://bugs.python.org/issue25441 diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index 7021d14cf551b3e..066e448a4f220c1 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -185,16 +185,28 @@ def test_sys_getframe(self): self.assertEqual(actual, expected) + + def test_wmi_exec_query(self): + import_helper.import_module("_wmi") + returncode, events, stderr = self.run_python("test_wmi_exec_query") + + actual = [(ev[0], ev[2]) for ev in events] + expected = [("_wmi.exec_query", "SELECT * FROM Win32_OperatingSystem")] + + self.assertEqual(actual, expected) + + def test_syslog(self): syslog = import_helper.import_module("syslog") returncode, events, stderr = self.run_python("test_syslog") + if returncode: self.fail(stderr) if support.verbose: print(*events, sep='\n') - + self.assertSequenceEqual( [('syslog.openlog', ' ', f'python 0 {syslog.LOG_USER}'), ('syslog.syslog', ' ', f'{syslog.LOG_INFO} test'), @@ -203,5 +215,6 @@ def test_syslog(self): events ) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py index ba108221ebf4543..97204d4cad38716 100644 --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -263,6 +263,34 @@ def test_insort_keynotNone(self): for f in (self.module.insort_left, self.module.insort_right): self.assertRaises(TypeError, f, x, y, key = "b") + def test_lt_returns_non_bool(self): + class A: + def __init__(self, val): + self.val = val + def __lt__(self, other): + return "nonempty" if self.val < other.val else "" + + data = [A(i) for i in range(100)] + i1 = self.module.bisect_left(data, A(33)) + i2 = self.module.bisect_right(data, A(33)) + self.assertEqual(i1, 33) + self.assertEqual(i2, 34) + + def test_lt_returns_notimplemented(self): + class A: + def __init__(self, val): + self.val = val + def __lt__(self, other): + return NotImplemented + def __gt__(self, other): + return self.val > other.val + + data = [A(i) for i in range(100)] + i1 = self.module.bisect_left(data, A(40)) + i2 = self.module.bisect_right(data, A(40)) + self.assertEqual(i1, 40) + self.assertEqual(i2, 41) + class TestBisectPython(TestBisect, unittest.TestCase): module = py_bisect diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 6fa5ea67c8b3995..8c9c1e506752eac 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2072,6 +2072,11 @@ def test_envar_ignored_when_hook_is_set(self): breakpoint() mock.assert_not_called() + def test_runtime_error_when_hook_is_lost(self): + del sys.breakpointhook + with self.assertRaises(RuntimeError): + breakpoint() + @unittest.skipUnless(pty, "the pty and signal modules must be available") class PtyTests(unittest.TestCase): diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 521e391b8d5f9db..53ba1ad6f5911f6 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -715,6 +715,24 @@ def test_mod(self): self.assertEqual(b, b'hello,\x00world!') self.assertIs(type(b), self.type2test) + def check(fmt, vals, result): + b = self.type2test(fmt) + b = b % vals + self.assertEqual(b, result) + self.assertIs(type(b), self.type2test) + + # A set of tests adapted from test_unicode:UnicodeTest.test_formatting + check(b'...%(foo)b...', {b'foo':b"abc"}, b'...abc...') + check(b'...%(f(o)o)b...', {b'f(o)o':b"abc", b'foo':b'bar'}, b'...abc...') + check(b'...%(foo)b...', {b'foo':b"abc",b'def':123}, b'...abc...') + check(b'%*b', (5, b'abc',), b' abc') + check(b'%*b', (-5, b'abc',), b'abc ') + check(b'%*.*b', (5, 2, b'abc',), b' ab') + check(b'%*.*b', (5, 3, b'abc',), b' abc') + check(b'%i %*.*b', (10, 5, 3, b'abc',), b'10 abc') + check(b'%i%b %*.*b', (10, b'3', 5, 3, b'abc',), b'103 abc') + check(b'%c', b'a', b'a') + def test_imod(self): b = self.type2test(b'hello, %b!') orig = b diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index 131b45e6caaab34..c00de27b265d273 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -1,5 +1,5 @@ import unittest -from test.support import cpython_only +from test.support import cpython_only, requires_limited_api try: import _testcapi except ImportError: @@ -760,9 +760,7 @@ def __call__(self, *args): self.assertEqual(expected, meth(*args1, **kwargs)) self.assertEqual(expected, wrapped(*args, **kwargs)) - @unittest.skipIf( - hasattr(sys, 'getobjects'), - "Limited API is not compatible with Py_TRACE_REFS") + @requires_limited_api def test_vectorcall_limited(self): from _testcapi import pyobject_vectorcall obj = _testcapi.LimitedVectorCallClass() diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index e6516b33aec0180..94f080978b030f0 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -677,21 +677,43 @@ def test_heaptype_with_custom_metaclass(self): def test_multiple_inheritance_ctypes_with_weakref_or_dict(self): - class Both1(_testcapi.HeapCTypeWithWeakref, _testcapi.HeapCTypeWithDict): + with self.assertRaises(TypeError): + class Both1(_testcapi.HeapCTypeWithWeakref, _testcapi.HeapCTypeWithDict): + pass + with self.assertRaises(TypeError): + class Both2(_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithWeakref): + pass + + def test_multiple_inheritance_ctypes_with_weakref_or_dict_and_other_builtin(self): + + with self.assertRaises(TypeError): + class C1(_testcapi.HeapCTypeWithDict, list): + pass + + with self.assertRaises(TypeError): + class C2(_testcapi.HeapCTypeWithWeakref, list): + pass + + class C3(_testcapi.HeapCTypeWithManagedDict, list): pass - class Both2(_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithWeakref): + class C4(_testcapi.HeapCTypeWithManagedWeakref, list): pass - for cls in (_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithDict2, - _testcapi.HeapCTypeWithWeakref, _testcapi.HeapCTypeWithWeakref2): - for cls2 in (_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithDict2, - _testcapi.HeapCTypeWithWeakref, _testcapi.HeapCTypeWithWeakref2): - if cls is not cls2: - class S(cls, cls2): - pass - class B1(Both1, cls): + inst = C3() + inst.append(0) + str(inst.__dict__) + + inst = C4() + inst.append(0) + str(inst.__weakref__) + + for cls in (_testcapi.HeapCTypeWithManagedDict, _testcapi.HeapCTypeWithManagedWeakref): + for cls2 in (_testcapi.HeapCTypeWithDict, _testcapi.HeapCTypeWithWeakref): + class S(cls, cls2): + pass + class B1(C3, cls): pass - class B2(Both1, cls): + class B2(C4, cls): pass def test_pytype_fromspec_with_repeated_slots(self): @@ -731,14 +753,30 @@ def meth(self): def test_pynumber_tobase(self): from _testcapi import pynumber_tobase - self.assertEqual(pynumber_tobase(123, 2), '0b1111011') - self.assertEqual(pynumber_tobase(123, 8), '0o173') - self.assertEqual(pynumber_tobase(123, 10), '123') - self.assertEqual(pynumber_tobase(123, 16), '0x7b') - self.assertEqual(pynumber_tobase(-123, 2), '-0b1111011') - self.assertEqual(pynumber_tobase(-123, 8), '-0o173') - self.assertEqual(pynumber_tobase(-123, 10), '-123') - self.assertEqual(pynumber_tobase(-123, 16), '-0x7b') + small_number = 123 + large_number = 2**64 + class IDX: + def __init__(self, val): + self.val = val + def __index__(self): + return self.val + + test_cases = ((2, '0b1111011', '0b10000000000000000000000000000000000000000000000000000000000000000'), + (8, '0o173', '0o2000000000000000000000'), + (10, '123', '18446744073709551616'), + (16, '0x7b', '0x10000000000000000')) + for base, small_target, large_target in test_cases: + with self.subTest(base=base, st=small_target, lt=large_target): + # Test for small number + self.assertEqual(pynumber_tobase(small_number, base), small_target) + self.assertEqual(pynumber_tobase(-small_number, base), '-' + small_target) + self.assertEqual(pynumber_tobase(IDX(small_number), base), small_target) + # Test for large number(out of range of a longlong,i.e.[-2**63, 2**63-1]) + self.assertEqual(pynumber_tobase(large_number, base), large_target) + self.assertEqual(pynumber_tobase(-large_number, base), '-' + large_target) + self.assertEqual(pynumber_tobase(IDX(large_number), base), large_target) + self.assertRaises(TypeError, pynumber_tobase, IDX(123.0), 10) + self.assertRaises(TypeError, pynumber_tobase, IDX('123'), 10) self.assertRaises(TypeError, pynumber_tobase, 123.0, 10) self.assertRaises(TypeError, pynumber_tobase, '123', 10) self.assertRaises(SystemError, pynumber_tobase, 123, 0) @@ -1031,6 +1069,21 @@ def callback(): t.start() t.join() + @threading_helper.reap_threads + @threading_helper.requires_working_threading() + def test_gilstate_ensure_no_deadlock(self): + # See https://github.com/python/cpython/issues/96071 + code = textwrap.dedent(f""" + import _testcapi + + def callback(): + print('callback called') + + _testcapi._test_thread_state(callback) + """) + ret = assert_python_ok('-X', 'tracemalloc', '-c', code) + self.assertIn(b'callback called', ret.out) + class Test_testcapi(unittest.TestCase): locals().update((name, getattr(_testcapi, name)) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 64469763957a58e..db967088804ae23 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -865,6 +865,39 @@ def test_parsing_error(self): self.assertTrue(proc.stderr.startswith(err_msg), proc.stderr) self.assertNotEqual(proc.returncode, 0) + def test_int_max_str_digits(self): + code = "import sys; print(sys.flags.int_max_str_digits, sys.get_int_max_str_digits())" + + assert_python_failure('-X', 'int_max_str_digits', '-c', code) + assert_python_failure('-X', 'int_max_str_digits=foo', '-c', code) + assert_python_failure('-X', 'int_max_str_digits=100', '-c', code) + + assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='foo') + assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='100') + + def res2int(res): + out = res.out.strip().decode("utf-8") + return tuple(int(i) for i in out.split()) + + res = assert_python_ok('-c', code) + self.assertEqual(res2int(res), (-1, sys.get_int_max_str_digits())) + res = assert_python_ok('-X', 'int_max_str_digits=0', '-c', code) + self.assertEqual(res2int(res), (0, 0)) + res = assert_python_ok('-X', 'int_max_str_digits=4000', '-c', code) + self.assertEqual(res2int(res), (4000, 4000)) + res = assert_python_ok('-X', 'int_max_str_digits=100000', '-c', code) + self.assertEqual(res2int(res), (100000, 100000)) + + res = assert_python_ok('-c', code, PYTHONINTMAXSTRDIGITS='0') + self.assertEqual(res2int(res), (0, 0)) + res = assert_python_ok('-c', code, PYTHONINTMAXSTRDIGITS='4000') + self.assertEqual(res2int(res), (4000, 4000)) + res = assert_python_ok( + '-X', 'int_max_str_digits=6000', '-c', code, + PYTHONINTMAXSTRDIGITS='4000' + ) + self.assertEqual(res2int(res), (6000, 6000)) + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index c64e4e55f4445af..3ed57c2a5d2763e 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -8,6 +8,7 @@ import tempfile import types import textwrap +import warnings from test import support from test.support import script_helper, requires_debug_ranges from test.support.os_helper import FakePath @@ -198,6 +199,19 @@ def test_literals_with_leading_zeroes(self): self.assertEqual(eval("0o777"), 511) self.assertEqual(eval("-0o0000010"), -8) + def test_int_literals_too_long(self): + n = 3000 + source = f"a = 1\nb = 2\nc = {'3'*n}\nd = 4" + with support.adjust_int_max_str_digits(n): + compile(source, "", "exec") # no errors. + with support.adjust_int_max_str_digits(n-1): + with self.assertRaises(SyntaxError) as err_ctx: + compile(source, "", "exec") + exc = err_ctx.exception + self.assertEqual(exc.lineno, 3) + self.assertIn('Exceeds the limit ', str(exc)) + self.assertIn(' Consider hexadecimal ', str(exc)) + def test_unary_minus(self): # Verify treatment of unary minus on negative numbers SF bug #660455 if sys.maxsize == 2147483647: @@ -1231,7 +1245,9 @@ def f(): with self.subTest(body): namespace = {} source = textwrap.dedent(source_template.format(body)) - exec(source, namespace) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SyntaxWarning) + exec(source, namespace) code = namespace["f"].__code__ self.assertOpcodeSourcePositionIs( code, diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index dba5ceffaf1c03e..8fff2d47c10fd56 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -4,6 +4,7 @@ import pickle import sys import types +import traceback import unittest import warnings from test import support @@ -2207,6 +2208,29 @@ async def f(): with self.assertWarns(RuntimeWarning): gen.cr_frame.clear() + def test_stack_in_coroutine_throw(self): + # Regression test for https://github.com/python/cpython/issues/93592 + async def a(): + return await b() + + async def b(): + return await c() + + @types.coroutine + def c(): + try: + # traceback.print_stack() + yield len(traceback.extract_stack()) + except ZeroDivisionError: + # traceback.print_stack() + yield len(traceback.extract_stack()) + + coro = a() + len_send = coro.send(None) + len_throw = coro.throw(ZeroDivisionError) + # before fixing, visible stack from throw would be shorter than from send. + self.assertEqual(len_send, len_throw) + @unittest.skipIf( support.is_emscripten or support.is_wasi, diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 95a19dd46cb4ffa..a2b00430c7dd602 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -448,6 +448,34 @@ def test_register_kwargs(self): self.assertEqual(csv.get_dialect(name).delimiter, ';') self.assertEqual([['X', 'Y', 'Z']], list(csv.reader(['X;Y;Z'], name))) + def test_register_kwargs_override(self): + class mydialect(csv.Dialect): + delimiter = "\t" + quotechar = '"' + doublequote = True + skipinitialspace = False + lineterminator = '\r\n' + quoting = csv.QUOTE_MINIMAL + + name = 'test_dialect' + csv.register_dialect(name, mydialect, + delimiter=';', + quotechar="'", + doublequote=False, + skipinitialspace=True, + lineterminator='\n', + quoting=csv.QUOTE_ALL) + self.addCleanup(csv.unregister_dialect, name) + + # Ensure that kwargs do override attributes of a dialect class: + dialect = csv.get_dialect(name) + self.assertEqual(dialect.delimiter, ';') + self.assertEqual(dialect.quotechar, "'") + self.assertEqual(dialect.doublequote, False) + self.assertEqual(dialect.skipinitialspace, True) + self.assertEqual(dialect.lineterminator, '\n') + self.assertEqual(dialect.quoting, csv.QUOTE_ALL) + def test_incomplete_dialect(self): class myexceltsv(csv.Dialect): delimiter = "\t" @@ -736,6 +764,34 @@ def test_write_field_not_in_field_names_ignore(self): csv.DictWriter.writerow(writer, dictrow) self.assertEqual(fileobj.getvalue(), "1,2\r\n") + def test_dict_reader_fieldnames_accepts_iter(self): + fieldnames = ["a", "b", "c"] + f = StringIO() + reader = csv.DictReader(f, iter(fieldnames)) + self.assertEqual(reader.fieldnames, fieldnames) + + def test_dict_reader_fieldnames_accepts_list(self): + fieldnames = ["a", "b", "c"] + f = StringIO() + reader = csv.DictReader(f, fieldnames) + self.assertEqual(reader.fieldnames, fieldnames) + + def test_dict_writer_fieldnames_rejects_iter(self): + fieldnames = ["a", "b", "c"] + f = StringIO() + writer = csv.DictWriter(f, iter(fieldnames)) + self.assertEqual(writer.fieldnames, fieldnames) + + def test_dict_writer_fieldnames_accepts_list(self): + fieldnames = ["a", "b", "c"] + f = StringIO() + writer = csv.DictWriter(f, fieldnames) + self.assertEqual(writer.fieldnames, fieldnames) + + def test_dict_reader_fieldnames_is_optional(self): + f = StringIO() + reader = csv.DictReader(f, fieldnames=None) + def test_read_dict_fields(self): with TemporaryFile("w+", encoding="utf-8") as fileobj: fileobj.write("1,2,abc\r\n") diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 7c5964e3d5535d8..67ccaab40c5edc1 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -2526,6 +2526,15 @@ class CUsabilityTest(UsabilityTest): class PyUsabilityTest(UsabilityTest): decimal = P + def setUp(self): + super().setUp() + self._previous_int_limit = sys.get_int_max_str_digits() + sys.set_int_max_str_digits(7000) + + def tearDown(self): + sys.set_int_max_str_digits(self._previous_int_limit) + super().tearDown() + class PythonAPItests(unittest.TestCase): def test_abc(self): @@ -4626,6 +4635,15 @@ class CCoverage(Coverage): class PyCoverage(Coverage): decimal = P + def setUp(self): + super().setUp() + self._previous_int_limit = sys.get_int_max_str_digits() + sys.set_int_max_str_digits(7000) + + def tearDown(self): + sys.set_int_max_str_digits(self._previous_int_limit) + super().tearDown() + class PyFunctionality(unittest.TestCase): """Extra functionality in decimal.py""" diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py index be271bebaaf1fff..7c48d800cd88bdf 100644 --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -170,6 +170,10 @@ def test_items_set_operations(self): {('a', 1), ('b', 2)}) self.assertEqual(d1.items() & set(d2.items()), {('b', 2)}) self.assertEqual(d1.items() & set(d3.items()), set()) + self.assertEqual(d1.items() & (("a", 1), ("b", 2)), + {('a', 1), ('b', 2)}) + self.assertEqual(d1.items() & (("a", 2), ("b", 2)), {('b', 2)}) + self.assertEqual(d1.items() & (("d", 4), ("e", 5)), set()) self.assertEqual(d1.items() | d1.items(), {('a', 1), ('b', 2)}) @@ -183,12 +187,23 @@ def test_items_set_operations(self): {('a', 1), ('a', 2), ('b', 2)}) self.assertEqual(d1.items() | set(d3.items()), {('a', 1), ('b', 2), ('d', 4), ('e', 5)}) + self.assertEqual(d1.items() | (('a', 1), ('b', 2)), + {('a', 1), ('b', 2)}) + self.assertEqual(d1.items() | (('a', 2), ('b', 2)), + {('a', 1), ('a', 2), ('b', 2)}) + self.assertEqual(d1.items() | (('d', 4), ('e', 5)), + {('a', 1), ('b', 2), ('d', 4), ('e', 5)}) self.assertEqual(d1.items() ^ d1.items(), set()) self.assertEqual(d1.items() ^ d2.items(), {('a', 1), ('a', 2)}) self.assertEqual(d1.items() ^ d3.items(), {('a', 1), ('b', 2), ('d', 4), ('e', 5)}) + self.assertEqual(d1.items() ^ (('a', 1), ('b', 2)), set()) + self.assertEqual(d1.items() ^ (("a", 2), ("b", 2)), + {('a', 1), ('a', 2)}) + self.assertEqual(d1.items() ^ (("d", 4), ("e", 5)), + {('a', 1), ('b', 2), ('d', 4), ('e', 5)}) self.assertEqual(d1.items() - d1.items(), set()) self.assertEqual(d1.items() - d2.items(), {('a', 1)}) @@ -196,6 +211,9 @@ def test_items_set_operations(self): self.assertEqual(d1.items() - set(d1.items()), set()) self.assertEqual(d1.items() - set(d2.items()), {('a', 1)}) self.assertEqual(d1.items() - set(d3.items()), {('a', 1), ('b', 2)}) + self.assertEqual(d1.items() - (('a', 1), ('b', 2)), set()) + self.assertEqual(d1.items() - (("a", 2), ("b", 2)), {('a', 1)}) + self.assertEqual(d1.items() - (("d", 4), ("e", 5)), {('a', 1), ('b', 2)}) self.assertFalse(d1.items().isdisjoint(d1.items())) self.assertFalse(d1.items().isdisjoint(d2.items())) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index f07e7c860547828..48d596027870fc7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -366,7 +366,7 @@ def bug42562(): %3d LOAD_GLOBAL 0 (Exception) CHECK_EXC_MATCH - POP_JUMP_FORWARD_IF_FALSE 22 (to 80) + POP_JUMP_IF_FALSE 22 (to 80) STORE_FAST 0 (e) %3d LOAD_FAST 0 (e) @@ -447,7 +447,7 @@ def _with(c): %3d >> PUSH_EXC_INFO WITH_EXCEPT_START - POP_JUMP_FORWARD_IF_TRUE 1 (to 46) + POP_JUMP_IF_TRUE 1 (to 46) RERAISE 2 >> POP_TOP POP_EXCEPT @@ -507,26 +507,31 @@ async def _asyncwith(c): LOAD_CONST 0 (None) RETURN_VALUE -%3d >> PUSH_EXC_INFO +%3d >> CLEANUP_THROW + JUMP_BACKWARD 24 (to 22) + >> CLEANUP_THROW + JUMP_BACKWARD 9 (to 56) + >> PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 LOAD_CONST 0 (None) - >> SEND 3 (to 82) + >> SEND 4 (to 92) YIELD_VALUE 6 RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 4 (to 74) - >> POP_JUMP_FORWARD_IF_TRUE 1 (to 86) + JUMP_BACKWARD_NO_INTERRUPT 4 (to 82) + >> CLEANUP_THROW + >> POP_JUMP_IF_TRUE 1 (to 96) RERAISE 2 >> POP_TOP POP_EXCEPT POP_TOP POP_TOP - JUMP_BACKWARD 19 (to 58) + JUMP_BACKWARD 24 (to 58) >> COPY 3 POP_EXCEPT RERAISE 1 ExceptionTable: -2 rows +6 rows """ % (_asyncwith.__code__.co_firstlineno, _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 2, @@ -869,15 +874,7 @@ def test_boundaries(self): self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT) def test_widths(self): - long_opcodes = set(['POP_JUMP_FORWARD_IF_FALSE', - 'POP_JUMP_FORWARD_IF_TRUE', - 'POP_JUMP_FORWARD_IF_NOT_NONE', - 'POP_JUMP_FORWARD_IF_NONE', - 'POP_JUMP_BACKWARD_IF_FALSE', - 'POP_JUMP_BACKWARD_IF_TRUE', - 'POP_JUMP_BACKWARD_IF_NOT_NONE', - 'POP_JUMP_BACKWARD_IF_NONE', - 'JUMP_BACKWARD_NO_INTERRUPT', + long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT', ]) for opcode, opname in enumerate(dis.opname): if opname in long_opcodes: @@ -1539,7 +1536,7 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=14, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='FOR_ITER', opcode=93, arg=29, argval=90, argrepr='to 90', offset=28, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='FOR_ITER', opcode=93, arg=30, argval=92, argrepr='to 92', offset=28, starts_line=None, is_jump_target=True, positions=None), Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=32, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=34, starts_line=4, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=46, starts_line=None, is_jump_target=False, positions=None), @@ -1548,103 +1545,105 @@ def _prepare_test_cases(): Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=5, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=62, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=64, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=74, argrepr='to 74', offset=70, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=74, argrepr='to 74', offset=70, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_BACKWARD', opcode=140, arg=23, argval=28, argrepr='to 28', offset=72, starts_line=6, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=7, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=76, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=78, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_BACKWARD_IF_FALSE', opcode=175, arg=29, argval=28, argrepr='to 28', offset=84, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=86, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=116, argrepr='to 116', offset=88, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=90, starts_line=10, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=102, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=116, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=34, argval=188, argrepr='to 188', offset=118, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=120, starts_line=12, is_jump_target=True, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=13, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=148, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=156, starts_line=14, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=158, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=170, argrepr='to 170', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=116, argrepr='to 116', offset=168, starts_line=15, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=170, starts_line=16, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=172, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=184, argrepr='to 184', offset=180, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=214, argrepr='to 214', offset=182, starts_line=17, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=184, starts_line=11, is_jump_target=True, positions=None), - Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=34, argval=120, argrepr='to 120', offset=186, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=188, starts_line=19, is_jump_target=True, positions=None), - 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=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=214, starts_line=20, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=216, starts_line=21, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=226, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=232, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=260, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=262, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=264, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=274, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=276, starts_line=28, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=288, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=300, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=302, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=1, argval=314, argrepr='to 314', offset=310, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=314, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=276, argrepr='to 276', offset=322, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=16, argval=380, argrepr='to 380', offset=346, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=374, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=376, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=276, argrepr='to 276', offset=378, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=380, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=390, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=402, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=404, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=414, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=416, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=88, argrepr='to 88', offset=84, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=30, argval=28, argrepr='to 28', offset=86, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=88, starts_line=8, is_jump_target=True, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=118, argrepr='to 118', offset=90, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=92, starts_line=10, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=104, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=106, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=118, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=35, argval=192, argrepr='to 192', offset=120, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=122, starts_line=12, is_jump_target=True, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=148, starts_line=13, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=150, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=156, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=158, starts_line=14, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=160, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=162, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=172, argrepr='to 172', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=118, argrepr='to 118', offset=170, starts_line=15, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=16, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=176, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=218, argrepr='to 218', offset=184, starts_line=17, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=11, is_jump_target=True, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=192, argrepr='to 192', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=35, argval=122, argrepr='to 122', offset=190, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=192, starts_line=19, is_jump_target=True, positions=None), + 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=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=218, starts_line=20, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=220, starts_line=21, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=222, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=230, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=234, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=236, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=248, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=260, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=262, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=264, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=266, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=278, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=280, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=292, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=306, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=310, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=318, argrepr='to 318', offset=314, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=280, argrepr='to 280', offset=326, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=332, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=334, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=336, starts_line=22, is_jump_target=False, positions=None), + Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=16, argval=384, argrepr='to 384', offset=350, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=352, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=354, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=366, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=280, argrepr='to 280', offset=382, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=392, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=394, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=406, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=408, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=426, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index c546bb08e297c34..70d7367ea9e64fd 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -436,6 +436,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'hash_seed': 0, 'faulthandler': 0, 'tracemalloc': 0, + 'perf_profiling': 0, 'import_time': 0, 'code_debug_ranges': 1, 'show_ref_count': 0, @@ -520,6 +521,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): use_hash_seed=0, faulthandler=0, tracemalloc=0, + perf_profiling=0, pathconfig_warnings=0, ) if MS_WINDOWS: @@ -828,6 +830,7 @@ def test_init_from_config(self): 'use_hash_seed': 1, 'hash_seed': 123, 'tracemalloc': 2, + 'perf_profiling': 0, 'import_time': 1, 'code_debug_ranges': 0, 'show_ref_count': 1, @@ -890,6 +893,7 @@ def test_init_compat_env(self): 'use_hash_seed': 1, 'hash_seed': 42, 'tracemalloc': 2, + 'perf_profiling': 0, 'import_time': 1, 'code_debug_ranges': 0, 'malloc_stats': 1, @@ -921,6 +925,7 @@ def test_init_python_env(self): 'use_hash_seed': 1, 'hash_seed': 42, 'tracemalloc': 2, + 'perf_profiling': 0, 'import_time': 1, 'code_debug_ranges': 0, 'malloc_stats': 1, diff --git a/Lib/test/test_exception_hierarchy.py b/Lib/test/test_exception_hierarchy.py index 89fe9ddcefba3ee..3318fa8e7746f7a 100644 --- a/Lib/test/test_exception_hierarchy.py +++ b/Lib/test/test_exception_hierarchy.py @@ -63,7 +63,7 @@ def test_select_error(self): +-- InterruptedError EINTR +-- IsADirectoryError EISDIR +-- NotADirectoryError ENOTDIR - +-- PermissionError EACCES, EPERM + +-- PermissionError EACCES, EPERM, ENOTCAPABLE +-- ProcessLookupError ESRCH +-- TimeoutError ETIMEDOUT """ @@ -75,6 +75,8 @@ def _make_map(s): continue excname, _, errnames = line.partition(' ') for errname in filter(None, errnames.strip().split(', ')): + if errname == "ENOTCAPABLE" and not hasattr(errno, errname): + continue _map[getattr(errno, errname)] = getattr(builtins, excname) return _map _map = _make_map(_pep_map) @@ -91,7 +93,7 @@ def test_errno_mapping(self): othercodes = set(errno.errorcode) - set(self._map) for errcode in othercodes: e = OSError(errcode, "Some message") - self.assertIs(type(e), OSError) + self.assertIs(type(e), OSError, repr(e)) def test_try_except(self): filename = "some_hopefully_non_existing_file" diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py index fc46e8674fc46e9..7fa9dbea905b592 100644 --- a/Lib/test/test_fractions.py +++ b/Lib/test/test_fractions.py @@ -162,6 +162,7 @@ def testInitFromDecimal(self): def testFromString(self): self.assertEqual((5, 1), _components(F("5"))) self.assertEqual((3, 2), _components(F("3/2"))) + self.assertEqual((3, 2), _components(F("3 / 2"))) self.assertEqual((3, 2), _components(F(" \n +3/2"))) self.assertEqual((-3, 2), _components(F("-3/2 "))) self.assertEqual((13, 2), _components(F(" 013/02 \n "))) @@ -190,9 +191,6 @@ def testFromString(self): self.assertRaisesMessage( ValueError, "Invalid literal for Fraction: '/2'", F, "/2") - self.assertRaisesMessage( - ValueError, "Invalid literal for Fraction: '3 /2'", - F, "3 /2") self.assertRaisesMessage( # Denominators don't need a sign. ValueError, "Invalid literal for Fraction: '3/+2'", diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py index 12917755a56017e..b42a611c62c0aa1 100644 --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -4,6 +4,8 @@ import pprint import unittest +from unittest.mock import patch + class EventCollector(html.parser.HTMLParser): @@ -787,5 +789,17 @@ def test_weird_chars_in_unquoted_attribute_values(self): ('starttag', 'form', [('action', 'bogus|&#()value')])]) + +class TestInheritance(unittest.TestCase): + + @patch("_markupbase.ParserBase.__init__") + @patch("_markupbase.ParserBase.reset") + def test_base_class_methods_called(self, super_reset_method, super_init_method): + with patch('_markupbase.ParserBase') as parser_base: + EventCollector() + super_init_method.assert_called_once() + super_reset_method.assert_called_once() + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 15dab0356f5e35e..b3d94e0a21cb6a9 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -553,6 +553,27 @@ def __new__(cls, value, phrase, description=''): obj.phrase = phrase obj.description = description return obj + + @property + def is_informational(self): + return 100 <= self <= 199 + + @property + def is_success(self): + return 200 <= self <= 299 + + @property + def is_redirection(self): + return 300 <= self <= 399 + + @property + def is_client_error(self): + return 400 <= self <= 499 + + @property + def is_server_error(self): + return 500 <= self <= 599 + # informational CONTINUE = 100, 'Continue', 'Request received, please continue' SWITCHING_PROTOCOLS = (101, 'Switching Protocols', @@ -669,6 +690,30 @@ def __new__(cls, value, phrase, description=''): 'The client needs to authenticate to gain network access') enum._test_simple_enum(CheckedHTTPStatus, HTTPStatus) + def test_httpstatus_range(self): + """Checks that the statuses are in the 100-599 range""" + + for member in HTTPStatus.__members__.values(): + self.assertGreaterEqual(member, 100) + self.assertLessEqual(member, 599) + + def test_httpstatus_category(self): + """Checks that the statuses belong to the standard categories""" + + categories = ( + ((100, 199), "is_informational"), + ((200, 299), "is_success"), + ((300, 399), "is_redirection"), + ((400, 499), "is_client_error"), + ((500, 599), "is_server_error"), + ) + for member in HTTPStatus.__members__.values(): + for (lower, upper), category in categories: + category_indicator = getattr(member, category) + if lower <= member <= upper: + self.assertTrue(category_indicator) + else: + self.assertFalse(category_indicator) def test_status_lines(self): # Test HTTP status lines diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index d44dc6b49f2935b..35b6afa91ebd4f8 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -66,11 +66,7 @@ def setUp(self): self.test_strings = mod.test_strings self.test_path = mod.__path__ - def test_import_encoded_module(self): - for modname, encoding, teststr in self.test_strings: - mod = importlib.import_module('test.encoded_modules.' - 'module_' + modname) - self.assertEqual(teststr, mod.test) + # test_import_encoded_module moved to test_source_encoding.py def test_find_module_encoding(self): for mod, encoding, _ in self.test_strings: diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py index 88bf100efaad80a..c214209350a0c85 100644 --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -320,32 +320,6 @@ def contents(self, *args, **kwargs): return super().contents(*args, **kwargs) -class ResourceReaderDefaultsTests(ABCTestHarness): - - SPLIT = make_abc_subclasses(ResourceReader) - - def test_open_resource(self): - with self.assertRaises(FileNotFoundError): - self.ins.open_resource('dummy_file') - - def test_resource_path(self): - with self.assertRaises(FileNotFoundError): - self.ins.resource_path('dummy_file') - - def test_is_resource(self): - with self.assertRaises(FileNotFoundError): - self.ins.is_resource('dummy_file') - - def test_contents(self): - with self.assertRaises(FileNotFoundError): - self.ins.contents() - - -(Frozen_RRDefaultTests, - Source_RRDefaultsTests - ) = test_util.test_both(ResourceReaderDefaultsTests) - - ##### MetaPathFinder concrete methods ########################################## class MetaPathFinderFindModuleTests: diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index a72699cc7506af1..800c0b006cdc6ba 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -1,4 +1,5 @@ import sys +import time import unittest from test import support @@ -577,5 +578,200 @@ def test_issue31619(self): self.assertEqual(int('1_2_3_4_5_6_7', 32), 1144132807) +class IntStrDigitLimitsTests(unittest.TestCase): + + int_class = int # Override this in subclasses to reuse the suite. + + def setUp(self): + super().setUp() + self._previous_limit = sys.get_int_max_str_digits() + sys.set_int_max_str_digits(2048) + + def tearDown(self): + sys.set_int_max_str_digits(self._previous_limit) + super().tearDown() + + def test_disabled_limit(self): + self.assertGreater(sys.get_int_max_str_digits(), 0) + self.assertLess(sys.get_int_max_str_digits(), 20_000) + with support.adjust_int_max_str_digits(0): + self.assertEqual(sys.get_int_max_str_digits(), 0) + i = self.int_class('1' * 20_000) + str(i) + self.assertGreater(sys.get_int_max_str_digits(), 0) + + def test_max_str_digits_edge_cases(self): + """Ignore the +/- sign and space padding.""" + int_class = self.int_class + maxdigits = sys.get_int_max_str_digits() + + int_class('1' * maxdigits) + int_class(' ' + '1' * maxdigits) + int_class('1' * maxdigits + ' ') + int_class('+' + '1' * maxdigits) + int_class('-' + '1' * maxdigits) + self.assertEqual(len(str(10 ** (maxdigits - 1))), maxdigits) + + def check(self, i, base=None): + with self.assertRaises(ValueError): + if base is None: + self.int_class(i) + else: + self.int_class(i, base) + + def test_max_str_digits(self): + maxdigits = sys.get_int_max_str_digits() + + self.check('1' * (maxdigits + 1)) + self.check(' ' + '1' * (maxdigits + 1)) + self.check('1' * (maxdigits + 1) + ' ') + self.check('+' + '1' * (maxdigits + 1)) + self.check('-' + '1' * (maxdigits + 1)) + self.check('1' * (maxdigits + 1)) + + i = 10 ** maxdigits + with self.assertRaises(ValueError): + str(i) + + def test_denial_of_service_prevented_int_to_str(self): + """Regression test: ensure we fail before performing O(N**2) work.""" + maxdigits = sys.get_int_max_str_digits() + assert maxdigits < 50_000, maxdigits # A test prerequisite. + get_time = time.process_time + if get_time() <= 0: # some platforms like WASM lack process_time() + get_time = time.monotonic + + huge_int = int(f'0x{"c"*65_000}', base=16) # 78268 decimal digits. + digits = 78_268 + with support.adjust_int_max_str_digits(digits): + start = get_time() + huge_decimal = str(huge_int) + seconds_to_convert = get_time() - start + self.assertEqual(len(huge_decimal), digits) + # Ensuring that we chose a slow enough conversion to measure. + # It takes 0.1 seconds on a Zen based cloud VM in an opt build. + if seconds_to_convert < 0.005: + raise unittest.SkipTest('"slow" conversion took only ' + f'{seconds_to_convert} seconds.') + + # We test with the limit almost at the size needed to check performance. + # The performant limit check is slightly fuzzy, give it a some room. + with support.adjust_int_max_str_digits(int(.995 * digits)): + with self.assertRaises(ValueError) as err: + start = get_time() + str(huge_int) + seconds_to_fail_huge = get_time() - start + self.assertIn('conversion', str(err.exception)) + self.assertLess(seconds_to_fail_huge, seconds_to_convert/8) + + # Now we test that a conversion that would take 30x as long also fails + # in a similarly fast fashion. + extra_huge_int = int(f'0x{"c"*500_000}', base=16) # 602060 digits. + with self.assertRaises(ValueError) as err: + start = get_time() + # If not limited, 8 seconds said Zen based cloud VM. + str(extra_huge_int) + seconds_to_fail_extra_huge = get_time() - start + self.assertIn('conversion', str(err.exception)) + self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8) + + def test_denial_of_service_prevented_str_to_int(self): + """Regression test: ensure we fail before performing O(N**2) work.""" + maxdigits = sys.get_int_max_str_digits() + assert maxdigits < 100_000, maxdigits # A test prerequisite. + get_time = time.process_time + if get_time() <= 0: # some platforms like WASM lack process_time() + get_time = time.monotonic + + digits = 133700 + huge = '8'*digits + with support.adjust_int_max_str_digits(digits): + start = get_time() + int(huge) + seconds_to_convert = get_time() - start + # Ensuring that we chose a slow enough conversion to measure. + # It takes 0.1 seconds on a Zen based cloud VM in an opt build. + if seconds_to_convert < 0.005: + raise unittest.SkipTest('"slow" conversion took only ' + f'{seconds_to_convert} seconds.') + + with support.adjust_int_max_str_digits(digits - 1): + with self.assertRaises(ValueError) as err: + start = get_time() + int(huge) + seconds_to_fail_huge = get_time() - start + self.assertIn('conversion', str(err.exception)) + self.assertLess(seconds_to_fail_huge, seconds_to_convert/8) + + # Now we test that a conversion that would take 30x as long also fails + # in a similarly fast fashion. + extra_huge = '7'*1_200_000 + with self.assertRaises(ValueError) as err: + start = get_time() + # If not limited, 8 seconds in the Zen based cloud VM. + int(extra_huge) + seconds_to_fail_extra_huge = get_time() - start + self.assertIn('conversion', str(err.exception)) + self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8) + + def test_power_of_two_bases_unlimited(self): + """The limit does not apply to power of 2 bases.""" + maxdigits = sys.get_int_max_str_digits() + + for base in (2, 4, 8, 16, 32): + with self.subTest(base=base): + self.int_class('1' * (maxdigits + 1), base) + assert maxdigits < 100_000 + self.int_class('1' * 100_000, base) + + def test_underscores_ignored(self): + maxdigits = sys.get_int_max_str_digits() + + triples = maxdigits // 3 + s = '111' * triples + s_ = '1_11' * triples + self.int_class(s) # succeeds + self.int_class(s_) # succeeds + self.check(f'{s}111') + self.check(f'{s_}_111') + + def test_sign_not_counted(self): + int_class = self.int_class + max_digits = sys.get_int_max_str_digits() + s = '5' * max_digits + i = int_class(s) + pos_i = int_class(f'+{s}') + assert i == pos_i + neg_i = int_class(f'-{s}') + assert -pos_i == neg_i + str(pos_i) + str(neg_i) + + def _other_base_helper(self, base): + int_class = self.int_class + max_digits = sys.get_int_max_str_digits() + s = '2' * max_digits + i = int_class(s, base) + if base > 10: + with self.assertRaises(ValueError): + str(i) + elif base < 10: + str(i) + with self.assertRaises(ValueError) as err: + int_class(f'{s}1', base) + + def test_int_from_other_bases(self): + base = 3 + with self.subTest(base=base): + self._other_base_helper(base) + base = 36 + with self.subTest(base=base): + self._other_base_helper(base) + + +class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests): + int_class = IntSubclass + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_json/__init__.py b/Lib/test/test_json/__init__.py index 74b64ed86a3183d..37b2e0d5e26d162 100644 --- a/Lib/test/test_json/__init__.py +++ b/Lib/test/test_json/__init__.py @@ -18,6 +18,7 @@ class PyTest(unittest.TestCase): json = pyjson loads = staticmethod(pyjson.loads) dumps = staticmethod(pyjson.dumps) + AttrDict = pyjson.AttrDict JSONDecodeError = staticmethod(pyjson.JSONDecodeError) @unittest.skipUnless(cjson, 'requires _json') diff --git a/Lib/test/test_json/test_attrdict.py b/Lib/test/test_json/test_attrdict.py new file mode 100644 index 000000000000000..48d14f4db93c120 --- /dev/null +++ b/Lib/test/test_json/test_attrdict.py @@ -0,0 +1,145 @@ +from test.test_json import PyTest +import pickle +import sys +import unittest + +kepler_dict = { + "orbital_period": { + "mercury": 88, + "venus": 225, + "earth": 365, + "mars": 687, + "jupiter": 4331, + "saturn": 10_756, + "uranus": 30_687, + "neptune": 60_190, + }, + "dist_from_sun": { + "mercury": 58, + "venus": 108, + "earth": 150, + "mars": 228, + "jupiter": 778, + "saturn": 1_400, + "uranus": 2_900, + "neptune": 4_500, + } +} + +class TestAttrDict(PyTest): + + def test_dict_subclass(self): + self.assertTrue(issubclass(self.AttrDict, dict)) + + def test_slots(self): + d = self.AttrDict(x=1, y=2) + with self.assertRaises(TypeError): + vars(d) + + def test_constructor_signatures(self): + AttrDict = self.AttrDict + target = dict(x=1, y=2) + self.assertEqual(AttrDict(x=1, y=2), target) # kwargs + self.assertEqual(AttrDict(dict(x=1, y=2)), target) # mapping + self.assertEqual(AttrDict(dict(x=1, y=0), y=2), target) # mapping, kwargs + self.assertEqual(AttrDict([('x', 1), ('y', 2)]), target) # iterable + self.assertEqual(AttrDict([('x', 1), ('y', 0)], y=2), target) # iterable, kwargs + + def test_getattr(self): + d = self.AttrDict(x=1, y=2) + self.assertEqual(d.x, 1) + with self.assertRaises(AttributeError): + d.z + + def test_setattr(self): + d = self.AttrDict(x=1, y=2) + d.x = 3 + d.z = 5 + self.assertEqual(d, dict(x=3, y=2, z=5)) + + def test_delattr(self): + d = self.AttrDict(x=1, y=2) + del d.x + self.assertEqual(d, dict(y=2)) + with self.assertRaises(AttributeError): + del d.z + + def test_dir(self): + d = self.AttrDict(x=1, y=2) + self.assertTrue(set(dir(d)), set(dir(dict)).union({'x', 'y'})) + + def test_repr(self): + # This repr is doesn't round-trip. It matches a regular dict. + # That seems to be the norm for AttrDict recipes being used + # in the wild. Also it supports the design concept that an + # AttrDict is just like a regular dict but has optional + # attribute style lookup. + self.assertEqual(repr(self.AttrDict(x=1, y=2)), + repr(dict(x=1, y=2))) + + def test_overlapping_keys_and_methods(self): + d = self.AttrDict(items=50) + self.assertEqual(d['items'], 50) + self.assertEqual(d.items(), dict(d).items()) + + def test_invalid_attribute_names(self): + d = self.AttrDict({ + 'control': 'normal case', + 'class': 'keyword', + 'two words': 'contains space', + 'hypen-ate': 'contains a hyphen' + }) + self.assertEqual(d.control, dict(d)['control']) + self.assertEqual(d['class'], dict(d)['class']) + self.assertEqual(d['two words'], dict(d)['two words']) + self.assertEqual(d['hypen-ate'], dict(d)['hypen-ate']) + + def test_object_hook_use_case(self): + AttrDict = self.AttrDict + json_string = self.dumps(kepler_dict) + kepler_ad = self.loads(json_string, object_hook=AttrDict) + + self.assertEqual(kepler_ad, kepler_dict) # Match regular dict + self.assertIsInstance(kepler_ad, AttrDict) # Verify conversion + self.assertIsInstance(kepler_ad.orbital_period, AttrDict) # Nested + + # Exercise dotted lookups + self.assertEqual(kepler_ad.orbital_period, kepler_dict['orbital_period']) + self.assertEqual(kepler_ad.orbital_period.earth, + kepler_dict['orbital_period']['earth']) + self.assertEqual(kepler_ad['orbital_period'].earth, + kepler_dict['orbital_period']['earth']) + + # Dict style error handling and Attribute style error handling + with self.assertRaises(KeyError): + kepler_ad.orbital_period['pluto'] + with self.assertRaises(AttributeError): + kepler_ad.orbital_period.Pluto + + # Order preservation + self.assertEqual(list(kepler_ad.items()), list(kepler_dict.items())) + self.assertEqual(list(kepler_ad.orbital_period.items()), + list(kepler_dict['orbital_period'].items())) + + # Round trip + self.assertEqual(self.dumps(kepler_ad), json_string) + + def test_pickle(self): + AttrDict = self.AttrDict + json_string = self.dumps(kepler_dict) + kepler_ad = self.loads(json_string, object_hook=AttrDict) + + # Pickling requires the cached module to be the real module + cached_module = sys.modules.get('json') + sys.modules['json'] = self.json + try: + for protocol in range(6): + kepler_ad2 = pickle.loads(pickle.dumps(kepler_ad, protocol)) + self.assertEqual(kepler_ad2, kepler_ad) + self.assertEqual(type(kepler_ad2), AttrDict) + finally: + sys.modules['json'] = cached_module + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index fdb9e62124ece1f..124045b13184b3e 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -2,6 +2,7 @@ from io import StringIO from collections import OrderedDict from test.test_json import PyTest, CTest +from test import support class TestDecode: @@ -95,5 +96,13 @@ def test_negative_index(self): d = self.json.JSONDecoder() self.assertRaises(ValueError, d.raw_decode, 'a'*42, -50000) + def test_limit_int(self): + maxdigits = 5000 + with support.adjust_int_max_str_digits(maxdigits): + self.loads('1' * maxdigits) + with self.assertRaises(ValueError): + self.loads('1' * (maxdigits + 1)) + + class TestPyDecode(TestDecode, PyTest): pass class TestCDecode(TestDecode, CTest): pass diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index 835a51e3b6e0112..be0cd90c7906f5c 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -238,9 +238,11 @@ def run_py(self, args, env=None, allow_fail=False, expect_returncode=0, argv=Non return data def py_ini(self, content): - if not self.py_exe: - self.py_exe = self.find_py() - return PreservePyIni(self.py_exe.with_name("py.ini"), content) + local_appdata = os.environ.get("LOCALAPPDATA") + if not local_appdata: + raise unittest.SkipTest("LOCALAPPDATA environment variable is " + "missing or empty") + return PreservePyIni(Path(local_appdata) / "py.ini", content) @contextlib.contextmanager def script(self, content, encoding="utf-8"): @@ -556,6 +558,13 @@ def test_py_shebang_short_argv0(self): self.assertEqual("3.100", data["SearchInfo.tag"]) self.assertEqual(f'X.Y.exe -prearg "{script}" -postarg', data["stdout"].strip()) + def test_py_handle_64_in_ini(self): + with self.py_ini("\n".join(["[defaults]", "python=3.999-64"])): + # Expect this to fail, but should get oldStyleTag flipped on + data = self.run_py([], allow_fail=True, expect_returncode=103) + self.assertEqual("3.999-64", data["SearchInfo.tag"]) + self.assertEqual("True", data["SearchInfo.oldStyleTag"]) + def test_search_path(self): stem = Path(sys.executable).stem with self.py_ini(TEST_PY_COMMANDS): diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 99ea2f687551d7a..d70bfd6b09e13d2 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3677,6 +3677,35 @@ def test_config_queue_handler(self): msg = str(ctx.exception) self.assertEqual(msg, "Unable to configure handler 'ah'") + def test_90195(self): + # See gh-90195 + config = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + }, + }, + 'loggers': { + 'a': { + 'level': 'DEBUG', + 'handlers': ['console'] + } + } + } + logger = logging.getLogger('a') + self.assertFalse(logger.disabled) + self.apply_config(config) + self.assertFalse(logger.disabled) + # Should disable all loggers ... + self.apply_config({'version': 1}) + self.assertTrue(logger.disabled) + del config['disable_existing_loggers'] + self.apply_config(config) + # Logger should be enabled, since explicitly mentioned + self.assertFalse(logger.disabled) class ManagerTest(BaseTest): def test_manager_loggerclass(self): @@ -3717,6 +3746,20 @@ def test_child_loggers(self): self.assertIs(c2, logging.getLogger('abc.def.ghi')) self.assertIs(c2, c3) + def test_get_children(self): + r = logging.getLogger() + l1 = logging.getLogger('foo') + l2 = logging.getLogger('foo.bar') + l3 = logging.getLogger('foo.bar.baz.bozz') + l4 = logging.getLogger('bar') + kids = r.getChildren() + expected = {l1, l4} + self.assertEqual(expected, kids & expected) # might be other kids for root + self.assertNotIn(l2, expected) + kids = l1.getChildren() + self.assertEqual({l2}, kids) + kids = l2.getChildren() + self.assertEqual(set(), kids) class DerivedLogRecord(logging.LogRecord): pass @@ -4261,6 +4304,14 @@ class NoMsecFormatter(logging.Formatter): f.converter = time.gmtime self.assertEqual(f.formatTime(r), '21/04/1993 08:03:00') + def test_issue_89047(self): + f = logging.Formatter(fmt='{asctime}.{msecs:03.0f} {message}', style='{', datefmt="%Y-%m-%d %H:%M:%S") + for i in range(2500): + time.sleep(0.0004) + r = logging.makeLogRecord({'msg': 'Message %d' % (i + 1)}) + s = f.format(r) + self.assertNotIn('.1000', s) + class TestBufferingFormatter(logging.BufferingFormatter): def formatHeader(self, records): diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index 97620258d82f6ba..ef38c362103fc6c 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -9,7 +9,7 @@ import pyexpat import xml.dom.minidom -from xml.dom.minidom import parse, Node, Document, parseString +from xml.dom.minidom import parse, Attr, Node, Document, parseString from xml.dom.minidom import getDOMImplementation from xml.parsers.expat import ExpatError @@ -77,6 +77,20 @@ def testParseFromTextFile(self): dom.unlink() self.confirm(isinstance(dom, Document)) + def testAttrModeSetsParamsAsAttrs(self): + attr = Attr("qName", "namespaceURI", "localName", "prefix") + self.assertEqual(attr.name, "qName") + self.assertEqual(attr.namespaceURI, "namespaceURI") + self.assertEqual(attr.prefix, "prefix") + self.assertEqual(attr.localName, "localName") + + def testAttrModeSetsNonOptionalAttrs(self): + attr = Attr("qName", "namespaceURI", None, "prefix") + self.assertEqual(attr.name, "qName") + self.assertEqual(attr.namespaceURI, "namespaceURI") + self.assertEqual(attr.prefix, "prefix") + self.assertEqual(attr.localName, attr.name) + def testGetElementsByTagName(self): dom = parse(tstfile) self.confirm(dom.getElementsByTagName("LI") == \ diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index c54dedb8b793a0a..9cd85e13634c2b4 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -14,6 +14,27 @@ _PyHASH_MODULUS = sys.hash_info.modulus _PyHASH_INF = sys.hash_info.inf + +class DummyIntegral(int): + """Dummy Integral class to test conversion of the Rational to float.""" + + def __mul__(self, other): + return DummyIntegral(super().__mul__(other)) + __rmul__ = __mul__ + + def __truediv__(self, other): + return NotImplemented + __rtruediv__ = __truediv__ + + @property + def numerator(self): + return DummyIntegral(self) + + @property + def denominator(self): + return DummyIntegral(1) + + class HashTest(unittest.TestCase): def check_equal_hash(self, x, y): # check both that x and y are equal and that their hashes are equal @@ -121,6 +142,13 @@ def test_fractions(self): self.assertEqual(hash(F(7*_PyHASH_MODULUS, 1)), 0) self.assertEqual(hash(F(-_PyHASH_MODULUS, 1)), 0) + # The numbers ABC doesn't enforce that the "true" division + # of integers produces a float. This tests that the + # Rational.__float__() method has required type conversions. + x = F(DummyIntegral(1), DummyIntegral(2), _normalize=False) + self.assertRaises(TypeError, lambda: x.numerator/x.denominator) + self.assertEqual(float(x), 0.5) + def test_hash_normalization(self): # Test for a bug encountered while changing long_hash. # diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index e03c42c2f823dc8..5f7e50d4e757af8 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -4,7 +4,7 @@ import textwrap import unittest -from test.support.bytecode_helper import BytecodeTestCase +from test.support.bytecode_helper import BytecodeTestCase, CfgOptimizationTestCase def compile_pattern_with_fast_locals(pattern): @@ -77,9 +77,8 @@ def unot(x): if not x == 2: del x self.assertNotInBytecode(unot, 'UNARY_NOT') - self.assertNotInBytecode(unot, 'POP_JUMP_FORWARD_IF_FALSE') - self.assertNotInBytecode(unot, 'POP_JUMP_BACKWARD_IF_FALSE') - self.assertInBytecode(unot, 'POP_JUMP_FORWARD_IF_TRUE') + self.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE') + self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE') self.check_lnotab(unot) def test_elim_inversion_of_is_or_in(self): @@ -409,7 +408,7 @@ def f(a, b, c): self.check_lnotab(f) self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP') self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP') - self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_FALSE') + self.assertInBytecode(f, 'POP_JUMP_IF_FALSE') # JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump def f(a, b, c): return ((a or b) @@ -418,7 +417,7 @@ def f(a, b, c): self.check_lnotab(f) self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP') self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP') - self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_TRUE') + self.assertInBytecode(f, 'POP_JUMP_IF_TRUE') def test_elim_jump_to_uncond_jump4(self): def f(): @@ -864,5 +863,81 @@ def trace(frame, event, arg): self.assertNotInBytecode(f, "LOAD_FAST_CHECK") +class DirectiCfgOptimizerTests(CfgOptimizationTestCase): + + def cfg_optimization_test(self, insts, expected_insts, + consts=None, expected_consts=None): + if expected_consts is None: + expected_consts = consts + opt_insts, opt_consts = self.get_optimized(insts, consts) + self.compareInstructions(opt_insts, expected_insts) + self.assertEqual(opt_consts, expected_consts) + + def test_conditional_jump_forward_non_const_condition(self): + insts = [ + ('LOAD_NAME', 1, 11), + ('POP_JUMP_IF_TRUE', lbl := self.Label(), 12), + ('LOAD_CONST', 2, 13), + lbl, + ('LOAD_CONST', 3, 14), + ] + expected = [ + ('LOAD_NAME', '1', 11), + ('POP_JUMP_IF_TRUE', lbl := self.Label(), 12), + ('LOAD_CONST', '2', 13), + lbl, + ('LOAD_CONST', '3', 14) + ] + self.cfg_optimization_test(insts, expected, consts=list(range(5))) + + def test_conditional_jump_forward_const_condition(self): + # The unreachable branch of the jump is removed, the jump + # becomes redundant and is replaced by a NOP (for the lineno) + + insts = [ + ('LOAD_CONST', 3, 11), + ('POP_JUMP_IF_TRUE', lbl := self.Label(), 12), + ('LOAD_CONST', 2, 13), + lbl, + ('LOAD_CONST', 3, 14), + ] + expected = [ + ('NOP', None, 11), + ('NOP', None, 12), + ('LOAD_CONST', '3', 14) + ] + self.cfg_optimization_test(insts, expected, consts=list(range(5))) + + def test_conditional_jump_backward_non_const_condition(self): + insts = [ + lbl1 := self.Label(), + ('LOAD_NAME', 1, 11), + ('POP_JUMP_IF_TRUE', lbl1, 12), + ('LOAD_CONST', 2, 13), + ] + expected = [ + lbl := self.Label(), + ('LOAD_NAME', '1', 11), + ('POP_JUMP_IF_TRUE', lbl, 12), + ('LOAD_CONST', '2', 13) + ] + self.cfg_optimization_test(insts, expected, consts=list(range(5))) + + def test_conditional_jump_backward_const_condition(self): + # The unreachable branch of the jump is removed + insts = [ + lbl1 := self.Label(), + ('LOAD_CONST', 1, 11), + ('POP_JUMP_IF_TRUE', lbl1, 12), + ('LOAD_CONST', 2, 13), + ] + expected = [ + lbl := self.Label(), + ('NOP', None, 11), + ('JUMP', lbl, 12) + ] + self.cfg_optimization_test(insts, expected, consts=list(range(5))) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py new file mode 100644 index 000000000000000..2b977d78d393248 --- /dev/null +++ b/Lib/test/test_perf_profiler.py @@ -0,0 +1,348 @@ +import unittest +import subprocess +import sys +import sysconfig +import os +import pathlib +from test import support +from test.support.script_helper import ( + make_script, + assert_python_failure, + assert_python_ok, +) +from test.support.os_helper import temp_dir + + +if not support.has_subprocess_support: + raise unittest.SkipTest("test module requires subprocess") + + +def supports_trampoline_profiling(): + perf_trampoline = sysconfig.get_config_var("PY_HAVE_PERF_TRAMPOLINE") + if not perf_trampoline: + return False + return int(perf_trampoline) == 1 + + +if not supports_trampoline_profiling(): + raise unittest.SkipTest("perf trampoline profiling not supported") + + +class TestPerfTrampoline(unittest.TestCase): + def setUp(self): + super().setUp() + self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map")) + + def tearDown(self) -> None: + super().tearDown() + files_to_delete = ( + set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files + ) + for file in files_to_delete: + file.unlink() + + def test_trampoline_works(self): + code = """if 1: + def foo(): + pass + + def bar(): + foo() + + def baz(): + bar() + + baz() + """ + with temp_dir() as script_dir: + script = make_script(script_dir, "perftest", code) + with subprocess.Popen( + [sys.executable, "-Xperf", script], + text=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) as process: + stdout, stderr = process.communicate() + + self.assertEqual(stderr, "") + self.assertEqual(stdout, "") + + perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map") + self.assertTrue(perf_file.exists()) + perf_file_contents = perf_file.read_text() + self.assertIn(f"py::foo:{script}", perf_file_contents) + self.assertIn(f"py::bar:{script}", perf_file_contents) + self.assertIn(f"py::baz:{script}", perf_file_contents) + + def test_trampoline_works_with_forks(self): + code = """if 1: + import os, sys + + def foo_fork(): + pass + + def bar_fork(): + foo_fork() + + def baz_fork(): + bar_fork() + + def foo(): + pid = os.fork() + if pid == 0: + print(os.getpid()) + baz_fork() + else: + _, status = os.waitpid(-1, 0) + sys.exit(status) + + def bar(): + foo() + + def baz(): + bar() + + baz() + """ + with temp_dir() as script_dir: + script = make_script(script_dir, "perftest", code) + with subprocess.Popen( + [sys.executable, "-Xperf", script], + text=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) as process: + stdout, stderr = process.communicate() + + self.assertEqual(process.returncode, 0) + self.assertEqual(stderr, "") + child_pid = int(stdout.strip()) + perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map") + perf_child_file = pathlib.Path(f"/tmp/perf-{child_pid}.map") + self.assertTrue(perf_file.exists()) + self.assertTrue(perf_child_file.exists()) + + perf_file_contents = perf_file.read_text() + self.assertIn(f"py::foo:{script}", perf_file_contents) + self.assertIn(f"py::bar:{script}", perf_file_contents) + self.assertIn(f"py::baz:{script}", perf_file_contents) + + child_perf_file_contents = perf_child_file.read_text() + self.assertIn(f"py::foo_fork:{script}", child_perf_file_contents) + self.assertIn(f"py::bar_fork:{script}", child_perf_file_contents) + self.assertIn(f"py::baz_fork:{script}", child_perf_file_contents) + + def test_sys_api(self): + code = """if 1: + import sys + def foo(): + pass + + def spam(): + pass + + def bar(): + sys.deactivate_stack_trampoline() + foo() + sys.activate_stack_trampoline("perf") + spam() + + def baz(): + bar() + + sys.activate_stack_trampoline("perf") + baz() + """ + with temp_dir() as script_dir: + script = make_script(script_dir, "perftest", code) + with subprocess.Popen( + [sys.executable, script], + text=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) as process: + stdout, stderr = process.communicate() + + self.assertEqual(stderr, "") + self.assertEqual(stdout, "") + + perf_file = pathlib.Path(f"/tmp/perf-{process.pid}.map") + self.assertTrue(perf_file.exists()) + perf_file_contents = perf_file.read_text() + self.assertNotIn(f"py::foo:{script}", perf_file_contents) + self.assertIn(f"py::spam:{script}", perf_file_contents) + self.assertIn(f"py::bar:{script}", perf_file_contents) + self.assertIn(f"py::baz:{script}", perf_file_contents) + + def test_sys_api_with_existing_trampoline(self): + code = """if 1: + import sys + sys.activate_stack_trampoline("perf") + sys.activate_stack_trampoline("perf") + """ + assert_python_ok("-c", code) + + def test_sys_api_with_invalid_trampoline(self): + code = """if 1: + import sys + sys.activate_stack_trampoline("invalid") + """ + rc, out, err = assert_python_failure("-c", code) + self.assertIn("invalid backend: invalid", err.decode()) + + def test_sys_api_get_status(self): + code = """if 1: + import sys + sys.activate_stack_trampoline("perf") + assert sys.is_stack_trampoline_active() is True + sys.deactivate_stack_trampoline() + assert sys.is_stack_trampoline_active() is False + """ + assert_python_ok("-c", code) + + +def is_unwinding_reliable(): + cflags = sysconfig.get_config_var("PY_CORE_CFLAGS") + if not cflags: + return False + return "no-omit-frame-pointer" in cflags + + +def perf_command_works(): + try: + cmd = ["perf", "--help"] + stdout = subprocess.check_output(cmd, text=True) + except (subprocess.SubprocessError, OSError): + return False + + # perf version does not return a version number on Fedora. Use presence + # of "perf.data" in help as indicator that it's perf from Linux tools. + if "perf.data" not in stdout: + return False + + # Check that we can run a simple perf run + with temp_dir() as script_dir: + try: + output_file = script_dir + "/perf_output.perf" + cmd = ( + "perf", + "record", + "-g", + "--call-graph=fp", + "-o", + output_file, + "--", + sys.executable, + "-c", + 'print("hello")', + ) + stdout = subprocess.check_output( + cmd, cwd=script_dir, text=True, stderr=subprocess.STDOUT + ) + except (subprocess.SubprocessError, OSError): + return False + + if "hello" not in stdout: + return False + + return True + + +def run_perf(cwd, *args, **env_vars): + if env_vars: + env = os.environ.copy() + env.update(env_vars) + else: + env = None + output_file = cwd + "/perf_output.perf" + base_cmd = ("perf", "record", "-g", "--call-graph=fp", "-o", output_file, "--") + proc = subprocess.run( + base_cmd + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + ) + if proc.returncode: + print(proc.stderr) + raise ValueError(f"Perf failed with return code {proc.returncode}") + + base_cmd = ("perf", "script") + proc = subprocess.run( + ("perf", "script", "-i", output_file), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + check=True, + ) + return proc.stdout.decode("utf-8", "replace"), proc.stderr.decode( + "utf-8", "replace" + ) + + +@unittest.skipUnless(perf_command_works(), "perf command doesn't work") +@unittest.skipUnless(is_unwinding_reliable(), "Unwinding is unreliable") +@support.skip_if_sanitizer(address=True, memory=True, ub=True) +class TestPerfProfiler(unittest.TestCase): + def setUp(self): + super().setUp() + self.perf_files = set(pathlib.Path("/tmp/").glob("perf-*.map")) + + def tearDown(self) -> None: + super().tearDown() + files_to_delete = ( + set(pathlib.Path("/tmp/").glob("perf-*.map")) - self.perf_files + ) + for file in files_to_delete: + file.unlink() + + def test_python_calls_appear_in_the_stack_if_perf_activated(self): + with temp_dir() as script_dir: + code = """if 1: + def foo(n): + x = 0 + for i in range(n): + x += i + + def bar(n): + foo(n) + + def baz(n): + bar(n) + + baz(10000000) + """ + script = make_script(script_dir, "perftest", code) + stdout, stderr = run_perf(script_dir, sys.executable, "-Xperf", script) + self.assertEqual(stderr, "") + + self.assertIn(f"py::foo:{script}", stdout) + self.assertIn(f"py::bar:{script}", stdout) + self.assertIn(f"py::baz:{script}", stdout) + + def test_python_calls_do_not_appear_in_the_stack_if_perf_activated(self): + with temp_dir() as script_dir: + code = """if 1: + def foo(n): + x = 0 + for i in range(n): + x += i + + def bar(n): + foo(n) + + def baz(n): + bar(n) + + baz(10000000) + """ + script = make_script(script_dir, "perftest", code) + stdout, stderr = run_perf(script_dir, sys.executable, script) + self.assertEqual(stderr, "") + + self.assertNotIn(f"py::foo:{script}", stdout) + self.assertNotIn(f"py::bar:{script}", stdout) + self.assertNotIn(f"py::baz:{script}", stdout) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 9b2cd201f3c2fe6..9c03a89fd57d074 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -229,6 +229,14 @@ def test_uname(self): self.assertEqual(res[-1], res.processor) self.assertEqual(len(res), 6) + @unittest.skipUnless(sys.platform.startswith('win'), "windows only test") + def test_uname_win32_without_wmi(self): + def raises_oserror(*a): + raise OSError() + + with support.swap_attr(platform, '_wmi_query', raises_oserror): + self.test_uname() + def test_uname_cast_to_tuple(self): res = platform.uname() expected = ( @@ -289,20 +297,27 @@ def test_uname_win32_ARCHITEW6432(self): # on 64 bit Windows: if PROCESSOR_ARCHITEW6432 exists we should be # using it, per # http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx - try: + + # We also need to suppress WMI checks, as those are reliable and + # overrule the environment variables + def raises_oserror(*a): + raise OSError() + + with support.swap_attr(platform, '_wmi_query', raises_oserror): with os_helper.EnvironmentVarGuard() as environ: - if 'PROCESSOR_ARCHITEW6432' in environ: - del environ['PROCESSOR_ARCHITEW6432'] - environ['PROCESSOR_ARCHITECTURE'] = 'foo' - platform._uname_cache = None - system, node, release, version, machine, processor = platform.uname() - self.assertEqual(machine, 'foo') - environ['PROCESSOR_ARCHITEW6432'] = 'bar' - platform._uname_cache = None - system, node, release, version, machine, processor = platform.uname() - self.assertEqual(machine, 'bar') - finally: - platform._uname_cache = None + try: + if 'PROCESSOR_ARCHITEW6432' in environ: + del environ['PROCESSOR_ARCHITEW6432'] + environ['PROCESSOR_ARCHITECTURE'] = 'foo' + platform._uname_cache = None + system, node, release, version, machine, processor = platform.uname() + self.assertEqual(machine, 'foo') + environ['PROCESSOR_ARCHITEW6432'] = 'bar' + platform._uname_cache = None + system, node, release, version, machine, processor = platform.uname() + self.assertEqual(machine, 'bar') + finally: + platform._uname_cache = None def test_java_ver(self): res = platform.java_ver() diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py index b2de4e8397d6ad4..23453e340159db9 100644 --- a/Lib/test/test_pyclbr.py +++ b/Lib/test/test_pyclbr.py @@ -229,7 +229,7 @@ def test_others(self): cm( 'pdb', # pyclbr does not handle elegantly `typing` or properties - ignore=('Union', 'ModuleTarget', 'ScriptTarget'), + ignore=('Union', '_ModuleTarget', '_ScriptTarget'), ) cm('pydoc', ignore=('input', 'output',)) # properties diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index f1b57fc40710326..d808f3f62b96dca 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1398,10 +1398,21 @@ def testStringToIPv6(self): def testSockName(self): # Testing getsockname() - port = socket_helper.find_unused_port() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.addCleanup(sock.close) - sock.bind(("0.0.0.0", port)) + + # Since find_unused_port() is inherently subject to race conditions, we + # call it a couple times if necessary. + for i in itertools.count(): + port = socket_helper.find_unused_port() + try: + sock.bind(("0.0.0.0", port)) + except OSError as e: + if e.errno != errno.EADDRINUSE or i == 5: + raise + else: + break + name = sock.getsockname() # XXX(nnorwitz): http://tinyurl.com/os5jz seems to indicate # it reasonable to get the host's addr in addition to 0.0.0.0. diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index e1b0de2adef6215..cfc4b13f18f330c 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -1,4 +1,4 @@ -# -*- coding: koi8-r -*- +# -*- coding: utf-8 -*- import unittest from test.support import script_helper, captured_stdout, requires_subprocess @@ -12,15 +12,14 @@ class MiscSourceEncodingTest(unittest.TestCase): - def test_pep263(self): - self.assertEqual( - "ðÉÔÏÎ".encode("utf-8"), - b'\xd0\x9f\xd0\xb8\xd1\x82\xd0\xbe\xd0\xbd' - ) - self.assertEqual( - "\ð".encode("utf-8"), - b'\\\xd0\x9f' - ) + def test_import_encoded_module(self): + from test.encoded_modules import test_strings + # Make sure we're actually testing something + self.assertGreaterEqual(len(test_strings), 1) + for modname, encoding, teststr in test_strings: + mod = importlib.import_module('test.encoded_modules.' + 'module_' + modname) + self.assertEqual(teststr, mod.test) def test_compilestring(self): # see #1882 @@ -148,6 +147,18 @@ def test_error_from_string(self): self.assertTrue(c.exception.args[0].startswith(expected), msg=c.exception.args[0]) + def test_file_parse_error_multiline(self): + # gh96611: + with open(TESTFN, "wb") as fd: + fd.write(b'print("""\n\xb1""")\n') + + try: + retcode, stdout, stderr = script_helper.assert_python_failure(TESTFN) + + self.assertGreater(retcode, 0) + self.assertIn(b"Non-UTF-8 code starting with '\\xb1'", stderr) + finally: + os.unlink(TESTFN) class AbstractSourceEncodingTest: @@ -236,53 +247,60 @@ def test_invalid_utf8(self): # test it is to write actual files to disk. # Each example is put inside a string at the top of the file so - # it's an otherwise valid Python source file. - template = b'"%s"\n' + # it's an otherwise valid Python source file. Put some newlines + # beforehand so we can assert that the error is reported on the + # correct line. + template = b'\n\n\n"%s"\n' - with tempfile.TemporaryDirectory() as tmpd: - fn = os.path.join(tmpd, 'test.py') + fn = TESTFN + self.addCleanup(unlink, fn) + + def check(content): + with open(fn, 'wb') as fp: + fp.write(template % content) + rc, stdout, stderr = script_helper.assert_python_failure(fn) + # We want to assert that the python subprocess failed gracefully, + # not via a signal. + self.assertGreaterEqual(rc, 1) + self.assertIn(b"Non-UTF-8 code starting with", stderr) + self.assertIn(b"on line 4", stderr) + + # continuation bytes in a sequence of 2, 3, or 4 bytes + continuation_bytes = [bytes([x]) for x in range(0x80, 0xC0)] + # start bytes of a 2-byte sequence equivalent to code points < 0x7F + invalid_2B_seq_start_bytes = [bytes([x]) for x in range(0xC0, 0xC2)] + # start bytes of a 4-byte sequence equivalent to code points > 0x10FFFF + invalid_4B_seq_start_bytes = [bytes([x]) for x in range(0xF5, 0xF8)] + invalid_start_bytes = ( + continuation_bytes + invalid_2B_seq_start_bytes + + invalid_4B_seq_start_bytes + [bytes([x]) for x in range(0xF7, 0x100)] + ) - def check(content): - with open(fn, 'wb') as fp: - fp.write(template % content) - script_helper.assert_python_failure(fn) - - # continuation bytes in a sequence of 2, 3, or 4 bytes - continuation_bytes = [bytes([x]) for x in range(0x80, 0xC0)] - # start bytes of a 2-byte sequence equivalent to code points < 0x7F - invalid_2B_seq_start_bytes = [bytes([x]) for x in range(0xC0, 0xC2)] - # start bytes of a 4-byte sequence equivalent to code points > 0x10FFFF - invalid_4B_seq_start_bytes = [bytes([x]) for x in range(0xF5, 0xF8)] - invalid_start_bytes = ( - continuation_bytes + invalid_2B_seq_start_bytes + - invalid_4B_seq_start_bytes + [bytes([x]) for x in range(0xF7, 0x100)] - ) - - for byte in invalid_start_bytes: - check(byte) - - for sb in invalid_2B_seq_start_bytes: - for cb in continuation_bytes: - check(sb + cb) - - for sb in invalid_4B_seq_start_bytes: - for cb1 in continuation_bytes[:3]: - for cb3 in continuation_bytes[:3]: - check(sb+cb1+b'\x80'+cb3) - - for cb in [bytes([x]) for x in range(0x80, 0xA0)]: - check(b'\xE0'+cb+b'\x80') - check(b'\xE0'+cb+b'\xBF') - # surrogates - for cb in [bytes([x]) for x in range(0xA0, 0xC0)]: - check(b'\xED'+cb+b'\x80') - check(b'\xED'+cb+b'\xBF') - for cb in [bytes([x]) for x in range(0x80, 0x90)]: - check(b'\xF0'+cb+b'\x80\x80') - check(b'\xF0'+cb+b'\xBF\xBF') - for cb in [bytes([x]) for x in range(0x90, 0xC0)]: - check(b'\xF4'+cb+b'\x80\x80') - check(b'\xF4'+cb+b'\xBF\xBF') + for byte in invalid_start_bytes: + check(byte) + + for sb in invalid_2B_seq_start_bytes: + for cb in continuation_bytes: + check(sb + cb) + + for sb in invalid_4B_seq_start_bytes: + for cb1 in continuation_bytes[:3]: + for cb3 in continuation_bytes[:3]: + check(sb+cb1+b'\x80'+cb3) + + for cb in [bytes([x]) for x in range(0x80, 0xA0)]: + check(b'\xE0'+cb+b'\x80') + check(b'\xE0'+cb+b'\xBF') + # surrogates + for cb in [bytes([x]) for x in range(0xA0, 0xC0)]: + check(b'\xED'+cb+b'\x80') + check(b'\xED'+cb+b'\xBF') + for cb in [bytes([x]) for x in range(0x80, 0x90)]: + check(b'\xF0'+cb+b'\x80\x80') + check(b'\xF0'+cb+b'\xBF\xBF') + for cb in [bytes([x]) for x in range(0x90, 0xC0)]: + check(b'\xF4'+cb+b'\x80\x80') + check(b'\xF4'+cb+b'\xBF\xBF') class BytesSourceEncodingTest(AbstractSourceEncodingTest, unittest.TestCase): diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index bf85525dd129a55..05ce79f126590a7 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2565,6 +2565,22 @@ def test_different_scales(self): self.assertAlmostEqual(statistics.covariance(x, y), 0.1) + def test_correlation_spearman(self): + # https://statistics.laerd.com/statistical-guides/spearmans-rank-order-correlation-statistical-guide-2.php + # Compare with: + # >>> import scipy.stats.mstats + # >>> scipy.stats.mstats.spearmanr(reading, mathematics) + # SpearmanrResult(correlation=0.6686960980480712, pvalue=0.03450954165178532) + # And Wolfram Alpha gives: 0.668696 + # https://www.wolframalpha.com/input?i=SpearmanRho%5B%7B56%2C+75%2C+45%2C+71%2C+61%2C+64%2C+58%2C+80%2C+76%2C+61%7D%2C+%7B66%2C+70%2C+40%2C+60%2C+65%2C+56%2C+59%2C+77%2C+67%2C+63%7D%5D + reading = [56, 75, 45, 71, 61, 64, 58, 80, 76, 61] + mathematics = [66, 70, 40, 60, 65, 56, 59, 77, 67, 63] + self.assertAlmostEqual(statistics.correlation(reading, mathematics, method='ranked'), + 0.6686960980480712) + + with self.assertRaises(ValueError): + statistics.correlation(reading, mathematics, method='bad_method') + class TestLinearRegression(unittest.TestCase): def test_constant_input_error(self): diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 78da09d6abc0f97..41482734872e06b 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -550,11 +550,17 @@ def test_attributes(self): self.assertIsInstance(sys.executable, str) self.assertEqual(len(sys.float_info), 11) self.assertEqual(sys.float_info.radix, 2) - self.assertEqual(len(sys.int_info), 2) + self.assertEqual(len(sys.int_info), 4) self.assertTrue(sys.int_info.bits_per_digit % 5 == 0) self.assertTrue(sys.int_info.sizeof_digit >= 1) + self.assertGreaterEqual(sys.int_info.default_max_str_digits, 500) + self.assertGreaterEqual(sys.int_info.str_digits_check_threshold, 100) + self.assertGreater(sys.int_info.default_max_str_digits, + sys.int_info.str_digits_check_threshold) self.assertEqual(type(sys.int_info.bits_per_digit), int) self.assertEqual(type(sys.int_info.sizeof_digit), int) + self.assertIsInstance(sys.int_info.default_max_str_digits, int) + self.assertIsInstance(sys.int_info.str_digits_check_threshold, int) self.assertIsInstance(sys.hexversion, int) self.assertEqual(len(sys.hash_info), 9) @@ -628,6 +634,14 @@ def test_thread_info(self): self.assertEqual(len(info), 3) self.assertIn(info.name, ('nt', 'pthread', 'pthread-stubs', 'solaris', None)) self.assertIn(info.lock, ('semaphore', 'mutex+cond', None)) + if sys.platform.startswith(("linux", "freebsd")): + self.assertEqual(info.name, "pthread") + elif sys.platform == "win32": + self.assertEqual(info.name, "nt") + elif sys.platform == "emscripten": + self.assertIn(info.name, {"pthread", "pthread-stubs"}) + elif sys.platform == "wasi": + self.assertEqual(info.name, "pthread-stubs") @unittest.skipUnless(support.is_emscripten, "only available on Emscripten") def test_emscripten_info(self): @@ -669,7 +683,7 @@ def test_sys_flags(self): "dont_write_bytecode", "no_user_site", "no_site", "ignore_environment", "verbose", "bytes_warning", "quiet", "hash_randomization", "isolated", "dev_mode", "utf8_mode", - "warn_default_encoding", "safe_path") + "warn_default_encoding", "safe_path", "int_max_str_digits") for attr in attrs: self.assertTrue(hasattr(sys.flags, attr), attr) attr_type = bool if attr in ("dev_mode", "safe_path") else int diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index dcd27697bb48398..c6649962331464a 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -853,6 +853,7 @@ def callback(): callback() finally: sys.settrace(old_trace) + threading.settrace(old_trace) def test_gettrace(self): def noop_trace(frame, event, arg): @@ -866,6 +867,35 @@ def noop_trace(frame, event, arg): finally: threading.settrace(old_trace) + def test_gettrace_all_threads(self): + def fn(*args): pass + old_trace = threading.gettrace() + first_check = threading.Event() + second_check = threading.Event() + + trace_funcs = [] + def checker(): + trace_funcs.append(sys.gettrace()) + first_check.set() + second_check.wait() + trace_funcs.append(sys.gettrace()) + + try: + t = threading.Thread(target=checker) + t.start() + first_check.wait() + threading.settrace_all_threads(fn) + second_check.set() + t.join() + self.assertEqual(trace_funcs, [None, fn]) + self.assertEqual(threading.gettrace(), fn) + self.assertEqual(sys.gettrace(), fn) + finally: + threading.settrace_all_threads(old_trace) + + self.assertEqual(threading.gettrace(), old_trace) + self.assertEqual(sys.gettrace(), old_trace) + def test_getprofile(self): def fn(*args): pass old_profile = threading.getprofile() @@ -875,6 +905,35 @@ def fn(*args): pass finally: threading.setprofile(old_profile) + def test_getprofile_all_threads(self): + def fn(*args): pass + old_profile = threading.getprofile() + first_check = threading.Event() + second_check = threading.Event() + + profile_funcs = [] + def checker(): + profile_funcs.append(sys.getprofile()) + first_check.set() + second_check.wait() + profile_funcs.append(sys.getprofile()) + + try: + t = threading.Thread(target=checker) + t.start() + first_check.wait() + threading.setprofile_all_threads(fn) + second_check.set() + t.join() + self.assertEqual(profile_funcs, [None, fn]) + self.assertEqual(threading.getprofile(), fn) + self.assertEqual(sys.getprofile(), fn) + finally: + threading.setprofile_all_threads(old_profile) + + self.assertEqual(threading.getprofile(), old_profile) + self.assertEqual(sys.getprofile(), old_profile) + @cpython_only def test_shutdown_locks(self): for daemon in (False, True): diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index d2a5ede61e3ff1e..94bcee302fe7303 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -360,6 +360,20 @@ def test_fork(self): else: support.wait_process(pid, exitcode=0) + def test_no_incomplete_frames(self): + tracemalloc.stop() + tracemalloc.start(8) + + def f(x): + def g(): + return x + return g + + obj = f(0).__closure__[0] + traceback = tracemalloc.get_object_traceback(obj) + self.assertIn("test_tracemalloc", traceback[-1].filename) + self.assertNotIn("test_tracemalloc", traceback[-2].filename) + class TestSnapshot(unittest.TestCase): maxDiff = 4000 diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 3f4101485c6e08b..d68c3259699598d 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -113,6 +113,12 @@ def test_any_instance_type_error(self): def test_repr(self): self.assertEqual(repr(Any), 'typing.Any') + class Sub(Any): pass + self.assertEqual( + repr(Sub), + ".Sub'>", + ) + def test_errors(self): with self.assertRaises(TypeError): issubclass(42, Any) @@ -596,6 +602,7 @@ class GenericAliasSubstitutionTests(BaseTestCase): def test_one_parameter(self): T = TypeVar('T') Ts = TypeVarTuple('Ts') + Ts2 = TypeVarTuple('Ts2') class C(Generic[T]): pass @@ -621,6 +628,8 @@ class C(Generic[T]): pass # Should definitely raise TypeError: list only takes one argument. ('list[T, *tuple_type[int, ...]]', '[int]', 'list[int, *tuple_type[int, ...]]'), ('List[T, *tuple_type[int, ...]]', '[int]', 'TypeError'), + # Should raise, because more than one `TypeVarTuple` is not supported. + ('generic[*Ts, *Ts2]', '[int]', 'TypeError'), ] for alias_template, args_template, expected_template in tests: @@ -4382,6 +4391,20 @@ def blah(): blah() + def test_overload_on_compiled_functions(self): + with patch("typing._overload_registry", + defaultdict(lambda: defaultdict(dict))): + # The registry starts out empty: + self.assertEqual(typing._overload_registry, {}) + + # This should just not fail: + overload(sum) + overload(print) + + # No overloads are recorded (but, it still has a side-effect): + self.assertEqual(typing.get_overloads(sum), []) + self.assertEqual(typing.get_overloads(print), []) + def set_up_overloads(self): def blah(): pass @@ -4416,6 +4439,9 @@ def some_other_func(): pass other_overload = some_other_func def some_other_func(): pass self.assertEqual(list(get_overloads(some_other_func)), [other_overload]) + # Unrelated function still has no overloads: + def not_overloaded(): pass + self.assertEqual(list(get_overloads(not_overloaded)), []) # Make sure that after we clear all overloads, the registry is # completely empty. @@ -7131,6 +7157,7 @@ def test_special_attrs(self): typing.Self: 'Self', # Subscribed special forms typing.Annotated[Any, "Annotation"]: 'Annotated', + typing.Annotated[int, 'Annotation']: 'Annotated', typing.ClassVar[Any]: 'ClassVar', typing.Concatenate[Any, SpecialAttrsP]: 'Concatenate', typing.Final[Any]: 'Final', diff --git a/Lib/test/test_unicodedata.py b/Lib/test/test_unicodedata.py index 3514697f548e651..42c02eee58b4449 100644 --- a/Lib/test/test_unicodedata.py +++ b/Lib/test/test_unicodedata.py @@ -71,7 +71,7 @@ class UnicodeFunctionsTest(UnicodeDatabaseTest): # Update this if the database changes. Make sure to do a full rebuild # (e.g. 'make distclean && make') to get the correct checksum. - expectedchecksum = '98d602e1f69d5c5bb8a5910c40bbbad4e18e8370' + expectedchecksum = '4975f3ec0acd4a62465d18c9bf8519b1964181f6' @requires_resource('cpu') def test_function_checksum(self): @@ -90,6 +90,7 @@ def test_function_checksum(self): self.db.decomposition(char), str(self.db.mirrored(char)), str(self.db.combining(char)), + unicodedata.east_asian_width(char), ] h.update(''.join(data).encode("ascii")) result = h.hexdigest() @@ -220,6 +221,23 @@ def test_east_asian_width(self): self.assertEqual(eaw('\u2010'), 'A') self.assertEqual(eaw('\U00020000'), 'W') + def test_east_asian_width_unassigned(self): + eaw = self.db.east_asian_width + # unassigned + for char in '\u0530\u0ece\u10c6\u20fc\uaaca\U000107bd\U000115f2': + self.assertEqual(eaw(char), 'N') + self.assertIs(self.db.name(char, None), None) + + # unassigned but reserved for CJK + for char in '\uFA6E\uFADA\U0002A6E0\U0002FA20\U0003134B\U0003FFFD': + self.assertEqual(eaw(char), 'W') + self.assertIs(self.db.name(char, None), None) + + # private use areas + for char in '\uE000\uF800\U000F0000\U000FFFEE\U00100000\U0010FFF0': + self.assertEqual(eaw(char), 'A') + self.assertIs(self.db.name(char, None), None) + def test_east_asian_width_9_0_changes(self): self.assertEqual(self.db.ucd_3_2_0.east_asian_width('\u231a'), 'N') self.assertEqual(self.db.east_asian_width('\u231a'), 'W') diff --git a/Lib/test/test_unittest/test_async_case.py b/Lib/test/test_unittest/test_async_case.py index f59fc760d3812fc..d7d4dc91316c6c3 100644 --- a/Lib/test/test_unittest/test_async_case.py +++ b/Lib/test/test_unittest/test_async_case.py @@ -43,10 +43,10 @@ async def __aenter__(self): class TestAsyncCase(unittest.TestCase): maxDiff = None - def tearDown(self): + def setUp(self): # Ensure that IsolatedAsyncioTestCase instances are destroyed before # starting a new event loop - support.gc_collect() + self.addCleanup(support.gc_collect) def test_full_cycle(self): class Test(unittest.IsolatedAsyncioTestCase): @@ -151,6 +151,7 @@ async def on_cleanup(self): events = [] test = Test("test_func") + self.addCleanup(test._tearDownAsyncioRunner) try: test.debug() except MyException: @@ -186,6 +187,7 @@ async def on_cleanup(self): events = [] test = Test("test_func") + self.addCleanup(test._tearDownAsyncioRunner) try: test.debug() except MyException: @@ -221,6 +223,7 @@ async def on_cleanup(self): events = [] test = Test("test_func") + self.addCleanup(test._tearDownAsyncioRunner) try: test.debug() except MyException: @@ -262,6 +265,7 @@ async def on_cleanup2(self): events = [] test = Test("test_func") + self.addCleanup(test._tearDownAsyncioRunner) try: test.debug() except MyException: @@ -424,6 +428,7 @@ async def cleanup(self, fut): events = [] test = Test("test_func") + self.addCleanup(test._tearDownAsyncioRunner) try: test.debug() except MyException: diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 969aa16678f4935..f1f1dd5dc26be84 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -422,6 +422,12 @@ def test_invalid_fstring_backslash(self): def test_invalid_yield_from(self): self.check_invalid(ast.YieldFrom(value=None)) + def test_import_from_level_none(self): + tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')]) + self.assertEqual(ast.unparse(tree), "from mod import x") + tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')], level=None) + self.assertEqual(ast.unparse(tree), "from mod import x") + def test_docstrings(self): docstrings = ( 'this ends with double quote"', diff --git a/Lib/test/test_wmi.py b/Lib/test/test_wmi.py new file mode 100644 index 000000000000000..af2a453dcb5216f --- /dev/null +++ b/Lib/test/test_wmi.py @@ -0,0 +1,67 @@ +# Test the internal _wmi module on Windows +# This is used by the platform module, and potentially others + +import re +import sys +import unittest +from test.support import import_helper + + +# Do this first so test will be skipped if module doesn't exist +_wmi = import_helper.import_module('_wmi', required_on=['win']) + + +class WmiTests(unittest.TestCase): + def test_wmi_query_os_version(self): + r = _wmi.exec_query("SELECT Version FROM Win32_OperatingSystem").split("\0") + self.assertEqual(1, len(r)) + k, eq, v = r[0].partition("=") + self.assertEqual("=", eq, r[0]) + self.assertEqual("Version", k, r[0]) + # Best we can check for the version is that it's digits, dot, digits, anything + # Otherwise, we are likely checking the result of the query against itself + self.assertTrue(re.match(r"\d+\.\d+.+$", v), r[0]) + + def test_wmi_query_repeated(self): + # Repeated queries should not break + for _ in range(10): + self.test_wmi_query_os_version() + + def test_wmi_query_error(self): + # Invalid queries fail with OSError + try: + _wmi.exec_query("SELECT InvalidColumnName FROM InvalidTableName") + except OSError as ex: + if ex.winerror & 0xFFFFFFFF == 0x80041010: + # This is the expected error code. All others should fail the test + return + self.fail("Expected OSError") + + def test_wmi_query_repeated_error(self): + for _ in range(10): + self.test_wmi_query_error() + + def test_wmi_query_not_select(self): + # Queries other than SELECT are blocked to avoid potential exploits + with self.assertRaises(ValueError): + _wmi.exec_query("not select, just in case someone tries something") + + def test_wmi_query_overflow(self): + # Ensure very big queries fail + # Test multiple times to ensure consistency + for _ in range(2): + with self.assertRaises(OSError): + _wmi.exec_query("SELECT * FROM CIM_DataFile") + + def test_wmi_query_multiple_rows(self): + # Multiple instances should have an extra null separator + r = _wmi.exec_query("SELECT ProcessId FROM Win32_Process WHERE ProcessId < 1000") + self.assertFalse(r.startswith("\0"), r) + self.assertFalse(r.endswith("\0"), r) + it = iter(r.split("\0")) + try: + while True: + self.assertTrue(re.match(r"ProcessId=\d+", next(it))) + self.assertEqual("", next(it)) + except StopIteration: + pass diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 6c4601ddaddcbde..9ff5545f786a320 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -289,6 +289,16 @@ def test_load_extension_types(self): check('9876543210.0123456789', decimal.Decimal('9876543210.0123456789')) + def test_limit_int(self): + check = self.check_loads + maxdigits = 5000 + with support.adjust_int_max_str_digits(maxdigits): + s = '1' * (maxdigits + 1) + with self.assertRaises(ValueError): + check(f'{s}', None) + with self.assertRaises(ValueError): + check(f'{s}', None) + def test_get_host_info(self): # see bug #3613, this raised a TypeError transp = xmlrpc.client.Transport() diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 21257785159b37a..6f6f4bc26b0d407 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -124,8 +124,9 @@ def zip_test(self, f, compression, compresslevel=None): self.assertEqual(info.filename, nm) self.assertEqual(info.file_size, len(self.data)) - # Check that testzip doesn't raise an exception - zipfp.testzip() + # Check that testzip thinks the archive is ok + # (it returns None if all contents could be read properly) + self.assertIsNone(zipfp.testzip()) def test_basic(self): for f in get_files(self): @@ -748,8 +749,8 @@ def zip_test(self, f, compression): self.assertEqual(info.filename, nm) self.assertEqual(info.file_size, len(self.data)) - # Check that testzip doesn't raise an exception - zipfp.testzip() + # Check that testzip thinks the archive is valid + self.assertIsNone(zipfp.testzip()) def test_basic(self): for f in get_files(self): diff --git a/Lib/test/test_zipfile64.py b/Lib/test/test_zipfile64.py index 0947013afbc6ed1..be654a8478b04b7 100644 --- a/Lib/test/test_zipfile64.py +++ b/Lib/test/test_zipfile64.py @@ -32,10 +32,6 @@ def setUp(self): line_gen = ("Test of zipfile line %d." % i for i in range(1000000)) self.data = '\n'.join(line_gen).encode('ascii') - # And write it to a file. - with open(TESTFN, "wb") as fp: - fp.write(self.data) - def zipTest(self, f, compression): # Create the ZIP archive. with zipfile.ZipFile(f, "w", compression) as zipfp: @@ -67,6 +63,9 @@ def zipTest(self, f, compression): (num, filecount)), file=sys.__stdout__) sys.__stdout__.flush() + # Check that testzip thinks the archive is valid + self.assertIsNone(zipfp.testzip()) + def testStored(self): # Try the temp file first. If we do TESTFN2 first, then it hogs # gigabytes of disk space for the duration of the test. @@ -85,9 +84,7 @@ def testDeflated(self): self.zipTest(TESTFN2, zipfile.ZIP_DEFLATED) def tearDown(self): - for fname in TESTFN, TESTFN2: - if os.path.exists(fname): - os.remove(fname) + os_helper.unlink(TESTFN2) class OtherTests(unittest.TestCase): diff --git a/Lib/threading.py b/Lib/threading.py index e32ad1418d9dd78..d030e1243623f98 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -28,7 +28,8 @@ 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError', 'setprofile', 'settrace', 'local', 'stack_size', - 'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile'] + 'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile', + 'setprofile_all_threads','settrace_all_threads'] # Rename some stuff so "from threading import *" is safe _start_new_thread = _thread.start_new_thread @@ -60,11 +61,20 @@ def setprofile(func): The func will be passed to sys.setprofile() for each thread, before its run() method is called. - """ global _profile_hook _profile_hook = func +def setprofile_all_threads(func): + """Set a profile function for all threads started from the threading module + and all Python threads that are currently executing. + + The func will be passed to sys.setprofile() for each thread, before its + run() method is called. + """ + setprofile(func) + _sys._setprofileallthreads(func) + def getprofile(): """Get the profiler function as set by threading.setprofile().""" return _profile_hook @@ -74,11 +84,20 @@ def settrace(func): The func will be passed to sys.settrace() for each thread, before its run() method is called. - """ global _trace_hook _trace_hook = func +def settrace_all_threads(func): + """Set a trace function for all threads started from the threading module + and all Python threads that are currently executing. + + The func will be passed to sys.settrace() for each thread, before its run() + method is called. + """ + settrace(func) + _sys._settraceallthreads(func) + def gettrace(): """Get the trace function as set by threading.settrace().""" return _trace_hook @@ -243,18 +262,12 @@ def __init__(self, lock=None): # If the lock defines _release_save() and/or _acquire_restore(), # these override the default implementations (which just call # release() and acquire() on the lock). Ditto for _is_owned(). - try: + if hasattr(lock, '_release_save'): self._release_save = lock._release_save - except AttributeError: - pass - try: + if hasattr(lock, '_acquire_restore'): self._acquire_restore = lock._acquire_restore - except AttributeError: - pass - try: + if hasattr(lock, '_is_owned'): self._is_owned = lock._is_owned - except AttributeError: - pass self._waiters = _deque() def _at_fork_reinit(self): @@ -570,7 +583,7 @@ def is_set(self): def isSet(self): """Return true if and only if the internal flag is true. - This method is deprecated, use notify_all() instead. + This method is deprecated, use is_set() instead. """ import warnings diff --git a/Lib/typing.py b/Lib/typing.py index 43ef07e50cfefce..95bd61c7f8c61f4 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -493,7 +493,9 @@ def __instancecheck__(self, obj): return super().__instancecheck__(obj) def __repr__(self): - return "typing.Any" + if self is Any: + return "typing.Any" + return super().__repr__() # respect to subclasses class Any(metaclass=_AnyMeta): @@ -1074,7 +1076,7 @@ def __typing_subst__(self, arg): def __typing_prepare_subst__(self, alias, args): params = alias.__parameters__ typevartuple_index = params.index(self) - for param in enumerate(params[typevartuple_index + 1:]): + for param in params[typevartuple_index + 1:]: if isinstance(param, TypeVarTuple): raise TypeError(f"More than one TypeVarTuple parameter in {alias}") @@ -2099,7 +2101,7 @@ def __init__(self, origin, metadata): if isinstance(origin, _AnnotatedAlias): metadata = origin.__metadata__ + metadata origin = origin.__origin__ - super().__init__(origin, origin) + super().__init__(origin, origin, name='Annotated') self.__metadata__ = metadata def copy_with(self, params): @@ -2132,6 +2134,9 @@ def __getattr__(self, attr): return 'Annotated' return super().__getattr__(attr) + def __mro_entries__(self, bases): + return (self.__origin__,) + class Annotated: """Add context specific metadata to a type. diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py index 8b06fad06209460..3457e92e5da298f 100644 --- a/Lib/unittest/async_case.py +++ b/Lib/unittest/async_case.py @@ -79,6 +79,10 @@ async def enterAsyncContext(self, cm): return result def _callSetUp(self): + # Force loop to be initialized and set as the current loop + # so that setUp functions can use get_event_loop() and get the + # correct loop instance. + self._asyncioRunner.get_loop() self._asyncioTestContext.run(self.setUp) self._callAsync(self.asyncSetUp) @@ -116,10 +120,6 @@ def _setupAsyncioRunner(self): assert self._asyncioRunner is None, 'asyncio runner is already initialized' runner = asyncio.Runner(debug=True) self._asyncioRunner = runner - # Force loop to be initialized and set as the current loop - # so that setUp functions can use get_event_loop() and get the - # correct loop instance. - runner.get_loop() def _tearDownAsyncioRunner(self): runner = self._asyncioRunner diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index fd6d9f44c6268cc..f25c770068bdd1c 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -906,7 +906,7 @@ def quote_from_bytes(bs, safe='/'): if not bs.rstrip(_ALWAYS_SAFE_BYTES + safe): return bs.decode() quoter = _byte_quoter_factory(safe) - return ''.join([quoter(char) for char in bs]) + return ''.join(map(quoter, bs)) def urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus): diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py index d09ef5e7d0371ae..ef8a159833bbc07 100644 --- a/Lib/xml/dom/minidom.py +++ b/Lib/xml/dom/minidom.py @@ -358,6 +358,8 @@ def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, self._name = qName self.namespaceURI = namespaceURI self._prefix = prefix + if localName is not None: + self._localName = localName self.childNodes = NodeList() # Add the single child node that represents the value of the attr diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 981560082cab7af..b6465373c107d50 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -480,7 +480,7 @@ def FileHeader(self, zip64=None): def _encodeFilenameFlags(self): try: - return self.filename.encode('ascii'), self.flag_bits & ~_MASK_UTF_FILENAME + return self.filename.encode('ascii'), self.flag_bits except UnicodeEncodeError: return self.filename.encode('utf-8'), self.flag_bits | _MASK_UTF_FILENAME @@ -1468,7 +1468,10 @@ def printdir(self, file=None): file=file) def testzip(self): - """Read all the files and check the CRC.""" + """Read all the files and check the CRC. + + Return None if all files could be read successfully, or the name + of the offending file otherwise.""" chunk_size = 2 ** 20 for zinfo in self.filelist: try: diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index a1d31c423814b32..9fd87f3361fde9b 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,9 +246,10 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.1.1n", - url="https://www.openssl.org/source/openssl-1.1.1n.tar.gz", - checksum='2aad5635f9bb338bc2c6b7d19cbc9676', + name="OpenSSL 1.1.1q", + url="https://www.openssl.org/source/openssl-1.1.1q.tar.gz", + checksum='d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca', + patches=['openssl1.1.1q-pr-18719.patch'], buildrecipe=build_universal_openssl, configure=None, install=None, @@ -797,10 +798,16 @@ def verifyThirdPartyFile(url, checksum, fname): print("Downloading %s"%(name,)) downloadURL(url, fname) print("Archive for %s stored as %s"%(name, fname)) + if len(checksum) == 32: + algo = 'md5' + elif len(checksum) == 64: + algo = 'sha256' + else: + raise ValueError(checksum) if os.system( - 'MD5=$(openssl md5 %s) ; test "${MD5##*= }" = "%s"' - % (shellQuote(fname), checksum) ): - fatal('MD5 checksum mismatch for file %s' % fname) + 'CHECKSUM=$(openssl %s %s) ; test "${CHECKSUM##*= }" = "%s"' + % (algo, shellQuote(fname), checksum) ): + fatal('%s checksum mismatch for file %s' % (algo, fname)) def build_universal_openssl(basedir, archList): """ diff --git a/Mac/BuildScript/openssl1.1.1q-pr-18719.patch b/Mac/BuildScript/openssl1.1.1q-pr-18719.patch new file mode 100644 index 000000000000000..6b4b1883159fd8b --- /dev/null +++ b/Mac/BuildScript/openssl1.1.1q-pr-18719.patch @@ -0,0 +1,17 @@ +https://github.com/openssl/openssl/commit/60f011f584d80447e86cae1d1bd3ae24bc13235b +This fixes a regression in 1.1.1q: + +test/v3ext.c:201:24: error: implicitly declaring library function 'memcmp' with type 'int (const void *, const void *, unsigned long)' [-Werror,-Wimplicit-function-declaration] + if (!TEST_true(memcmp(ip1->data, ip2->data, ip1->length) <= 0)) + +diff -Naur openssl-1.1.1q/test/v3ext.c openssl-1.1.1q-patched/test/v3ext.c +--- openssl-1.1.1q/test/v3ext.c 2022-07-05 09:08:33.000000000 +0000 ++++ openssl-1.1.1q-patched/test/v3ext.c 2022-09-05 16:54:45.740859256 +0000 +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include diff --git a/Makefile.pre.in b/Makefile.pre.in index c647853c223894f..107a7075ebf6a34 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -54,6 +54,8 @@ DTRACE= @DTRACE@ DFLAGS= @DFLAGS@ DTRACE_HEADERS= @DTRACE_HEADERS@ DTRACE_OBJS= @DTRACE_OBJS@ +DSYMUTIL= @DSYMUTIL@ +DSYMUTIL_PATH= @DSYMUTIL_PATH@ GNULD= @GNULD@ @@ -388,6 +390,7 @@ PYTHON_OBJS= \ Python/getcopyright.o \ Python/getplatform.o \ Python/getversion.o \ + Python/ceval_gil.o \ Python/hamt.o \ Python/hashtable.o \ Python/import.o \ @@ -475,7 +478,9 @@ OBJECT_OBJS= \ Objects/unicodeobject.o \ Objects/unicodectype.o \ Objects/unionobject.o \ - Objects/weakrefobject.o + Objects/weakrefobject.o \ + Objects/perf_trampoline.o \ + @PERF_TRAMPOLINE_OBJ@ DEEPFREEZE_OBJS = Python/deepfreeze/deepfreeze.o @@ -575,7 +580,7 @@ LIBEXPAT_HEADERS= \ # Default target all: @DEF_MAKE_ALL_RULE@ build_all: check-clean-src $(BUILDPYTHON) platform sharedmods \ - gdbhooks Programs/_testembed scripts checksharedmods + gdbhooks Programs/_testembed scripts checksharedmods rundsymutil build_wasm: check-clean-src $(BUILDPYTHON) platform sharedmods \ python-config checksharedmods @@ -640,6 +645,16 @@ profile-opt: profile-run-stamp -rm -f profile-clean-stamp $(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS_NODIST) $(PGO_PROF_USE_FLAG)" LDFLAGS_NODIST="$(LDFLAGS_NODIST)" +bolt-opt: @PREBOLT_RULE@ + rm -f *.fdata + @LLVM_BOLT@ ./$(BUILDPYTHON) -instrument -instrumentation-file-append-pid -instrumentation-file=$(abspath $(BUILDPYTHON).bolt) -o $(BUILDPYTHON).bolt_inst + ./$(BUILDPYTHON).bolt_inst $(PROFILE_TASK) || true + @MERGE_FDATA@ $(BUILDPYTHON).*.fdata > $(BUILDPYTHON).fdata + @LLVM_BOLT@ ./$(BUILDPYTHON) -o $(BUILDPYTHON).bolt -data=$(BUILDPYTHON).fdata -update-debug-sections -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions=3 -icf=1 -inline-all -split-eh -reorder-functions-use-hot-size -peepholes=all -jump-tables=aggressive -inline-ap -indirect-call-promotion=all -dyno-stats -use-gnu-stack -frame-opt=hot + rm -f *.fdata + rm -f $(BUILDPYTHON).bolt_inst + mv $(BUILDPYTHON).bolt $(BUILDPYTHON) + # Compile and run with gcov .PHONY=coverage coverage-lcov coverage-report coverage: @@ -793,10 +808,11 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) # wasm assets directory is relative to current build dir, e.g. "./usr/local". # --preload-file turns a relative asset path into an absolute path. +.PHONY: wasm_stdlib +wasm_stdlib: $(WASM_STDLIB) $(WASM_STDLIB): $(srcdir)/Lib/*.py $(srcdir)/Lib/*/*.py \ $(srcdir)/Tools/wasm/wasm_assets.py \ - Makefile pybuilddir.txt Modules/Setup.local \ - python.html python.worker.js + Makefile pybuilddir.txt Modules/Setup.local $(PYTHON_FOR_BUILD) $(srcdir)/Tools/wasm/wasm_assets.py \ --buildroot . --prefix $(prefix) @@ -893,6 +909,22 @@ sharedmods: $(SHAREDMODS) pybuilddir.txt checksharedmods: sharedmods $(PYTHON_FOR_BUILD_DEPS) $(BUILDPYTHON) @$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/check_extension_modules.py +rundsymutil: sharedmods $(PYTHON_FOR_BUILD_DEPS) $(BUILDPYTHON) + @if [ ! -z $(DSYMUTIL) ] ; then \ + echo $(DSYMUTIL_PATH) $(BUILDPYTHON); \ + $(DSYMUTIL_PATH) $(BUILDPYTHON); \ + if test -f $(LDLIBRARY); then \ + echo $(DSYMUTIL_PATH) $(LDLIBRARY); \ + $(DSYMUTIL_PATH) $(LDLIBRARY); \ + fi; \ + for mod in X $(SHAREDMODS); do \ + if test $$mod != X; then \ + echo $(DSYMUTIL_PATH) $$mod; \ + $(DSYMUTIL_PATH) $$mod; \ + fi; \ + done \ + fi + Modules/Setup.local: @# Create empty Setup.local when file was deleted by user echo "# Edit this file for local setup changes" > $@ @@ -1408,8 +1440,7 @@ regen-opcode-targets: $(srcdir)/Python/opcode_targets.h.new $(UPDATE_FILE) $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/opcode_targets.h.new -Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h \ - $(srcdir)/Python/condvar.h +Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/condvar.h Python/frozen.o: $(FROZEN_FILES_OUT) @@ -1744,9 +1775,14 @@ sharedinstall: $(DESTSHARED) all if test $$i != X; then \ echo $(INSTALL_SHARED) $$i $(DESTSHARED)/`basename $$i`; \ $(INSTALL_SHARED) $$i $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ + if test -d "$$i.dSYM"; then \ + echo $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ + $(DSYMUTIL_PATH) $(DESTDIR)$(DESTSHARED)/`basename $$i`; \ + fi; \ fi; \ done + $(DESTSHARED): @for i in $(DESTDIRS); \ do \ @@ -1807,6 +1843,23 @@ altbininstall: $(BUILDPYTHON) @FRAMEWORKPYTHONW@ -output $(DESTDIR)$(BINDIR)/python$(VERSION)-intel64$(EXE) \ $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE); \ fi + # Install macOS debug information (if available) + if test -d "$(BUILDPYTHON).dSYM"; then \ + echo $(DSYMUTIL_PATH) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \ + $(DSYMUTIL_PATH) $(DESTDIR)$(BINDIR)/python$(LDVERSION)$(EXE); \ + fi + if test "$(PYTHONFRAMEWORKDIR)" = "no-framework" ; then \ + if test -d "$(LDLIBRARY).dSYM"; then \ + echo $(DSYMUTIL_PATH) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \ + $(DSYMUTIL_PATH) $(DESTDIR)$(LIBDIR)/$(INSTSONAME); \ + fi \ + else \ + if test -d "$(LDLIBRARY).dSYM"; then \ + echo $(DSYMUTIL_PATH) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(INSTSONAME); \ + $(DSYMUTIL_PATH) $(DESTDIR)$(PYTHONFRAMEWORKPREFIX)/$(INSTSONAME); \ + fi \ + fi + bininstall: altbininstall if test ! -d $(DESTDIR)$(LIBPC); then \ @@ -2307,6 +2360,9 @@ config.status: $(srcdir)/configure .PRECIOUS: config.status $(BUILDPYTHON) Makefile Makefile.pre +Objects/asm_trampoline.o: $(srcdir)/Objects/asm_trampoline.S + $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< + # Some make's put the object file in the current directory .c.o: $(CC) -c $(PY_CORE_CFLAGS) -o $@ $< @@ -2381,6 +2437,7 @@ clean-retain-profile: pycremoval find . -name '*.[oa]' -exec rm -f {} ';' find . -name '*.s[ol]' -exec rm -f {} ';' find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' + find . -name '*.lto' -exec rm -f {} ';' find . -name '*.wasm' -exec rm -f {} ';' find . -name '*.lst' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true @@ -2497,7 +2554,7 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h # Declare targets that aren't real files .PHONY: all build_all build_wasm check-clean-src -.PHONY: sharedmods checksharedmods test quicktest +.PHONY: sharedmods checksharedmods test quicktest rundsymutil .PHONY: install altinstall sharedinstall bininstall altbininstall .PHONY: maninstall libinstall inclinstall libainstall .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure @@ -2511,6 +2568,8 @@ Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h ########################################################################## # Module dependencies and platform-specific files +MODULE_DEPS=$(PYTHON_HEADERS) Modules/config.c $(EXPORTSYMS) + MODULE_CMATH_DEPS=$(srcdir)/Modules/_math.h MODULE_MATH_DEPS=$(srcdir)/Modules/_math.h MODULE_PYEXPAT_DEPS=$(LIBEXPAT_HEADERS) @LIBEXPAT_INTERNAL@ diff --git a/Misc/ACKS b/Misc/ACKS index c1f570acaaf8e04..0edea9219d05ef4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1212,6 +1212,7 @@ Gideon Mitchell Tim Mitchell Zubin Mithra Florian Mladitsch +Kevin Modzelewski Doug Moen Jakub Molinski Juliette Monsel @@ -1418,6 +1419,7 @@ John Popplewell Matheus Vieira Portela Davin Potts Guillaume Pratte +Pedro Pregueiro Florian Preinstorfer Alex Prengère Amrit Prem @@ -1440,6 +1442,7 @@ Ram Rachum Jeffrey Rackauckas Jérôme Radix Burton Radons +Kirill (python273) R. Abhilash Raj Shorya Raj Ajith Ramachandran @@ -1985,6 +1988,7 @@ Gordon Worley Darren Worrall Thomas Wouters Daniel Wozniak +Simon Wrede Marcin Niemira Wei Wu Heiko Wundram diff --git a/Misc/NEWS.d/3.11.0a6.rst b/Misc/NEWS.d/3.11.0a6.rst index 24fc5f05666a636..68b80e46690dc90 100644 --- a/Misc/NEWS.d/3.11.0a6.rst +++ b/Misc/NEWS.d/3.11.0a6.rst @@ -1043,7 +1043,8 @@ Respect `--with-suffix` when building on case-insensitive file systems. .. nonce: MD783M .. section: Build -Building Python now requires a C11 compiler without optional C11 features. +Building Python now requires a C11 compiler. Optional C11 features are not +required. Patch by Victor Stinner. .. diff --git a/Misc/NEWS.d/3.11.0a7.rst b/Misc/NEWS.d/3.11.0a7.rst index 5eaf8ec1f63c033..8e7ccd4d6771ee8 100644 --- a/Misc/NEWS.d/3.11.0a7.rst +++ b/Misc/NEWS.d/3.11.0a7.rst @@ -1099,7 +1099,7 @@ wrong. .. section: Library Fix handling of the ``stacklevel`` argument to logging functions in the -:mod:`logging` module so that it is consistent accross all logging functions +:mod:`logging` module so that it is consistent across all logging functions and, as advertised, similar to the ``stacklevel`` argument used in :meth:`~warnings.warn`. diff --git a/Misc/NEWS.d/next/Build/2022-07-08-10-28-23.gh-issue-94682.ZtGt_0.rst b/Misc/NEWS.d/next/Build/2022-07-08-10-28-23.gh-issue-94682.ZtGt_0.rst new file mode 100644 index 000000000000000..60717a15bcc2718 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-08-10-28-23.gh-issue-94682.ZtGt_0.rst @@ -0,0 +1 @@ +Build and test with OpenSSL 1.1.1q diff --git a/Misc/NEWS.d/next/Build/2022-08-12-13-06-03.gh-issue-90536.qMpF6p.rst b/Misc/NEWS.d/next/Build/2022-08-12-13-06-03.gh-issue-90536.qMpF6p.rst new file mode 100644 index 000000000000000..4605e03915ee639 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-08-12-13-06-03.gh-issue-90536.qMpF6p.rst @@ -0,0 +1,2 @@ +Use the BOLT post-link optimizer to improve performance, particularly on +medium-to-large applications. diff --git a/Misc/NEWS.d/next/Build/2022-08-15-10-56-07.gh-issue-95973.Bsswsc.rst b/Misc/NEWS.d/next/Build/2022-08-15-10-56-07.gh-issue-95973.Bsswsc.rst new file mode 100644 index 000000000000000..d03bc5205ead8e6 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-08-15-10-56-07.gh-issue-95973.Bsswsc.rst @@ -0,0 +1,2 @@ +Add a new ``--with-dsymutil`` configure option to to link debug information +in macOS. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Build/2022-08-26-11-50-03.gh-issue-96269.x_J5h0.rst b/Misc/NEWS.d/next/Build/2022-08-26-11-50-03.gh-issue-96269.x_J5h0.rst new file mode 100644 index 000000000000000..adb605fede5dae8 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-08-26-11-50-03.gh-issue-96269.x_J5h0.rst @@ -0,0 +1,3 @@ +Shared module targets now depend on new ``MODULE_DEPS`` variable, which +includes ``EXPORTSYMS``. This fixes a build order issue on unsupported AIX +platform. diff --git a/Misc/NEWS.d/next/C API/2022-06-06-16-04-14.gh-issue-93503.MHJTu8.rst b/Misc/NEWS.d/next/C API/2022-06-06-16-04-14.gh-issue-93503.MHJTu8.rst new file mode 100644 index 000000000000000..6df9f95fc9461d2 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-06-06-16-04-14.gh-issue-93503.MHJTu8.rst @@ -0,0 +1,7 @@ +Add two new public functions to the public C-API, +:c:func:`PyEval_SetProfileAllThreads` and +:c:func:`PyEval_SetTraceAllThreads`, that allow to set tracking and +profiling functions in all running threads in addition to the calling one. +Also, add a new *running_threads* parameter to :func:`threading.setprofile` +and :func:`threading.settrace` that allows to do the same from Python. Patch +by Pablo Galindo diff --git a/Misc/NEWS.d/next/C API/2022-08-16-16-54-42.gh-issue-95589.6xE1ar.rst b/Misc/NEWS.d/next/C API/2022-08-16-16-54-42.gh-issue-95589.6xE1ar.rst new file mode 100644 index 000000000000000..696e3c80db62cf1 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-08-16-16-54-42.gh-issue-95589.6xE1ar.rst @@ -0,0 +1,4 @@ +Extensions classes that set ``tp_dictoffset`` and ``tp_weaklistoffset`` +lose the support for multiple inheritance, but are now safe. Extension +classes should use :const:`Py_TPFLAGS_MANAGED_DICT` and +:const:`Py_TPFLAGS_MANAGED_WEAKREF` instead. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-18-17-00-33.gh-issue-93911.y286of.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-18-17-00-33.gh-issue-93911.y286of.rst new file mode 100644 index 000000000000000..7fc8f6a2d492939 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-18-17-00-33.gh-issue-93911.y286of.rst @@ -0,0 +1 @@ +Specialize ``LOAD_ATTR`` for objects with custom ``__getattribute__``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-15-11-58-05.gh-issue-90997.bWwV8Q.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-15-11-58-05.gh-issue-90997.bWwV8Q.rst new file mode 100644 index 000000000000000..8db714e59e15929 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-15-11-58-05.gh-issue-90997.bWwV8Q.rst @@ -0,0 +1,3 @@ +Compile virtual :keyword:`try`/:keyword:`except` blocks to handle exceptions +raised during :meth:`~generator.close` or :meth:`~generator.throw` calls +through a suspended frame. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-15-20-52-41.gh-issue-93678.X7GuIJ.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-15-20-52-41.gh-issue-93678.X7GuIJ.rst new file mode 100644 index 000000000000000..9e2b90ba07a4546 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-15-20-52-41.gh-issue-93678.X7GuIJ.rst @@ -0,0 +1 @@ +Added test a harness for direct unit tests of the compiler's optimization stage. The ``_testinternalcapi.optimize_cfg()`` function runs the optimiser on a sequence of instructions. The ``CfgOptimizationTestCase`` class in ``test.support`` has utilities for invoking the optimizer and checking the output. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-18-13-47-59.gh-issue-96046.5Hqbka.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-18-13-47-59.gh-issue-96046.5Hqbka.rst new file mode 100644 index 000000000000000..b8cb52d4b4ece98 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-18-13-47-59.gh-issue-96046.5Hqbka.rst @@ -0,0 +1,4 @@ +:c:func:`PyType_Ready` now initializes ``ht_cached_keys`` and performs +additional checks to ensure that type objects are properly configured. This +avoids crashes in 3rd party packages that don't use regular API to create +new types. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-19-06-51-17.gh-issue-96071.mVgPAo.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-19-06-51-17.gh-issue-96071.mVgPAo.rst new file mode 100644 index 000000000000000..37653ffac12418b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-19-06-51-17.gh-issue-96071.mVgPAo.rst @@ -0,0 +1 @@ +Fix a deadlock in :c:func:`PyGILState_Ensure` when allocating new thread state. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-20-18-36-40.gh-issue-96143.nh3GFM.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-20-18-36-40.gh-issue-96143.nh3GFM.rst new file mode 100644 index 000000000000000..30f44fd453a5476 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-20-18-36-40.gh-issue-96143.nh3GFM.rst @@ -0,0 +1,7 @@ +Add a new ``-X perf`` Python command line option as well as +:func:`sys.activate_stack_trampoline` and :func:`sys.deactivate_stack_trampoline` +function in the :mod:`sys` module that allows to set/unset the interpreter in a +way that the Linux ``perf`` profiler can detect Python calls. The new +:func:`sys.is_stack_trampoline_active` function allows to query the state of the +perf trampoline. Design by Pablo Galindo. Patch by Pablo Galindo and Christian Heimes +with contributions from Gregory P. Smith [Google] and Mark Shannon. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-22-21-33-28.gh-issue-96187.W_6SRG.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-22-21-33-28.gh-issue-96187.W_6SRG.rst new file mode 100644 index 000000000000000..fd194faa68545d2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-22-21-33-28.gh-issue-96187.W_6SRG.rst @@ -0,0 +1,2 @@ +Fixed a bug that caused ``_PyCode_GetExtra`` to return garbage for negative +indexes. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-24-14-30-26.gh-issue-96237.msif5f.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-24-14-30-26.gh-issue-96237.msif5f.rst new file mode 100644 index 000000000000000..cb8a1c0eb7c26f3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-24-14-30-26.gh-issue-96237.msif5f.rst @@ -0,0 +1,5 @@ +The internal field ``_PyInterpreterFrame.f_func`` is renamed to +``_PyInterpreterFrame.f_funcobj`` and may be any object. The ``f_globals`` +and ``f_builtin`` fields may hold junk values. + +It is safest to treat the ``_PyInterpreterFrame`` struct as opaque. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-25-10-19-34.gh-issue-96268.AbYrLB.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-25-10-19-34.gh-issue-96268.AbYrLB.rst new file mode 100644 index 000000000000000..987d85ff3bab8e1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-25-10-19-34.gh-issue-96268.AbYrLB.rst @@ -0,0 +1,2 @@ +Loading a file with invalid UTF-8 will now report the broken character at +the correct location. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst new file mode 100644 index 000000000000000..dff12aef721b537 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst @@ -0,0 +1,16 @@ +Change the jump opcodes so that all conditional jumps are forward jumps. +Backward jumps are converted by the assembler into a conditional forward +jump whose target is the fallthrough block (and with a reversed condition), +followed by an unconditional backward jump. For example: + +``POP_JUMP_IF_TRUE BACKWARD_TARGET`` becomes ``POP_JUMP_IF_FALSE NEXT_BLOCK; +JUMP BACKWARD_TARGET``. + +All the directed conditional jump opcodes were removed: +``POP_JUMP_FORWARD_IF_TRUE``, ``POP_JUMP_BACKWARD_IF_TRUE``, +``POP_JUMP_FORWARD_IF_FALSE``, ``POP_JUMP_BACKWARD_IF_FALSE``, +``POP_JUMP_FORWARD_IF_NONE``, ``POP_JUMP_BACKWARD_IF_NONE``, +``POP_JUMP_FORWARD_IF_NOT_NONE``, ``POP_JUMP_BACKWARD_IF_NOT_NONE``. + +The corresponding opcodes without direction are no longer pseudo-instructions, +and they implement the forward conditional jumps. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-02-16-47-52.gh-issue-93911.vF-GWe.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-02-16-47-52.gh-issue-93911.vF-GWe.rst new file mode 100644 index 000000000000000..b8dc0435377b5f9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-02-16-47-52.gh-issue-93911.vF-GWe.rst @@ -0,0 +1,2 @@ +Fix an issue that could prevent :opcode:`LOAD_ATTR` from specializing +properly when accessing properties. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-05-16-43-44.gh-issue-96569.9lmTCC.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-05-16-43-44.gh-issue-96569.9lmTCC.rst new file mode 100644 index 000000000000000..4734d3d6ded12a2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-05-16-43-44.gh-issue-96569.9lmTCC.rst @@ -0,0 +1 @@ +Remove two cases of undefined behavoir, by adding NULL checks. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-05-19-20-44.gh-issue-96587.bVxhX2.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-05-19-20-44.gh-issue-96587.bVxhX2.rst new file mode 100644 index 000000000000000..37e9dcbb11f0305 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-05-19-20-44.gh-issue-96587.bVxhX2.rst @@ -0,0 +1,2 @@ +Correctly raise ``SyntaxError`` on exception groups (:pep:`654`) on python +versions prior to 3.11 diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-06-14-26-36.gh-issue-96612.P4ZbeY.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-14-26-36.gh-issue-96612.P4ZbeY.rst new file mode 100644 index 000000000000000..52e92703c9c483b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-14-26-36.gh-issue-96612.P4ZbeY.rst @@ -0,0 +1 @@ +Make sure that incomplete frames do not show up in tracemalloc traces. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-22-13.gh-issue-96611.14wIX8.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-22-13.gh-issue-96611.14wIX8.rst new file mode 100644 index 000000000000000..08bd409bc9f9972 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-22-13.gh-issue-96611.14wIX8.rst @@ -0,0 +1,2 @@ +When loading a file with invalid UTF-8 inside a multi-line string, a correct +SyntaxError is emitted. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-54-49.gh-issue-96572.8DRsaW.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-54-49.gh-issue-96572.8DRsaW.rst new file mode 100644 index 000000000000000..44cceb46c28c3e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-06-16-54-49.gh-issue-96572.8DRsaW.rst @@ -0,0 +1 @@ +Fix use after free in trace refs build mode. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-09-07-13-38-37.gh-issue-96641.wky0Fc.rst b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-13-38-37.gh-issue-96641.wky0Fc.rst new file mode 100644 index 000000000000000..51faca8716fbcae --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-09-07-13-38-37.gh-issue-96641.wky0Fc.rst @@ -0,0 +1 @@ +Do not expose ``KeyWrapper`` in :mod:`_functools`. diff --git a/Misc/NEWS.d/next/Documentation/2022-08-19-17-07-45.gh-issue-96098.nDp43u.rst b/Misc/NEWS.d/next/Documentation/2022-08-19-17-07-45.gh-issue-96098.nDp43u.rst new file mode 100644 index 000000000000000..5ead20bbb5357b4 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2022-08-19-17-07-45.gh-issue-96098.nDp43u.rst @@ -0,0 +1,3 @@ +Improve discoverability of the higher level concurrent.futures module by +providing clearer links from the lower level threading and multiprocessing +modules. diff --git a/Misc/NEWS.d/next/Documentation/2022-09-01-17-03-04.gh-issue-96432.1EJ1-4.rst b/Misc/NEWS.d/next/Documentation/2022-09-01-17-03-04.gh-issue-96432.1EJ1-4.rst new file mode 100644 index 000000000000000..a5858f432932cab --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2022-09-01-17-03-04.gh-issue-96432.1EJ1-4.rst @@ -0,0 +1,2 @@ +Fraction literals now support whitespace around the forward slash, +`Fraction('2 / 3')`. diff --git a/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst b/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst new file mode 100644 index 000000000000000..4599b73cc342cad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-04-01-09-43-54.bpo-32547.NIUiNC.rst @@ -0,0 +1 @@ +The constructors for :class:`~csv.DictWriter` and :class:`~csv.DictReader` now coerce the ``fieldnames`` argument to a :class:`list` if it is an iterator. diff --git a/Misc/NEWS.d/next/Library/2022-05-09-21-31-41.gh-issue-92445.tJosdm.rst b/Misc/NEWS.d/next/Library/2022-05-09-21-31-41.gh-issue-92445.tJosdm.rst new file mode 100644 index 000000000000000..ba69a011601fd06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-09-21-31-41.gh-issue-92445.tJosdm.rst @@ -0,0 +1,3 @@ +Fix a bug in :mod:`argparse` where `nargs="*"` would raise an error instead of returning +an empty list when 0 arguments were supplied if choice was also defined in +``parser.add_argument``. diff --git a/Misc/NEWS.d/next/Library/2022-05-19-22-34-42.gh-issue-92986.e6uKxj.rst b/Misc/NEWS.d/next/Library/2022-05-19-22-34-42.gh-issue-92986.e6uKxj.rst new file mode 100644 index 000000000000000..691c0dd3759f8c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-19-22-34-42.gh-issue-92986.e6uKxj.rst @@ -0,0 +1 @@ +Fix :func:`ast.unparse` when ``ImportFrom.level`` is None diff --git a/Misc/NEWS.d/next/Library/2022-06-18-15-06-54.gh-issue-93973.4y6UQT.rst b/Misc/NEWS.d/next/Library/2022-06-18-15-06-54.gh-issue-93973.4y6UQT.rst new file mode 100644 index 000000000000000..a3e68ce4fab9dfc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-06-18-15-06-54.gh-issue-93973.4y6UQT.rst @@ -0,0 +1 @@ +Add keyword argument ``all_errors`` to ``asyncio.create_connection`` so that multiple connection errors can be raised as an ``ExceptionGroup``. diff --git a/Misc/NEWS.d/next/Library/2022-07-09-08-55-04.gh-issue-74116.0XwYC1.rst b/Misc/NEWS.d/next/Library/2022-07-09-08-55-04.gh-issue-74116.0XwYC1.rst new file mode 100644 index 000000000000000..33782598745b783 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-09-08-55-04.gh-issue-74116.0XwYC1.rst @@ -0,0 +1 @@ +Allow :meth:`asyncio.StreamWriter.drain` to be awaited concurrently by multiple tasks. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst b/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst new file mode 100644 index 000000000000000..6393444b53fb64d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst @@ -0,0 +1,2 @@ +The :class:`HTTPStatus ` enum offers a couple of properties +to indicate the HTTP status category e.g. ``HTTPStatus.OK.is_success``. diff --git a/Misc/NEWS.d/next/Library/2022-08-10-17-34-07.gh-issue-95861.qv-T5s.rst b/Misc/NEWS.d/next/Library/2022-08-10-17-34-07.gh-issue-95861.qv-T5s.rst new file mode 100644 index 000000000000000..aae76c74e2fd7d0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-10-17-34-07.gh-issue-95861.qv-T5s.rst @@ -0,0 +1,2 @@ +Add support for computing Spearman's correlation coefficient to the existing +statistics.correlation() function. diff --git a/Misc/NEWS.d/next/Library/2022-08-11-03-16-48.gh-issue-95865.0IOkFP.rst b/Misc/NEWS.d/next/Library/2022-08-11-03-16-48.gh-issue-95865.0IOkFP.rst new file mode 100644 index 000000000000000..aa7c73ff1a35ab4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-11-03-16-48.gh-issue-95865.0IOkFP.rst @@ -0,0 +1 @@ +Speed up :func:`urllib.parse.quote_from_bytes` by replacing a list comprehension with ``map()``. diff --git a/Misc/NEWS.d/next/Library/2022-08-14-18-59-54.gh-issue-69142.6is5Pq.rst b/Misc/NEWS.d/next/Library/2022-08-14-18-59-54.gh-issue-69142.6is5Pq.rst new file mode 100644 index 000000000000000..0db8b3730cf54df --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-14-18-59-54.gh-issue-69142.6is5Pq.rst @@ -0,0 +1 @@ +Add ``%:z`` strftime format code (generates tzoffset with colons as separator), see :ref:`strftime-strptime-behavior`. diff --git a/Misc/NEWS.d/next/Library/2022-08-18-14-53-53.gh-issue-95463.GpP05c.rst b/Misc/NEWS.d/next/Library/2022-08-18-14-53-53.gh-issue-95463.GpP05c.rst new file mode 100644 index 000000000000000..553c55436aab08a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-18-14-53-53.gh-issue-95463.GpP05c.rst @@ -0,0 +1,2 @@ +Remove an incompatible change from :issue:`28080` that caused a regression +that ignored the utf8 in ``ZipInfo.flag_bits``. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Library/2022-08-19-10-19-32.gh-issue-96019.b7uAVP.rst b/Misc/NEWS.d/next/Library/2022-08-19-10-19-32.gh-issue-96019.b7uAVP.rst new file mode 100644 index 000000000000000..296963fd8172480 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-19-10-19-32.gh-issue-96019.b7uAVP.rst @@ -0,0 +1,3 @@ +Fix a bug in the ``makeunicodedata.py`` script leading to about 13 KiB of +space saving in the ``unicodedata`` module, specifically the character +decomposition data. diff --git a/Misc/NEWS.d/next/Library/2022-08-19-18-21-01.gh-issue-96125.ODcF1Y.rst b/Misc/NEWS.d/next/Library/2022-08-19-18-21-01.gh-issue-96125.ODcF1Y.rst new file mode 100644 index 000000000000000..ba7d26a965821f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-19-18-21-01.gh-issue-96125.ODcF1Y.rst @@ -0,0 +1,2 @@ +Fix incorrect condition that causes ``sys.thread_info.name`` to be wrong on +pthread platforms. diff --git a/Misc/NEWS.d/next/Library/2022-08-20-12-56-15.gh-issue-96145.8ah3pE.rst b/Misc/NEWS.d/next/Library/2022-08-20-12-56-15.gh-issue-96145.8ah3pE.rst new file mode 100644 index 000000000000000..540ec8b71ebf903 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-20-12-56-15.gh-issue-96145.8ah3pE.rst @@ -0,0 +1 @@ +Add AttrDict to JSON module for use with object_hook. diff --git a/Misc/NEWS.d/next/Library/2022-08-22-13-54-20.gh-issue-96175.bH7zGU.rst b/Misc/NEWS.d/next/Library/2022-08-22-13-54-20.gh-issue-96175.bH7zGU.rst new file mode 100644 index 000000000000000..c34eff22b3d4568 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-22-13-54-20.gh-issue-96175.bH7zGU.rst @@ -0,0 +1 @@ +Fix unused ``localName`` parameter in the ``Attr`` class in :mod:`xml.dom.minidom`. diff --git a/Misc/NEWS.d/next/Library/2022-08-22-18-42-17.gh-issue-96159.3bFU39.rst b/Misc/NEWS.d/next/Library/2022-08-22-18-42-17.gh-issue-96159.3bFU39.rst new file mode 100644 index 000000000000000..f64469e563f340f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-22-18-42-17.gh-issue-96159.3bFU39.rst @@ -0,0 +1 @@ +Fix a performance regression in logging TimedRotatingFileHandler. Only check for special files when the rollover time has passed. diff --git a/Misc/NEWS.d/next/Library/2022-08-23-13-30-30.gh-issue-96172.7WTHer.rst b/Misc/NEWS.d/next/Library/2022-08-23-13-30-30.gh-issue-96172.7WTHer.rst new file mode 100644 index 000000000000000..1bb57f177887618 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-23-13-30-30.gh-issue-96172.7WTHer.rst @@ -0,0 +1,3 @@ +Fix a bug in ``unicodedata``: ``east_asian_width`` used to return the wrong +value for unassigned characters; and for yet unassigned, but reserved +characters. diff --git a/Misc/NEWS.d/next/Library/2022-08-27-14-38-49.gh-issue-90467.VOOB0p.rst b/Misc/NEWS.d/next/Library/2022-08-27-14-38-49.gh-issue-90467.VOOB0p.rst new file mode 100644 index 000000000000000..282c0e76a8c81cf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-27-14-38-49.gh-issue-90467.VOOB0p.rst @@ -0,0 +1,2 @@ +Fix :class:`asyncio.streams.StreamReaderProtocol` to keep a strong reference +to the created task, so that it's not garbage collected diff --git a/Misc/NEWS.d/next/Library/2022-08-27-21-26-52.gh-issue-96349.XyYLlO.rst b/Misc/NEWS.d/next/Library/2022-08-27-21-26-52.gh-issue-96349.XyYLlO.rst new file mode 100644 index 000000000000000..59eb3517191ddd2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-27-21-26-52.gh-issue-96349.XyYLlO.rst @@ -0,0 +1 @@ +Fixed a minor performance regression in :func:`threading.Event.__init__` diff --git a/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst b/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst new file mode 100644 index 000000000000000..74300c108c893b2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-29-07-04-03.gh-issue-89258.ri7ncj.rst @@ -0,0 +1,2 @@ +Added a :meth:`~logging.Logger.getChildren` method to +:class:`logging.Logger`, to get the immediate child loggers of a logger. diff --git a/Misc/NEWS.d/next/Library/2022-08-29-15-28-39.gh-issue-96385.uLRTsf.rst b/Misc/NEWS.d/next/Library/2022-08-29-15-28-39.gh-issue-96385.uLRTsf.rst new file mode 100644 index 000000000000000..57354826f349263 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-29-15-28-39.gh-issue-96385.uLRTsf.rst @@ -0,0 +1,3 @@ +Fix ``TypeVarTuple.__typing_prepare_subst__``. ``TypeError`` was not raised +when using more than one ``TypeVarTuple``, like ``[*T, *V]`` in type alias +substitutions. diff --git a/Misc/NEWS.d/next/Library/2022-08-29-16-54-36.gh-issue-96388.dCpJcu.rst b/Misc/NEWS.d/next/Library/2022-08-29-16-54-36.gh-issue-96388.dCpJcu.rst new file mode 100644 index 000000000000000..3a35c4734871d1c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-29-16-54-36.gh-issue-96388.dCpJcu.rst @@ -0,0 +1,2 @@ +Work around missing socket functions in :class:`~socket.socket`'s +``__repr__``. diff --git a/Misc/NEWS.d/next/Library/2022-08-30-11-46-36.gh-issue-95987.CV7_u4.rst b/Misc/NEWS.d/next/Library/2022-08-30-11-46-36.gh-issue-95987.CV7_u4.rst new file mode 100644 index 000000000000000..232bba1b92440bc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-30-11-46-36.gh-issue-95987.CV7_u4.rst @@ -0,0 +1 @@ +Fix ``repr`` of ``Any`` subclasses. diff --git a/Misc/NEWS.d/next/Library/2022-08-31-11-10-21.gh-issue-96079.uqrXdJ.rst b/Misc/NEWS.d/next/Library/2022-08-31-11-10-21.gh-issue-96079.uqrXdJ.rst new file mode 100644 index 000000000000000..4cb8d276cbe7f73 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-31-11-10-21.gh-issue-96079.uqrXdJ.rst @@ -0,0 +1 @@ +In :mod:`typing`, fix missing field ``name`` and incorrect ``__module__`` in _AnnotatedAlias. diff --git a/Misc/NEWS.d/next/Library/2022-09-01-13-54-38.gh-issue-96465.0IJmrH.rst b/Misc/NEWS.d/next/Library/2022-09-01-13-54-38.gh-issue-96465.0IJmrH.rst new file mode 100644 index 000000000000000..c78d7538ef943e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-09-01-13-54-38.gh-issue-96465.0IJmrH.rst @@ -0,0 +1 @@ +Fraction hashes are now cached. diff --git a/Misc/NEWS.d/next/Library/2022-09-03-18-39-05.gh-issue-96538.W156-D.rst b/Misc/NEWS.d/next/Library/2022-09-03-18-39-05.gh-issue-96538.W156-D.rst new file mode 100644 index 000000000000000..22e5b4fc2599640 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-09-03-18-39-05.gh-issue-96538.W156-D.rst @@ -0,0 +1 @@ +Speed up ``bisect.bisect()`` functions by taking advantage of type-stability. diff --git a/Misc/NEWS.d/next/Library/2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst b/Misc/NEWS.d/next/Library/2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst new file mode 100644 index 000000000000000..756f6c9eb9e8424 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst @@ -0,0 +1 @@ +Correct conversion of :class:`numbers.Rational`'s to :class:`float`. diff --git a/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst b/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst new file mode 100644 index 000000000000000..8eb8a34884dcedd --- /dev/null +++ b/Misc/NEWS.d/next/Security/2022-08-07-16-53-38.gh-issue-95778.ch010gps.rst @@ -0,0 +1,14 @@ +Converting between :class:`int` and :class:`str` in bases other than 2 +(binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now +raises a :exc:`ValueError` if the number of digits in string form is above a +limit to avoid potential denial of service attacks due to the algorithmic +complexity. This is a mitigation for `CVE-2020-10735 +`_. + +This new limit can be configured or disabled by environment variable, command +line flag, or :mod:`sys` APIs. See the :ref:`integer string conversion length +limitation ` documentation. The default limit is 4300 +digits in string form. + +Patch by Gregory P. Smith [Google] and Christian Heimes [Red Hat] with feedback +from Victor Stinner, Thomas Wouters, Steve Dower, Ned Deily, and Mark Dickinson. diff --git a/Misc/NEWS.d/next/Tests/2022-06-17-13-27-21.gh-issue-93884.5pvPvl.rst b/Misc/NEWS.d/next/Tests/2022-06-17-13-27-21.gh-issue-93884.5pvPvl.rst new file mode 100644 index 000000000000000..ce389149aaae860 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-06-17-13-27-21.gh-issue-93884.5pvPvl.rst @@ -0,0 +1 @@ +Add test cases for :c:func:`PyNumber_ToBase` that take a large number or a non-int object as parameter. diff --git a/Misc/NEWS.d/next/Tests/2022-08-22-14-59-42.gh-issue-95243.DeD66V.rst b/Misc/NEWS.d/next/Tests/2022-08-22-14-59-42.gh-issue-95243.DeD66V.rst new file mode 100644 index 000000000000000..a9ca1f8b86764c2 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2022-08-22-14-59-42.gh-issue-95243.DeD66V.rst @@ -0,0 +1,3 @@ +Mitigate the inherent race condition from using find_unused_port() in +testSockName() by trying to find an unused port a few times before failing. +Patch by Ross Burton. diff --git a/Misc/NEWS.d/next/Tools-Demos/2022-08-29-17-25-13.gh-issue-95853.Ce17cT.rst b/Misc/NEWS.d/next/Tools-Demos/2022-08-29-17-25-13.gh-issue-95853.Ce17cT.rst new file mode 100644 index 000000000000000..1cd1ce14fac08c4 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2022-08-29-17-25-13.gh-issue-95853.Ce17cT.rst @@ -0,0 +1,2 @@ +The ``wasm_build.py`` script now pre-builds Emscripten ports, checks for +broken EMSDK versions, and warns about pkg-config env vars. diff --git a/Misc/NEWS.d/next/Windows/2022-08-26-00-11-18.gh-issue-89545.zmJMY_.rst b/Misc/NEWS.d/next/Windows/2022-08-26-00-11-18.gh-issue-89545.zmJMY_.rst new file mode 100644 index 000000000000000..eeedbf9d6fa8f69 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-08-26-00-11-18.gh-issue-89545.zmJMY_.rst @@ -0,0 +1 @@ +Updates :mod:`platform` code getting the Windows version to use native Windows Management Instrumentation (WMI) queries to determine OS version, type, and architecture. diff --git a/Misc/NEWS.d/next/Windows/2022-08-30-12-01-51.gh-issue-94781.OxO-Gr.rst b/Misc/NEWS.d/next/Windows/2022-08-30-12-01-51.gh-issue-94781.OxO-Gr.rst new file mode 100644 index 000000000000000..d343173d40d6064 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-08-30-12-01-51.gh-issue-94781.OxO-Gr.rst @@ -0,0 +1,2 @@ +Fix :file:`pcbuild.proj` to clean previous instances of ouput files in ``Python\deepfreeze`` and +``Python\frozen_modules`` directories on Windows. Patch by Charlie Zhao. diff --git a/Misc/NEWS.d/next/Windows/2022-09-05-18-32-47.gh-issue-96559.561sUd.rst b/Misc/NEWS.d/next/Windows/2022-09-05-18-32-47.gh-issue-96559.561sUd.rst new file mode 100644 index 000000000000000..275617648f92199 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-09-05-18-32-47.gh-issue-96559.561sUd.rst @@ -0,0 +1,3 @@ +Fixes the Windows launcher not using the compatible interpretation of +default tags found in configuration files when no tag was passed to the +command. diff --git a/Misc/NEWS.d/next/Windows/2022-09-07-00-11-33.gh-issue-96577.kV4K_1.rst b/Misc/NEWS.d/next/Windows/2022-09-07-00-11-33.gh-issue-96577.kV4K_1.rst new file mode 100644 index 000000000000000..6025e5ce4130426 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-09-07-00-11-33.gh-issue-96577.kV4K_1.rst @@ -0,0 +1 @@ +Fixes a potential buffer overrun in :mod:`msilib`. diff --git a/Modules/_bisectmodule.c b/Modules/_bisectmodule.c index 0caa92b2dc6e024..9ceb3ae46fe56d3 100644 --- a/Modules/_bisectmodule.c +++ b/Modules/_bisectmodule.c @@ -25,6 +25,26 @@ get_bisect_state(PyObject *module) return (bisect_state *)state; } +static ssizeargfunc +get_sq_item(PyObject *s) +{ + // The parts of PySequence_GetItem that we only need to do once + PyTypeObject *tp = Py_TYPE(s); + PySequenceMethods *m = tp->tp_as_sequence; + if (m && m->sq_item) { + return m->sq_item; + } + const char *msg; + if (tp->tp_as_mapping && tp->tp_as_mapping->mp_subscript) { + msg = "%.200s is not a sequence"; + } + else { + msg = "'%.200s' object does not support indexing"; + } + PyErr_Format(PyExc_TypeError, msg, tp->tp_name); + return NULL; +} + static inline Py_ssize_t internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi, PyObject* key) @@ -42,32 +62,86 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t if (hi < 0) return -1; } + ssizeargfunc sq_item = get_sq_item(list); + if (sq_item == NULL) { + return -1; + } + if (Py_EnterRecursiveCall("in _bisect.bisect_right") < 0) { + return -1; + } + PyTypeObject *tp = Py_TYPE(item); + richcmpfunc compare = tp->tp_richcompare; while (lo < hi) { /* The (size_t)cast ensures that the addition and subsequent division are performed as unsigned operations, avoiding difficulties from signed overflow. (See issue 13496.) */ mid = ((size_t)lo + hi) / 2; - litem = PySequence_GetItem(list, mid); - if (litem == NULL) - return -1; + assert(mid >= 0); + // PySequence_GetItem, but we already checked the types. + litem = sq_item(list, mid); + assert((PyErr_Occurred() == NULL) ^ (litem == NULL)); + if (litem == NULL) { + goto error; + } if (key != Py_None) { PyObject *newitem = PyObject_CallOneArg(key, litem); if (newitem == NULL) { - Py_DECREF(litem); - return -1; + goto error; } Py_SETREF(litem, newitem); } - res = PyObject_RichCompareBool(item, litem, Py_LT); + /* if item < key(list[mid]): + * hi = mid + * else: + * lo = mid + 1 + */ + if (compare != NULL && Py_IS_TYPE(litem, tp)) { + // A fast path for comparing objects of the same type + PyObject *res_obj = compare(item, litem, Py_LT); + if (res_obj == Py_True) { + Py_DECREF(res_obj); + Py_DECREF(litem); + hi = mid; + continue; + } + if (res_obj == Py_False) { + Py_DECREF(res_obj); + Py_DECREF(litem); + lo = mid + 1; + continue; + } + if (res_obj == NULL) { + goto error; + } + if (res_obj == Py_NotImplemented) { + Py_DECREF(res_obj); + compare = NULL; + res = PyObject_RichCompareBool(item, litem, Py_LT); + } + else { + res = PyObject_IsTrue(res_obj); + Py_DECREF(res_obj); + } + } + else { + // A default path for comparing arbitrary objects + res = PyObject_RichCompareBool(item, litem, Py_LT); + } + if (res < 0) { + goto error; + } Py_DECREF(litem); - if (res < 0) - return -1; if (res) hi = mid; else lo = mid + 1; } + Py_LeaveRecursiveCall(); return lo; +error: + Py_LeaveRecursiveCall(); + Py_XDECREF(litem); + return -1; } /*[clinic input] @@ -168,32 +242,86 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h if (hi < 0) return -1; } + ssizeargfunc sq_item = get_sq_item(list); + if (sq_item == NULL) { + return -1; + } + if (Py_EnterRecursiveCall("in _bisect.bisect_left") < 0) { + return -1; + } + PyTypeObject *tp = Py_TYPE(item); + richcmpfunc compare = tp->tp_richcompare; while (lo < hi) { /* The (size_t)cast ensures that the addition and subsequent division are performed as unsigned operations, avoiding difficulties from signed overflow. (See issue 13496.) */ mid = ((size_t)lo + hi) / 2; - litem = PySequence_GetItem(list, mid); - if (litem == NULL) - return -1; + assert(mid >= 0); + // PySequence_GetItem, but we already checked the types. + litem = sq_item(list, mid); + assert((PyErr_Occurred() == NULL) ^ (litem == NULL)); + if (litem == NULL) { + goto error; + } if (key != Py_None) { PyObject *newitem = PyObject_CallOneArg(key, litem); if (newitem == NULL) { - Py_DECREF(litem); - return -1; + goto error; } Py_SETREF(litem, newitem); } - res = PyObject_RichCompareBool(litem, item, Py_LT); + /* if key(list[mid]) < item: + * lo = mid + 1 + * else: + * hi = mid + */ + if (compare != NULL && Py_IS_TYPE(litem, tp)) { + // A fast path for comparing objects of the same type + PyObject *res_obj = compare(litem, item, Py_LT); + if (res_obj == Py_True) { + Py_DECREF(res_obj); + Py_DECREF(litem); + lo = mid + 1; + continue; + } + if (res_obj == Py_False) { + Py_DECREF(res_obj); + Py_DECREF(litem); + hi = mid; + continue; + } + if (res_obj == NULL) { + goto error; + } + if (res_obj == Py_NotImplemented) { + Py_DECREF(res_obj); + compare = NULL; + res = PyObject_RichCompareBool(litem, item, Py_LT); + } + else { + res = PyObject_IsTrue(res_obj); + Py_DECREF(res_obj); + } + } + else { + // A default path for comparing arbitrary objects + res = PyObject_RichCompareBool(litem, item, Py_LT); + } + if (res < 0) { + goto error; + } Py_DECREF(litem); - if (res < 0) - return -1; if (res) lo = mid + 1; else hi = mid; } + Py_LeaveRecursiveCall(); return lo; +error: + Py_LeaveRecursiveCall(); + Py_XDECREF(litem); + return -1; } diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index eca7c6b29d7a365..d86418af0dc1a8d 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1506,6 +1506,27 @@ format_utcoffset(char *buf, size_t buflen, const char *sep, return 0; } +static PyObject * +make_somezreplacement(PyObject *object, char *sep, PyObject *tzinfoarg) +{ + char buf[100]; + PyObject *tzinfo = get_tzinfo_member(object); + + if (tzinfo == Py_None || tzinfo == NULL) { + return PyBytes_FromStringAndSize(NULL, 0); + } + + assert(tzinfoarg != NULL); + if (format_utcoffset(buf, + sizeof(buf), + sep, + tzinfo, + tzinfoarg) < 0) + return NULL; + + return PyBytes_FromStringAndSize(buf, strlen(buf)); +} + static PyObject * make_Zreplacement(PyObject *object, PyObject *tzinfoarg) { @@ -1566,7 +1587,7 @@ make_freplacement(PyObject *object) /* I sure don't want to reproduce the strftime code from the time module, * so this imports the module and calls it. All the hair is due to - * giving special meanings to the %z, %Z and %f format codes via a + * giving special meanings to the %z, %:z, %Z and %f format codes via a * preprocessing step on the format string. * tzinfoarg is the argument to pass to the object's tzinfo method, if * needed. @@ -1578,6 +1599,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, PyObject *result = NULL; /* guilty until proved innocent */ PyObject *zreplacement = NULL; /* py string, replacement for %z */ + PyObject *colonzreplacement = NULL; /* py string, replacement for %:z */ PyObject *Zreplacement = NULL; /* py string, replacement for %Z */ PyObject *freplacement = NULL; /* py string, replacement for %f */ @@ -1632,32 +1654,29 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, } /* A % has been seen and ch is the character after it. */ else if (ch == 'z') { + /* %z -> +HHMM */ if (zreplacement == NULL) { - /* format utcoffset */ - char buf[100]; - PyObject *tzinfo = get_tzinfo_member(object); - zreplacement = PyBytes_FromStringAndSize("", 0); - if (zreplacement == NULL) goto Done; - if (tzinfo != Py_None && tzinfo != NULL) { - assert(tzinfoarg != NULL); - if (format_utcoffset(buf, - sizeof(buf), - "", - tzinfo, - tzinfoarg) < 0) - goto Done; - Py_DECREF(zreplacement); - zreplacement = - PyBytes_FromStringAndSize(buf, - strlen(buf)); - if (zreplacement == NULL) - goto Done; - } + zreplacement = make_somezreplacement(object, "", tzinfoarg); + if (zreplacement == NULL) + goto Done; } assert(zreplacement != NULL); + assert(PyBytes_Check(zreplacement)); ptoappend = PyBytes_AS_STRING(zreplacement); ntoappend = PyBytes_GET_SIZE(zreplacement); } + else if (ch == ':' && *pin == 'z' && pin++) { + /* %:z -> +HH:MM */ + if (colonzreplacement == NULL) { + colonzreplacement = make_somezreplacement(object, ":", tzinfoarg); + if (colonzreplacement == NULL) + goto Done; + } + assert(colonzreplacement != NULL); + assert(PyBytes_Check(colonzreplacement)); + ptoappend = PyBytes_AS_STRING(colonzreplacement); + ntoappend = PyBytes_GET_SIZE(colonzreplacement); + } else if (ch == 'Z') { /* format tzname */ if (Zreplacement == NULL) { @@ -1686,7 +1705,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, ntoappend = PyBytes_GET_SIZE(freplacement); } else { - /* percent followed by neither z nor Z */ + /* percent followed by something else */ ptoappend = pin - 2; ntoappend = 2; } @@ -1733,6 +1752,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, Done: Py_XDECREF(freplacement); Py_XDECREF(zreplacement); + Py_XDECREF(colonzreplacement); Py_XDECREF(Zreplacement); Py_XDECREF(newfmt); return result; diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index c6d6ca934e9c473..3abb7fd710aeb4f 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1471,9 +1471,8 @@ _functools_exec(PyObject *module) if (state->keyobject_type == NULL) { return -1; } - if (PyModule_AddType(module, state->keyobject_type) < 0) { - return -1; - } + // keyobject_type is used only internally. + // So we don't expose it in module namespace. state->lru_list_elem_type = (PyTypeObject *)PyType_FromModuleAndSpec( module, &lru_list_elem_type_spec, NULL); diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index a76ddd93c0efb90..304e5922c0d50b3 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -1,9 +1,36 @@ -#include "Python.h" +#ifndef Py_TESTCAPI_PARTS_H +#define Py_TESTCAPI_PARTS_H + +#include "pyconfig.h" // for Py_TRACE_REFS + +// Figure out if Limited API is available for this build. If it isn't we won't +// build tests for it. +// Currently, only Py_TRACE_REFS disables Limited API. +#ifdef Py_TRACE_REFS +#undef LIMITED_API_AVAILABLE +#else +#define LIMITED_API_AVAILABLE 1 +#endif -/* Always enable assertions */ +// Always enable assertions #undef NDEBUG +#if !defined(LIMITED_API_AVAILABLE) && defined(Py_LIMITED_API) +// Limited API being unavailable means that with Py_LIMITED_API defined +// we can't even include Python.h. +// Do nothing; the .c file that defined Py_LIMITED_API should also do nothing. + +#else + +#include "Python.h" + int _PyTestCapi_Init_Vectorcall(PyObject *module); -int _PyTestCapi_Init_VectorcallLimited(PyObject *module); int _PyTestCapi_Init_Heaptype(PyObject *module); int _PyTestCapi_Init_Unicode(PyObject *module); + +#ifdef LIMITED_API_AVAILABLE +int _PyTestCapi_Init_VectorcallLimited(PyObject *module); +#endif // LIMITED_API_AVAILABLE + +#endif +#endif // Py_TESTCAPI_PARTS_H diff --git a/Modules/_testcapi/vectorcall_limited.c b/Modules/_testcapi/vectorcall_limited.c index c5184318e292e6c..ee57af84b1bb5fb 100644 --- a/Modules/_testcapi/vectorcall_limited.c +++ b/Modules/_testcapi/vectorcall_limited.c @@ -1,18 +1,8 @@ -#include "pyconfig.h" // Py_TRACE_REFS - -#ifdef Py_TRACE_REFS - -// Py_TRACE_REFS is incompatible with Limited API +#define Py_LIMITED_API 0x030c0000 // 3.12 #include "parts.h" -int -_PyTestCapi_Init_VectorcallLimited(PyObject *m) { - return 0; -} -#else +#ifdef LIMITED_API_AVAILABLE -#define Py_LIMITED_API 0x030c0000 // 3.12 -#include "parts.h" #include "structmember.h" // PyMemberDef /* Test Vectorcall in the limited API */ @@ -89,4 +79,4 @@ _PyTestCapi_Init_VectorcallLimited(PyObject *m) { return 0; } -#endif // Py_TRACE_REFS +#endif // LIMITED_API_AVAILABLE diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 8d9a0c15b1b0234..2d4c73cfe97097b 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -6544,9 +6544,6 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Vectorcall(m) < 0) { return NULL; } - if (_PyTestCapi_Init_VectorcallLimited(m) < 0) { - return NULL; - } if (_PyTestCapi_Init_Heaptype(m) < 0) { return NULL; } @@ -6554,6 +6551,15 @@ PyInit__testcapi(void) return NULL; } +#ifndef LIMITED_API_AVAILABLE + PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False); +#else + PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_True); + if (_PyTestCapi_Init_VectorcallLimited(m) < 0) { + return NULL; + } +#endif + PyState_AddModule(m, &_testcapimodule); return m; } diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 238de749fffc5d2..02a061b84f85a3c 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -14,6 +14,7 @@ #include "Python.h" #include "pycore_atomic_funcs.h" // _Py_atomic_int_get() #include "pycore_bitutils.h" // _Py_bswap32() +#include "pycore_compile.h" // _PyCompile_OptimizeCfg() #include "pycore_fileutils.h" // _Py_normpath #include "pycore_frame.h" // _PyInterpreterFrame #include "pycore_gc.h" // PyGC_Head @@ -25,7 +26,12 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "osdefs.h" // MAXPATHLEN +#include "clinic/_testinternalcapi.c.h" +/*[clinic input] +module _testinternalcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7bb583d8c9eb9a78]*/ static PyObject * get_configs(PyObject *self, PyObject *Py_UNUSED(args)) { @@ -505,7 +511,9 @@ set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args)) static PyObject * record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc) { - PyList_Append(record_list, f->f_func->func_name); + if (PyFunction_Check(f->f_funcobj)) { + PyList_Append(record_list, ((PyFunctionObject *)f->f_funcobj)->func_name); + } return _PyEval_EvalFrameDefault(tstate, f, exc); } @@ -525,6 +533,25 @@ set_eval_frame_record(PyObject *self, PyObject *list) } +/*[clinic input] + +_testinternalcapi.optimize_cfg -> object + + instructions: object + consts: object + +Apply compiler optimizations to an instruction list. +[clinic start generated code]*/ + +static PyObject * +_testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, + PyObject *consts) +/*[clinic end generated code: output=5412aeafca683c8b input=7e8a3de86ebdd0f9]*/ +{ + return _PyCompile_OptimizeCfg(instructions, consts); +} + + static PyMethodDef TestMethods[] = { {"get_configs", get_configs, METH_NOARGS}, {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, @@ -543,6 +570,7 @@ static PyMethodDef TestMethods[] = { {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS}, {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL}, {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL}, + _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index ae09869deda7043..44a1f7b673c0eb2 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -400,7 +400,13 @@ traceback_get_frames(traceback_t *traceback) } _PyInterpreterFrame *pyframe = tstate->cframe->current_frame; - for (; pyframe != NULL;) { + for (;;) { + while (pyframe && _PyFrame_IsIncomplete(pyframe)) { + pyframe = pyframe->previous; + } + if (pyframe == NULL) { + break; + } if (traceback->nframe < _Py_tracemalloc_config.max_nframe) { tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); assert(traceback->frames[traceback->nframe].filename != NULL); @@ -410,8 +416,7 @@ traceback_get_frames(traceback_t *traceback) traceback->total_nframe++; } - _PyInterpreterFrame *back = pyframe->previous; - pyframe = back; + pyframe = pyframe->previous; } } diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c index e806730aa9cf2a4..a1c511e09d704e6 100644 --- a/Modules/atexitmodule.c +++ b/Modules/atexitmodule.c @@ -185,7 +185,7 @@ PyDoc_STRVAR(atexit_run_exitfuncs__doc__, \n\ Run all registered exit functions.\n\ \n\ -If a callaback raises an exception, it is logged with sys.unraisablehook."); +If a callback raises an exception, it is logged with sys.unraisablehook."); static PyObject * atexit_run_exitfuncs(PyObject *module, PyObject *unused) diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h new file mode 100644 index 000000000000000..8113fff37997af8 --- /dev/null +++ b/Modules/clinic/_testinternalcapi.c.h @@ -0,0 +1,68 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(_testinternalcapi_optimize_cfg__doc__, +"optimize_cfg($module, /, instructions, consts)\n" +"--\n" +"\n" +"Apply compiler optimizations to an instruction list."); + +#define _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF \ + {"optimize_cfg", _PyCFunction_CAST(_testinternalcapi_optimize_cfg), METH_FASTCALL|METH_KEYWORDS, _testinternalcapi_optimize_cfg__doc__}, + +static PyObject * +_testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, + PyObject *consts); + +static PyObject * +_testinternalcapi_optimize_cfg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(instructions), &_Py_ID(consts), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"instructions", "consts", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "optimize_cfg", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *instructions; + PyObject *consts; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + instructions = args[0]; + consts = args[1]; + return_value = _testinternalcapi_optimize_cfg_impl(module, instructions, consts); + +exit: + return return_value; +} +/*[clinic end generated code: output=3b1fd713290f68a9 input=a9049054013a1b77]*/ diff --git a/Modules/makesetup b/Modules/makesetup index 08303814c8c9112..5c275ac9a049452 100755 --- a/Modules/makesetup +++ b/Modules/makesetup @@ -267,7 +267,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | cc="$cc $cpps \$(PY_BUILTIN_MODULE_CFLAGS)";; esac # force rebuild when header file or module build flavor (static/shared) is changed - rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(PYTHON_HEADERS) Modules/config.c; $cc -c $src -o $obj" + rule="$obj: $src \$(MODULE_${mods_upper}_DEPS) \$(MODULE_DEPS); $cc -c $src -o $obj" echo "$rule" >>$rulesf done case $doconfig in diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d45fa231ae5e2aa..3810bc87c1fbab8 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -606,6 +606,11 @@ PyOS_AfterFork_Child(void) } assert(_PyThreadState_GET() == tstate); + status = _PyPerfTrampoline_AfterFork_Child(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + run_at_forkers(tstate->interp->after_forkers_child, 0); return; diff --git a/Modules/unicodedata_db.h b/Modules/unicodedata_db.h index f56fa035b685f74..399610be74d5cc8 100644 --- a/Modules/unicodedata_db.h +++ b/Modules/unicodedata_db.h @@ -4,10 +4,10 @@ /* a list of unique database records */ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {0, 0, 0, 0, 0, 0}, - {13, 0, 15, 0, 5, 0}, - {13, 0, 17, 0, 5, 0}, - {13, 0, 16, 0, 5, 0}, - {13, 0, 18, 0, 5, 0}, + {13, 0, 15, 0, 0, 0}, + {13, 0, 17, 0, 0, 0}, + {13, 0, 16, 0, 0, 0}, + {13, 0, 18, 0, 0, 0}, {10, 0, 18, 0, 3, 0}, {26, 0, 19, 0, 3, 0}, {26, 0, 11, 0, 3, 0}, @@ -24,44 +24,44 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {29, 0, 19, 0, 3, 0}, {20, 0, 19, 0, 3, 0}, {2, 0, 1, 0, 3, 0}, - {10, 0, 13, 0, 5, 136}, + {10, 0, 13, 0, 0, 136}, {26, 0, 19, 0, 4, 0}, {28, 0, 11, 0, 4, 0}, {30, 0, 19, 0, 3, 0}, {29, 0, 19, 0, 4, 136}, - {30, 0, 19, 0, 5, 0}, + {30, 0, 19, 0, 0, 0}, {19, 0, 1, 0, 4, 136}, - {24, 0, 19, 1, 5, 0}, + {24, 0, 19, 1, 0, 0}, {14, 0, 15, 0, 4, 0}, {30, 0, 19, 0, 4, 0}, {29, 0, 19, 0, 3, 136}, {30, 0, 11, 0, 4, 0}, {27, 0, 11, 0, 4, 0}, {9, 0, 9, 0, 4, 136}, - {2, 0, 1, 0, 5, 136}, - {25, 0, 19, 1, 5, 0}, + {2, 0, 1, 0, 0, 136}, + {25, 0, 19, 1, 0, 0}, {9, 0, 19, 0, 4, 136}, - {1, 0, 1, 0, 5, 10}, + {1, 0, 1, 0, 0, 10}, {1, 0, 1, 0, 4, 0}, {27, 0, 19, 0, 4, 0}, {2, 0, 1, 0, 4, 0}, {2, 0, 1, 0, 4, 10}, - {2, 0, 1, 0, 5, 10}, - {1, 0, 1, 0, 5, 0}, + {2, 0, 1, 0, 0, 10}, + {1, 0, 1, 0, 0, 0}, {1, 0, 1, 0, 4, 136}, {2, 0, 1, 0, 4, 136}, - {2, 0, 1, 0, 5, 0}, - {19, 0, 1, 0, 5, 0}, - {1, 0, 1, 0, 5, 136}, - {3, 0, 1, 0, 5, 136}, - {18, 0, 1, 0, 5, 136}, - {18, 0, 19, 0, 5, 0}, - {18, 0, 1, 0, 5, 0}, - {29, 0, 19, 0, 5, 0}, + {2, 0, 1, 0, 0, 0}, + {19, 0, 1, 0, 0, 0}, + {1, 0, 1, 0, 0, 136}, + {3, 0, 1, 0, 0, 136}, + {18, 0, 1, 0, 0, 136}, + {18, 0, 19, 0, 0, 0}, + {18, 0, 1, 0, 0, 0}, + {29, 0, 19, 0, 0, 0}, {29, 0, 19, 0, 4, 0}, {18, 0, 19, 0, 4, 0}, {18, 0, 1, 0, 4, 0}, - {29, 0, 19, 0, 5, 136}, + {29, 0, 19, 0, 0, 136}, {4, 230, 14, 0, 4, 80}, {4, 230, 14, 0, 4, 0}, {4, 232, 14, 0, 4, 0}, @@ -77,173 +77,173 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {4, 0, 14, 0, 4, 0}, {4, 233, 14, 0, 4, 0}, {4, 234, 14, 0, 4, 0}, - {18, 0, 19, 0, 5, 170}, - {26, 0, 19, 0, 5, 170}, - {29, 0, 19, 0, 5, 138}, - {1, 0, 1, 0, 5, 138}, - {27, 0, 19, 0, 5, 0}, + {18, 0, 19, 0, 0, 170}, + {26, 0, 19, 0, 0, 170}, + {29, 0, 19, 0, 0, 138}, + {1, 0, 1, 0, 0, 138}, + {27, 0, 19, 0, 0, 0}, {1, 0, 1, 0, 4, 10}, - {30, 0, 1, 0, 5, 0}, - {4, 230, 14, 0, 5, 0}, - {6, 0, 14, 0, 5, 0}, - {26, 0, 1, 0, 5, 0}, - {21, 0, 19, 0, 5, 0}, - {28, 0, 11, 0, 5, 0}, - {4, 220, 14, 0, 5, 0}, - {4, 222, 14, 0, 5, 0}, - {4, 228, 14, 0, 5, 0}, - {4, 10, 14, 0, 5, 0}, - {4, 11, 14, 0, 5, 0}, - {4, 12, 14, 0, 5, 0}, - {4, 13, 14, 0, 5, 0}, - {4, 14, 14, 0, 5, 0}, - {4, 15, 14, 0, 5, 0}, - {4, 16, 14, 0, 5, 0}, - {4, 17, 14, 0, 5, 0}, - {4, 18, 14, 0, 5, 0}, - {4, 19, 14, 0, 5, 0}, - {4, 20, 14, 0, 5, 0}, - {4, 21, 14, 0, 5, 0}, - {4, 22, 14, 0, 5, 0}, - {21, 0, 4, 0, 5, 0}, - {4, 23, 14, 0, 5, 0}, - {26, 0, 4, 0, 5, 0}, - {4, 24, 14, 0, 5, 0}, - {4, 25, 14, 0, 5, 0}, - {19, 0, 4, 0, 5, 0}, - {14, 0, 12, 0, 5, 0}, - {27, 0, 5, 0, 5, 0}, - {26, 0, 11, 0, 5, 0}, - {28, 0, 5, 0, 5, 0}, - {26, 0, 13, 0, 5, 0}, - {26, 0, 5, 0, 5, 0}, - {4, 30, 14, 0, 5, 0}, - {4, 31, 14, 0, 5, 0}, - {4, 32, 14, 0, 5, 0}, - {14, 0, 5, 0, 5, 0}, - {19, 0, 5, 0, 5, 0}, - {19, 0, 5, 0, 5, 10}, - {18, 0, 5, 0, 5, 0}, - {4, 27, 14, 0, 5, 0}, - {4, 28, 14, 0, 5, 0}, - {4, 29, 14, 0, 5, 0}, - {4, 33, 14, 0, 5, 0}, - {4, 34, 14, 0, 5, 0}, - {4, 230, 14, 0, 5, 80}, - {4, 220, 14, 0, 5, 80}, - {7, 0, 12, 0, 5, 0}, - {26, 0, 12, 0, 5, 0}, - {4, 35, 14, 0, 5, 0}, - {19, 0, 5, 0, 5, 136}, - {7, 0, 9, 0, 5, 0}, - {30, 0, 5, 0, 5, 0}, - {4, 36, 14, 0, 5, 0}, - {4, 0, 14, 0, 5, 0}, - {7, 0, 4, 0, 5, 0}, - {18, 0, 4, 0, 5, 0}, - {26, 0, 19, 0, 5, 0}, - {28, 0, 4, 0, 5, 0}, - {29, 0, 5, 0, 5, 0}, - {5, 0, 1, 0, 5, 0}, - {19, 0, 1, 0, 5, 10}, - {4, 7, 14, 0, 5, 80}, - {4, 9, 14, 0, 5, 0}, - {19, 0, 1, 0, 5, 170}, - {7, 0, 1, 0, 5, 0}, - {4, 7, 14, 0, 5, 0}, - {5, 0, 1, 0, 5, 80}, - {5, 0, 1, 0, 5, 10}, - {9, 0, 1, 0, 5, 0}, - {4, 0, 14, 0, 5, 80}, - {4, 0, 14, 0, 5, 10}, - {4, 84, 14, 0, 5, 0}, - {4, 91, 14, 0, 5, 80}, - {9, 0, 19, 0, 5, 0}, - {4, 0, 1, 0, 5, 0}, - {4, 9, 14, 0, 5, 80}, - {19, 0, 1, 0, 5, 136}, - {4, 103, 14, 0, 5, 0}, - {4, 107, 14, 0, 5, 0}, - {4, 118, 14, 0, 5, 0}, - {4, 122, 14, 0, 5, 0}, - {26, 0, 1, 0, 5, 136}, - {4, 216, 14, 0, 5, 0}, - {22, 0, 19, 1, 5, 0}, - {23, 0, 19, 1, 5, 0}, - {4, 129, 14, 0, 5, 0}, - {4, 130, 14, 0, 5, 0}, - {4, 0, 14, 0, 5, 170}, - {4, 132, 14, 0, 5, 0}, - {4, 0, 14, 0, 5, 136}, + {30, 0, 1, 0, 0, 0}, + {4, 230, 14, 0, 0, 0}, + {6, 0, 14, 0, 0, 0}, + {26, 0, 1, 0, 0, 0}, + {21, 0, 19, 0, 0, 0}, + {28, 0, 11, 0, 0, 0}, + {4, 220, 14, 0, 0, 0}, + {4, 222, 14, 0, 0, 0}, + {4, 228, 14, 0, 0, 0}, + {4, 10, 14, 0, 0, 0}, + {4, 11, 14, 0, 0, 0}, + {4, 12, 14, 0, 0, 0}, + {4, 13, 14, 0, 0, 0}, + {4, 14, 14, 0, 0, 0}, + {4, 15, 14, 0, 0, 0}, + {4, 16, 14, 0, 0, 0}, + {4, 17, 14, 0, 0, 0}, + {4, 18, 14, 0, 0, 0}, + {4, 19, 14, 0, 0, 0}, + {4, 20, 14, 0, 0, 0}, + {4, 21, 14, 0, 0, 0}, + {4, 22, 14, 0, 0, 0}, + {21, 0, 4, 0, 0, 0}, + {4, 23, 14, 0, 0, 0}, + {26, 0, 4, 0, 0, 0}, + {4, 24, 14, 0, 0, 0}, + {4, 25, 14, 0, 0, 0}, + {19, 0, 4, 0, 0, 0}, + {14, 0, 12, 0, 0, 0}, + {27, 0, 5, 0, 0, 0}, + {26, 0, 11, 0, 0, 0}, + {28, 0, 5, 0, 0, 0}, + {26, 0, 13, 0, 0, 0}, + {26, 0, 5, 0, 0, 0}, + {4, 30, 14, 0, 0, 0}, + {4, 31, 14, 0, 0, 0}, + {4, 32, 14, 0, 0, 0}, + {14, 0, 5, 0, 0, 0}, + {19, 0, 5, 0, 0, 0}, + {19, 0, 5, 0, 0, 10}, + {18, 0, 5, 0, 0, 0}, + {4, 27, 14, 0, 0, 0}, + {4, 28, 14, 0, 0, 0}, + {4, 29, 14, 0, 0, 0}, + {4, 33, 14, 0, 0, 0}, + {4, 34, 14, 0, 0, 0}, + {4, 230, 14, 0, 0, 80}, + {4, 220, 14, 0, 0, 80}, + {7, 0, 12, 0, 0, 0}, + {26, 0, 12, 0, 0, 0}, + {4, 35, 14, 0, 0, 0}, + {19, 0, 5, 0, 0, 136}, + {7, 0, 9, 0, 0, 0}, + {30, 0, 5, 0, 0, 0}, + {4, 36, 14, 0, 0, 0}, + {4, 0, 14, 0, 0, 0}, + {7, 0, 4, 0, 0, 0}, + {18, 0, 4, 0, 0, 0}, + {26, 0, 19, 0, 0, 0}, + {28, 0, 4, 0, 0, 0}, + {29, 0, 5, 0, 0, 0}, + {5, 0, 1, 0, 0, 0}, + {19, 0, 1, 0, 0, 10}, + {4, 7, 14, 0, 0, 80}, + {4, 9, 14, 0, 0, 0}, + {19, 0, 1, 0, 0, 170}, + {7, 0, 1, 0, 0, 0}, + {4, 7, 14, 0, 0, 0}, + {5, 0, 1, 0, 0, 80}, + {5, 0, 1, 0, 0, 10}, + {9, 0, 1, 0, 0, 0}, + {4, 0, 14, 0, 0, 80}, + {4, 0, 14, 0, 0, 10}, + {4, 84, 14, 0, 0, 0}, + {4, 91, 14, 0, 0, 80}, + {9, 0, 19, 0, 0, 0}, + {4, 0, 1, 0, 0, 0}, + {4, 9, 14, 0, 0, 80}, + {19, 0, 1, 0, 0, 136}, + {4, 103, 14, 0, 0, 0}, + {4, 107, 14, 0, 0, 0}, + {4, 118, 14, 0, 0, 0}, + {4, 122, 14, 0, 0, 0}, + {26, 0, 1, 0, 0, 136}, + {4, 216, 14, 0, 0, 0}, + {22, 0, 19, 1, 0, 0}, + {23, 0, 19, 1, 0, 0}, + {4, 129, 14, 0, 0, 0}, + {4, 130, 14, 0, 0, 0}, + {4, 0, 14, 0, 0, 170}, + {4, 132, 14, 0, 0, 0}, + {4, 0, 14, 0, 0, 136}, {19, 0, 1, 0, 2, 0}, - {19, 0, 1, 0, 5, 80}, - {10, 0, 18, 0, 5, 0}, - {8, 0, 1, 0, 5, 0}, - {5, 9, 1, 0, 5, 0}, - {14, 0, 15, 0, 5, 0}, - {4, 1, 14, 0, 5, 0}, - {4, 234, 14, 0, 5, 0}, - {4, 214, 14, 0, 5, 0}, - {4, 202, 14, 0, 5, 0}, - {4, 232, 14, 0, 5, 0}, - {4, 218, 14, 0, 5, 0}, - {4, 233, 14, 0, 5, 0}, - {2, 0, 1, 0, 5, 138}, - {2, 0, 1, 0, 5, 170}, - {3, 0, 1, 0, 5, 10}, - {1, 0, 1, 0, 5, 170}, - {29, 0, 19, 0, 5, 170}, - {10, 0, 18, 0, 5, 170}, - {10, 0, 18, 0, 5, 136}, - {14, 0, 1, 0, 5, 0}, - {14, 0, 4, 0, 5, 0}, + {19, 0, 1, 0, 0, 80}, + {10, 0, 18, 0, 0, 0}, + {8, 0, 1, 0, 0, 0}, + {5, 9, 1, 0, 0, 0}, + {14, 0, 15, 0, 0, 0}, + {4, 1, 14, 0, 0, 0}, + {4, 234, 14, 0, 0, 0}, + {4, 214, 14, 0, 0, 0}, + {4, 202, 14, 0, 0, 0}, + {4, 232, 14, 0, 0, 0}, + {4, 218, 14, 0, 0, 0}, + {4, 233, 14, 0, 0, 0}, + {2, 0, 1, 0, 0, 138}, + {2, 0, 1, 0, 0, 170}, + {3, 0, 1, 0, 0, 10}, + {1, 0, 1, 0, 0, 170}, + {29, 0, 19, 0, 0, 170}, + {10, 0, 18, 0, 0, 170}, + {10, 0, 18, 0, 0, 136}, + {14, 0, 1, 0, 0, 0}, + {14, 0, 4, 0, 0, 0}, {21, 0, 19, 0, 4, 0}, - {21, 0, 19, 0, 5, 136}, - {26, 0, 19, 0, 5, 136}, + {21, 0, 19, 0, 0, 136}, + {26, 0, 19, 0, 0, 136}, {24, 0, 19, 0, 4, 0}, {25, 0, 19, 0, 4, 0}, - {22, 0, 19, 0, 5, 0}, - {24, 0, 19, 0, 5, 0}, + {22, 0, 19, 0, 0, 0}, + {24, 0, 19, 0, 0, 0}, {26, 0, 19, 0, 4, 136}, - {11, 0, 18, 0, 5, 0}, - {12, 0, 16, 0, 5, 0}, - {14, 0, 2, 0, 5, 0}, - {14, 0, 6, 0, 5, 0}, - {14, 0, 8, 0, 5, 0}, - {14, 0, 3, 0, 5, 0}, - {14, 0, 7, 0, 5, 0}, + {11, 0, 18, 0, 0, 0}, + {12, 0, 16, 0, 0, 0}, + {14, 0, 2, 0, 0, 0}, + {14, 0, 6, 0, 0, 0}, + {14, 0, 8, 0, 0, 0}, + {14, 0, 3, 0, 0, 0}, + {14, 0, 7, 0, 0, 0}, {26, 0, 11, 0, 4, 0}, {26, 0, 11, 0, 4, 136}, - {26, 0, 11, 0, 5, 136}, - {20, 0, 19, 0, 5, 0}, - {27, 0, 13, 0, 5, 0}, - {14, 0, 20, 0, 5, 0}, - {14, 0, 21, 0, 5, 0}, - {14, 0, 22, 0, 5, 0}, - {14, 0, 23, 0, 5, 0}, - {9, 0, 9, 0, 5, 136}, - {27, 0, 10, 0, 5, 136}, - {27, 0, 19, 0, 5, 136}, - {22, 0, 19, 1, 5, 136}, - {23, 0, 19, 1, 5, 136}, + {26, 0, 11, 0, 0, 136}, + {20, 0, 19, 0, 0, 0}, + {27, 0, 13, 0, 0, 0}, + {14, 0, 20, 0, 0, 0}, + {14, 0, 21, 0, 0, 0}, + {14, 0, 22, 0, 0, 0}, + {14, 0, 23, 0, 0, 0}, + {9, 0, 9, 0, 0, 136}, + {27, 0, 10, 0, 0, 136}, + {27, 0, 19, 0, 0, 136}, + {22, 0, 19, 1, 0, 136}, + {23, 0, 19, 1, 0, 136}, {18, 0, 1, 0, 4, 136}, - {28, 0, 11, 0, 5, 136}, + {28, 0, 11, 0, 0, 136}, {28, 0, 11, 0, 1, 0}, - {30, 0, 19, 0, 5, 136}, + {30, 0, 19, 0, 0, 136}, {30, 0, 19, 0, 4, 136}, {1, 0, 1, 0, 4, 170}, - {30, 0, 11, 0, 5, 0}, - {27, 0, 19, 1, 5, 136}, - {9, 0, 19, 0, 5, 136}, + {30, 0, 11, 0, 0, 0}, + {27, 0, 19, 1, 0, 136}, + {9, 0, 19, 0, 0, 136}, {8, 0, 1, 0, 4, 136}, - {8, 0, 1, 0, 5, 136}, - {27, 0, 19, 0, 5, 10}, - {30, 0, 19, 0, 5, 10}, - {27, 0, 19, 1, 5, 0}, + {8, 0, 1, 0, 0, 136}, + {27, 0, 19, 0, 0, 10}, + {30, 0, 19, 0, 0, 10}, + {27, 0, 19, 1, 0, 0}, {27, 0, 19, 1, 4, 0}, - {27, 0, 19, 1, 5, 10}, - {27, 0, 10, 0, 5, 0}, - {27, 0, 11, 0, 5, 0}, + {27, 0, 19, 1, 0, 10}, + {27, 0, 10, 0, 0, 0}, + {27, 0, 11, 0, 0, 0}, {27, 0, 19, 1, 4, 136}, {27, 0, 19, 1, 4, 10}, {30, 0, 19, 0, 2, 0}, @@ -252,10 +252,10 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {30, 0, 1, 0, 4, 136}, {9, 0, 19, 0, 4, 0}, {27, 0, 19, 0, 2, 0}, - {27, 0, 19, 1, 5, 170}, - {30, 0, 19, 1, 5, 0}, + {27, 0, 19, 1, 0, 170}, + {30, 0, 19, 1, 0, 0}, {30, 0, 19, 0, 2, 136}, - {10, 0, 18, 0, 0, 136}, + {10, 0, 18, 0, 5, 136}, {26, 0, 19, 0, 2, 0}, {18, 0, 1, 0, 2, 0}, {8, 0, 1, 0, 2, 0}, @@ -280,15 +280,16 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {30, 0, 1, 0, 2, 136}, {9, 0, 1, 0, 4, 0}, {9, 0, 19, 0, 2, 136}, - {29, 0, 1, 0, 5, 0}, - {15, 0, 1, 0, 5, 0}, + {29, 0, 1, 0, 0, 0}, + {15, 0, 1, 0, 0, 0}, {16, 0, 1, 0, 4, 0}, {19, 0, 1, 0, 2, 170}, - {19, 0, 4, 0, 5, 170}, - {4, 26, 14, 0, 5, 0}, - {19, 0, 4, 0, 5, 136}, - {23, 0, 19, 0, 5, 0}, - {28, 0, 5, 0, 5, 136}, + {0, 0, 0, 0, 2, 0}, + {19, 0, 4, 0, 0, 170}, + {4, 26, 14, 0, 0, 0}, + {19, 0, 4, 0, 0, 136}, + {23, 0, 19, 0, 0, 0}, + {28, 0, 5, 0, 0, 136}, {26, 0, 19, 0, 2, 136}, {22, 0, 19, 0, 2, 136}, {23, 0, 19, 0, 2, 136}, @@ -303,47 +304,47 @@ const _PyUnicode_DatabaseRecord _PyUnicode_Database_Records[] = { {27, 0, 19, 1, 2, 136}, {27, 0, 19, 0, 2, 136}, {28, 0, 11, 0, 2, 136}, - {26, 0, 19, 0, 0, 136}, - {26, 0, 11, 0, 0, 136}, - {28, 0, 11, 0, 0, 136}, - {22, 0, 19, 1, 0, 136}, - {23, 0, 19, 1, 0, 136}, - {27, 0, 10, 0, 0, 136}, - {26, 0, 13, 0, 0, 136}, - {21, 0, 10, 0, 0, 136}, - {7, 0, 9, 0, 0, 136}, - {27, 0, 19, 1, 0, 136}, - {27, 0, 19, 0, 0, 136}, - {1, 0, 1, 0, 0, 136}, - {29, 0, 19, 0, 0, 136}, - {20, 0, 19, 0, 0, 136}, - {2, 0, 1, 0, 0, 136}, + {26, 0, 19, 0, 5, 136}, + {26, 0, 11, 0, 5, 136}, + {28, 0, 11, 0, 5, 136}, + {22, 0, 19, 1, 5, 136}, + {23, 0, 19, 1, 5, 136}, + {27, 0, 10, 0, 5, 136}, + {26, 0, 13, 0, 5, 136}, + {21, 0, 10, 0, 5, 136}, + {7, 0, 9, 0, 5, 136}, + {27, 0, 19, 1, 5, 136}, + {27, 0, 19, 0, 5, 136}, + {1, 0, 1, 0, 5, 136}, + {29, 0, 19, 0, 5, 136}, + {20, 0, 19, 0, 5, 136}, + {2, 0, 1, 0, 5, 136}, {26, 0, 19, 0, 1, 136}, {22, 0, 19, 1, 1, 136}, {23, 0, 19, 1, 1, 136}, {19, 0, 1, 0, 1, 136}, {18, 0, 1, 0, 1, 136}, - {30, 0, 19, 0, 0, 136}, + {30, 0, 19, 0, 5, 136}, {30, 0, 19, 0, 1, 136}, {27, 0, 19, 0, 1, 136}, - {14, 0, 19, 0, 5, 0}, - {8, 0, 19, 0, 5, 0}, - {9, 0, 9, 0, 5, 0}, - {9, 0, 4, 0, 5, 0}, - {30, 0, 4, 0, 5, 0}, - {1, 0, 4, 0, 5, 0}, - {2, 0, 4, 0, 5, 0}, - {9, 0, 12, 0, 5, 0}, - {9, 0, 5, 0, 5, 0}, - {4, 9, 1, 0, 5, 0}, + {14, 0, 19, 0, 0, 0}, + {8, 0, 19, 0, 0, 0}, + {9, 0, 9, 0, 0, 0}, + {9, 0, 4, 0, 0, 0}, + {30, 0, 4, 0, 0, 0}, + {1, 0, 4, 0, 0, 0}, + {2, 0, 4, 0, 0, 0}, + {9, 0, 12, 0, 0, 0}, + {9, 0, 5, 0, 0, 0}, + {4, 9, 1, 0, 0, 0}, {4, 0, 14, 0, 2, 0}, {5, 6, 1, 0, 2, 0}, - {30, 0, 1, 0, 5, 170}, - {5, 216, 1, 0, 5, 0}, - {5, 226, 1, 0, 5, 0}, - {27, 0, 1, 0, 5, 136}, - {7, 0, 9, 0, 5, 136}, - {30, 0, 1, 0, 5, 136}, + {30, 0, 1, 0, 0, 170}, + {5, 216, 1, 0, 0, 0}, + {5, 226, 1, 0, 0, 0}, + {27, 0, 1, 0, 0, 136}, + {7, 0, 9, 0, 0, 136}, + {30, 0, 1, 0, 0, 136}, {30, 0, 1, 0, 4, 0}, {29, 0, 19, 0, 2, 0}, }; @@ -674,12 +675,12 @@ const char *_PyUnicode_BidirectionalNames[] = { NULL }; const char *_PyUnicode_EastAsianWidthNames[] = { - "F", + "N", "H", "W", "Na", "A", - "N", + "F", NULL }; static const char *decomp_prefix[] = { @@ -809,23 +810,46 @@ static const unsigned short index1[] = { 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, - 101, 101, 101, 267, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 121, 121, 121, 121, 268, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 267, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 121, 121, 121, 121, 269, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 270, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, - 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 269, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 271, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 268, 270, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, @@ -1191,30 +1215,7 @@ static const unsigned short index1[] = { 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 270, 137, 271, 272, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 272, 137, 273, 274, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, @@ -1287,7 +1288,7 @@ static const unsigned short index1[] = { 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 273, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 275, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, @@ -1324,7 +1325,7 @@ static const unsigned short index1[] = { 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 273, + 120, 275, }; static const unsigned short index2[] = { @@ -2259,7 +2260,7 @@ static const unsigned short index2[] = { 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 0, 0, 280, 280, 280, 280, 280, 280, 280, + 280, 280, 280, 280, 280, 280, 281, 281, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, @@ -2267,22 +2268,23 @@ static const unsigned short index2[] = { 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 35, 35, 35, 35, 35, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, - 281, 282, 281, 283, 283, 283, 283, 283, 283, 283, 283, 283, 219, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 0, 281, 281, - 281, 281, 281, 0, 281, 0, 281, 281, 0, 281, 281, 0, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 283, 131, 131, 131, 131, 131, 131, 131, 131, + 280, 280, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 35, 35, 35, + 35, 35, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 35, 35, 35, + 0, 0, 0, 0, 0, 282, 283, 282, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 219, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 0, 282, 282, 282, 282, 282, 0, 282, 0, 282, 282, 0, 282, 282, 0, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 284, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, @@ -2299,26 +2301,26 @@ static const unsigned short index2[] = { 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 284, 199, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 285, 199, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 285, 26, 26, 26, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 286, 286, 286, 286, 286, 286, 286, 287, 288, 286, 0, 0, 0, 0, - 0, 0, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 81, 81, - 286, 289, 289, 290, 290, 287, 288, 287, 288, 287, 288, 287, 288, 287, - 288, 287, 288, 287, 288, 287, 288, 253, 253, 287, 288, 286, 286, 286, - 286, 290, 290, 290, 291, 286, 291, 0, 286, 291, 286, 286, 289, 292, 293, - 292, 293, 292, 293, 294, 286, 286, 295, 296, 297, 297, 298, 0, 286, 299, - 294, 286, 0, 0, 0, 0, 131, 131, 131, 118, 131, 0, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 286, 26, 26, 26, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 287, 287, 287, 287, 287, 287, 287, 288, 289, + 287, 0, 0, 0, 0, 0, 0, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, + 86, 86, 81, 81, 287, 290, 290, 291, 291, 288, 289, 288, 289, 288, 289, + 288, 289, 288, 289, 288, 289, 288, 289, 288, 289, 253, 253, 288, 289, + 287, 287, 287, 287, 291, 291, 291, 292, 287, 292, 0, 287, 292, 287, 287, + 290, 293, 294, 293, 294, 293, 294, 295, 287, 287, 296, 297, 298, 298, + 299, 0, 287, 300, 295, 287, 0, 0, 0, 0, 131, 131, 131, 118, 131, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, @@ -2328,278 +2330,278 @@ static const unsigned short index2[] = { 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, - 131, 131, 131, 131, 131, 0, 0, 177, 0, 300, 300, 301, 302, 301, 300, 300, - 303, 304, 300, 305, 306, 307, 306, 306, 308, 308, 308, 308, 308, 308, - 308, 308, 308, 308, 306, 300, 309, 310, 309, 300, 300, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 311, 311, 311, 311, 311, 311, 303, 300, 304, 312, 313, - 312, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, 303, - 310, 304, 310, 303, 304, 315, 316, 317, 315, 315, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 319, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 319, 319, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 0, 0, 0, 318, 318, 318, 318, 318, 318, 0, 0, 318, 318, 318, 318, - 318, 318, 0, 0, 318, 318, 318, 318, 318, 318, 0, 0, 318, 318, 318, 0, 0, - 0, 302, 302, 310, 312, 320, 302, 302, 0, 321, 322, 322, 322, 322, 321, - 321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, 323, 323, 26, 30, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 131, 131, 131, 131, 131, 131, 131, 131, 0, 0, 177, 0, 301, 301, 302, 303, + 302, 301, 301, 304, 305, 301, 306, 307, 308, 307, 307, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 307, 301, 310, 311, 310, 301, 301, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 304, 301, + 305, 313, 314, 313, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, 315, + 315, 315, 304, 311, 305, 311, 304, 305, 316, 317, 318, 316, 316, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 320, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 320, + 320, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 0, 0, 0, 319, 319, 319, 319, 319, 319, 0, 0, 319, + 319, 319, 319, 319, 319, 0, 0, 319, 319, 319, 319, 319, 319, 0, 0, 319, + 319, 319, 0, 0, 0, 303, 303, 311, 313, 321, 303, 303, 0, 322, 323, 323, + 323, 323, 322, 322, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 324, 324, 26, 30, + 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 0, 0, 0, 0, 0, 83, 138, 83, 0, 0, 0, 0, 150, 150, 150, + 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 83, 138, 83, 0, 0, 0, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, - 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 324, 324, 324, 324, 324, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, - 324, 324, 324, 324, 324, 155, 155, 155, 155, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 155, 155, 26, 80, 80, 0, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 26, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 155, 155, 155, 155, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 155, 155, 26, 80, + 80, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 26, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 80, 80, 80, 80, 80, 80, 80, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 325, 325, 325, - 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, - 325, 325, 325, 325, 325, 325, 325, 325, 325, 325, 0, 0, 0, 0, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 150, 150, 150, 150, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 175, 48, 48, 48, 48, 48, 48, 48, 48, 175, 0, 0, - 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 0, 0, 0, + 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 150, 150, + 150, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 175, 48, 48, 48, 48, 48, 48, + 48, 48, 175, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 83, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 83, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 83, 175, 175, 175, 175, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 48, + 48, 48, 48, 48, 48, 48, 48, 83, 175, 175, 175, 175, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 44, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 83, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, - 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44, 44, - 44, 44, 44, 0, 44, 44, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, - 47, 47, 47, 47, 47, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 0, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 0, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 0, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 51, 51, 51, 51, - 51, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, + 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 53, 51, 51, 51, 51, 51, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 0, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, - 107, 107, 107, 107, 0, 0, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 0, 0, 0, 107, 107, 107, 107, 107, 107, 0, 0, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 0, 107, 107, 0, 0, 0, 107, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 107, 107, + 0, 0, 0, 107, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 104, + 327, 327, 327, 327, 327, 327, 327, 327, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 104, 326, 326, 326, 326, - 326, 326, 326, 326, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 327, - 327, 326, 326, 326, 326, 326, 326, 326, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 328, 328, 327, 327, 327, 327, 327, 327, 327, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, - 0, 0, 326, 326, 326, 326, 326, 326, 326, 326, 326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 0, 107, 107, 0, 0, 0, 0, 0, 326, 326, 326, 326, 326, 107, 107, 107, + 107, 0, 0, 0, 0, 0, 0, 0, 0, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 326, 326, 326, 326, 326, 326, 0, 0, 0, 138, 107, + 107, 107, 107, 107, 107, 0, 107, 107, 0, 0, 0, 0, 0, 327, 327, 327, 327, + 327, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 327, 327, 327, 327, 327, + 327, 0, 0, 0, 138, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, - 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 0, 0, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 326, 326, - 107, 107, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 0, 0, 326, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 326, 326, 326, 326, 326, 107, 135, 135, 135, 0, 135, - 135, 0, 0, 0, 0, 0, 135, 86, 135, 81, 107, 107, 107, 107, 0, 107, 107, - 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 0, 0, 81, 178, 86, 0, 0, 0, 0, 144, 326, 326, 326, 326, 326, - 326, 326, 326, 326, 0, 0, 0, 0, 0, 0, 0, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, + 0, 0, 0, 327, 327, 107, 107, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 0, 0, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 107, 135, + 135, 135, 0, 135, 135, 0, 0, 0, 0, 0, 135, 86, 135, 81, 107, 107, 107, + 107, 0, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 326, 326, 104, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 0, 0, 81, 178, 86, 0, 0, 0, 0, 144, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 0, 0, 0, 0, 0, 0, 0, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 326, 326, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 327, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 327, 327, + 104, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 81, - 86, 0, 0, 0, 0, 326, 326, 326, 326, 326, 104, 104, 104, 104, 104, 104, - 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 327, 327, 327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, + 107, 107, 107, 328, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 81, 86, 0, 0, 0, 0, 327, 327, 327, 327, 327, 104, + 104, 104, 104, 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 0, 0, 0, 138, 138, 138, 138, 138, 138, 138, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 0, 0, 326, 326, 326, 326, 326, 326, 326, - 326, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 326, 326, 326, 326, 326, - 326, 326, 326, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 104, 104, 104, - 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 326, 326, 326, 326, 326, 326, - 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 138, 138, 138, 138, + 138, 138, 138, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 327, 327, + 327, 327, 327, 327, 327, 327, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, + 327, 327, 327, 327, 327, 327, 327, 327, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, + 0, 0, 0, 104, 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 327, + 327, 327, 327, 327, 327, 327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - 329, 329, 329, 329, 329, 329, 329, 329, 329, 0, 0, 0, 0, 0, 0, 0, 326, - 326, 326, 326, 326, 326, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 0, 0, 0, + 0, 0, 0, 0, 327, 327, 327, 327, 327, 327, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 81, 81, - 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, - 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, - 330, 330, 330, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 331, 331, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 0, 81, 81, 102, 0, 0, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 107, 0, 81, 81, 102, 0, 0, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 326, - 326, 326, 326, 326, 326, 326, 326, 326, 326, 107, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 86, 86, 81, 81, 81, 86, 81, 86, - 86, 86, 86, 331, 331, 331, 331, 113, 113, 113, 113, 113, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 81, - 86, 81, 86, 104, 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 326, 326, 326, 326, 326, 326, 326, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, + 107, 107, 107, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 107, 0, + 0, 0, 0, 0, 0, 0, 0, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 86, 86, 81, + 81, 81, 86, 81, 86, 86, 86, 86, 332, 332, 332, 332, 113, 113, 113, 113, + 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 135, 141, + 107, 107, 107, 107, 81, 86, 81, 86, 104, 104, 104, 104, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 327, 327, 327, + 327, 327, 327, 327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 135, 141, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 144, 83, - 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, 155, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 146, - 146, 146, 146, 146, 146, 146, 146, 146, 146, 144, 48, 48, 135, 135, 48, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 135, 135, 141, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 142, - 48, 142, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 142, 48, - 48, 48, 48, 141, 141, 141, 135, 135, 135, 135, 141, 141, 144, 143, 83, - 83, 192, 83, 83, 83, 83, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, 0, 81, 81, 81, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 151, 135, 135, - 135, 135, 141, 135, 152, 152, 135, 135, 135, 144, 144, 0, 146, 146, 146, - 146, 146, 146, 146, 146, 146, 146, 83, 83, 83, 83, 48, 141, 141, 48, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 144, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 144, 48, + 48, 135, 135, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 135, 135, 141, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 147, 83, 83, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 135, - 141, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 142, 48, 142, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 142, 48, 48, 48, 48, 141, 141, 141, 135, 135, 135, 135, 141, 141, + 144, 143, 83, 83, 192, 83, 83, 83, 83, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 192, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, 0, 81, 81, 81, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 141, 141, 141, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 141, 176, 48, 48, 48, 48, 83, 83, - 83, 83, 135, 147, 135, 135, 83, 141, 135, 146, 146, 146, 146, 146, 146, - 146, 146, 146, 146, 48, 83, 48, 83, 83, 83, 0, 150, 150, 150, 150, 150, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 151, + 135, 135, 135, 135, 141, 135, 152, 152, 135, 135, 135, 144, 144, 0, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 83, 83, 83, 83, 48, 141, + 141, 48, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 147, 83, 83, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 135, 141, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 141, 141, + 141, 135, 135, 135, 135, 135, 135, 135, 135, 135, 141, 176, 48, 48, 48, + 48, 83, 83, 83, 83, 135, 147, 135, 135, 83, 141, 135, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 48, 83, 48, 83, 83, 83, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 141, - 141, 141, 135, 135, 135, 141, 141, 135, 176, 147, 135, 83, 83, 83, 83, - 83, 83, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 150, 150, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 141, 141, 141, 135, 135, 135, 141, 141, 135, 176, 147, 135, 83, + 83, 83, 83, 83, 83, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 83, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 0, 48, 48, 48, 48, 0, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 83, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 135, 141, 141, 141, 135, 135, 135, 135, 135, 135, 147, 144, 0, 0, 0, 0, - 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, 0, 0, 0, - 135, 135, 141, 141, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, 48, 0, - 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, 48, - 48, 48, 48, 0, 147, 147, 48, 148, 141, 135, 141, 141, 141, 141, 0, 0, + 48, 48, 48, 135, 141, 141, 141, 135, 135, 135, 135, 135, 135, 147, 144, + 0, 0, 0, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 0, 0, 0, + 0, 0, 0, 135, 135, 141, 141, 0, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 48, + 48, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 0, 48, 48, 48, 48, 48, 48, 48, 0, 48, 48, 0, 48, + 48, 48, 48, 48, 0, 147, 147, 48, 148, 141, 135, 141, 141, 141, 141, 0, 0, 141, 141, 0, 0, 149, 149, 176, 0, 0, 48, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 141, 141, 0, 0, 81, 81, 81, 81, 81, 81, 81, 0, 0, 0, 81, 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, @@ -2688,7 +2690,7 @@ static const unsigned short index2[] = { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 141, 135, 135, 135, 135, 135, 135, 135, 0, 135, 135, 135, 135, 135, 135, - 141, 332, 48, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 146, + 141, 333, 48, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0, 83, 83, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, @@ -2815,7 +2817,7 @@ static const unsigned short index2[] = { 53, 53, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, - 253, 254, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 334, 334, 0, 0, 0, 0, 0, + 253, 254, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335, 335, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, @@ -2899,13 +2901,13 @@ static const unsigned short index2[] = { 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 335, 335, 335, 335, 335, 335, 335, - 336, 336, 178, 178, 178, 80, 80, 80, 337, 336, 336, 336, 336, 336, 177, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 336, 336, 336, 336, 336, 336, 336, + 337, 337, 178, 178, 178, 80, 80, 80, 338, 337, 337, 337, 337, 337, 177, 177, 177, 177, 177, 177, 177, 177, 86, 86, 86, 86, 86, 86, 86, 86, 80, 80, 81, 81, 81, 81, 81, 86, 86, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 335, 335, 335, 335, 335, 335, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 336, 336, 336, 336, 336, 336, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, @@ -2966,26 +2968,26 @@ static const unsigned short index2[] = { 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 338, 35, 35, 35, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 339, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 338, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 339, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 338, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 49, 49, 49, 49, 339, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 338, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 49, 49, 49, 49, 49, 49, 49, 49, 339, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 338, 35, 35, 35, 35, 35, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 339, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 35, 0, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 35, 35, 230, 35, 35, 35, 35, 35, 35, 49, 35, 0, 0, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, @@ -3044,35 +3046,35 @@ static const unsigned short index2[] = { 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 0, 0, 326, 326, 326, 326, 326, 326, 326, - 326, 326, 86, 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 107, 107, 0, 0, 327, 327, 327, 327, 327, 327, 327, + 327, 327, 86, 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, 328, - 328, 328, 328, 328, 328, 328, 328, 328, 328, 329, 329, 329, 329, 329, + 0, 0, 0, 0, 0, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, - 329, 81, 81, 81, 81, 81, 81, 147, 137, 0, 0, 0, 0, 136, 136, 136, 136, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + 330, 81, 81, 81, 81, 81, 81, 147, 137, 0, 0, 0, 0, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 0, 0, 0, 0, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 133, - 331, 331, 331, 111, 331, 331, 331, 331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 133, + 332, 332, 332, 111, 332, 332, 332, 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 133, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 133, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, @@ -3106,16 +3108,16 @@ static const unsigned short index2[] = { 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 155, 155, 26, 26, 26, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 340, 26, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 341, 26, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 226, 226, 226, 26, 26, 26, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 272, 341, - 246, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 246, 246, 246, 246, 246, 246, 246, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 226, 226, 226, 26, 26, 26, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 272, 342, + 246, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 342, 342, 342, + 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, 342, + 342, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 274, 274, @@ -3142,8 +3144,8 @@ static const unsigned short index2[] = { 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 26, 26, 26, 26, 243, 243, 243, 243, 243, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, - 243, 243, 243, 243, 26, 26, 26, 243, 26, 26, 26, 243, 243, 243, 342, 342, - 342, 342, 342, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 26, 26, 26, 243, 26, 26, 26, 243, 243, 243, 343, 343, + 343, 343, 343, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, @@ -3265,27 +3267,29 @@ static const unsigned short index2[] = { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 281, 281, 281, 281, 281, 281, + 281, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 281, 281, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, @@ -3294,9 +3298,8 @@ static const unsigned short index2[] = { 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, @@ -3308,30 +3311,55 @@ static const unsigned short index2[] = { 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 172, 172, 172, 172, 172, 172, + 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 0, 0, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 0, 177, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, - 177, 177, 177, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, @@ -3344,8 +3372,7 @@ static const unsigned short index2[] = { 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 71, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, @@ -3354,7 +3381,7 @@ static const unsigned short index2[] = { 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 0, 0, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 0, 0, }; /* decomposition data */ @@ -3420,121 +3447,120 @@ static const unsigned int decomp_data[] = { 259, 121, 514, 32, 774, 514, 32, 775, 514, 32, 778, 514, 32, 808, 514, 32, 771, 514, 32, 779, 259, 611, 259, 108, 259, 115, 259, 120, 259, 661, 256, 768, 256, 769, 256, 787, 512, 776, 769, 256, 697, 514, 32, 837, 256, - 59, 514, 32, 769, 512, 168, 769, 512, 913, 769, 256, 183, 512, 917, 769, - 512, 919, 769, 512, 921, 769, 512, 927, 769, 512, 933, 769, 512, 937, - 769, 512, 970, 769, 512, 921, 776, 512, 933, 776, 512, 945, 769, 512, - 949, 769, 512, 951, 769, 512, 953, 769, 512, 971, 769, 512, 953, 776, - 512, 965, 776, 512, 959, 769, 512, 965, 769, 512, 969, 769, 258, 946, - 258, 952, 258, 933, 512, 978, 769, 512, 978, 776, 258, 966, 258, 960, - 258, 954, 258, 961, 258, 962, 258, 920, 258, 949, 258, 931, 512, 1045, - 768, 512, 1045, 776, 512, 1043, 769, 512, 1030, 776, 512, 1050, 769, 512, - 1048, 768, 512, 1059, 774, 512, 1048, 774, 512, 1080, 774, 512, 1077, - 768, 512, 1077, 776, 512, 1075, 769, 512, 1110, 776, 512, 1082, 769, 512, - 1080, 768, 512, 1091, 774, 512, 1140, 783, 512, 1141, 783, 512, 1046, - 774, 512, 1078, 774, 512, 1040, 774, 512, 1072, 774, 512, 1040, 776, 512, - 1072, 776, 512, 1045, 774, 512, 1077, 774, 512, 1240, 776, 512, 1241, - 776, 512, 1046, 776, 512, 1078, 776, 512, 1047, 776, 512, 1079, 776, 512, - 1048, 772, 512, 1080, 772, 512, 1048, 776, 512, 1080, 776, 512, 1054, - 776, 512, 1086, 776, 512, 1256, 776, 512, 1257, 776, 512, 1069, 776, 512, - 1101, 776, 512, 1059, 772, 512, 1091, 772, 512, 1059, 776, 512, 1091, - 776, 512, 1059, 779, 512, 1091, 779, 512, 1063, 776, 512, 1095, 776, 512, - 1067, 776, 512, 1099, 776, 514, 1381, 1410, 512, 1575, 1619, 512, 1575, - 1620, 512, 1608, 1620, 512, 1575, 1621, 512, 1610, 1620, 514, 1575, 1652, - 514, 1608, 1652, 514, 1735, 1652, 514, 1610, 1652, 512, 1749, 1620, 512, - 1729, 1620, 512, 1746, 1620, 512, 2344, 2364, 512, 2352, 2364, 512, 2355, - 2364, 512, 2325, 2364, 512, 2326, 2364, 512, 2327, 2364, 512, 2332, 2364, - 512, 2337, 2364, 512, 2338, 2364, 512, 2347, 2364, 512, 2351, 2364, 512, - 2503, 2494, 512, 2503, 2519, 512, 2465, 2492, 512, 2466, 2492, 512, 2479, - 2492, 512, 2610, 2620, 512, 2616, 2620, 512, 2582, 2620, 512, 2583, 2620, - 512, 2588, 2620, 512, 2603, 2620, 512, 2887, 2902, 512, 2887, 2878, 512, - 2887, 2903, 512, 2849, 2876, 512, 2850, 2876, 512, 2962, 3031, 512, 3014, - 3006, 512, 3015, 3006, 512, 3014, 3031, 512, 3142, 3158, 512, 3263, 3285, - 512, 3270, 3285, 512, 3270, 3286, 512, 3270, 3266, 512, 3274, 3285, 512, - 3398, 3390, 512, 3399, 3390, 512, 3398, 3415, 512, 3545, 3530, 512, 3545, - 3535, 512, 3548, 3530, 512, 3545, 3551, 514, 3661, 3634, 514, 3789, 3762, - 514, 3755, 3737, 514, 3755, 3745, 257, 3851, 512, 3906, 4023, 512, 3916, - 4023, 512, 3921, 4023, 512, 3926, 4023, 512, 3931, 4023, 512, 3904, 4021, - 512, 3953, 3954, 512, 3953, 3956, 512, 4018, 3968, 514, 4018, 3969, 512, - 4019, 3968, 514, 4019, 3969, 512, 3953, 3968, 512, 3986, 4023, 512, 3996, - 4023, 512, 4001, 4023, 512, 4006, 4023, 512, 4011, 4023, 512, 3984, 4021, - 512, 4133, 4142, 259, 4316, 512, 6917, 6965, 512, 6919, 6965, 512, 6921, - 6965, 512, 6923, 6965, 512, 6925, 6965, 512, 6929, 6965, 512, 6970, 6965, - 512, 6972, 6965, 512, 6974, 6965, 512, 6975, 6965, 512, 6978, 6965, 259, - 65, 259, 198, 259, 66, 259, 68, 259, 69, 259, 398, 259, 71, 259, 72, 259, - 73, 259, 74, 259, 75, 259, 76, 259, 77, 259, 78, 259, 79, 259, 546, 259, - 80, 259, 82, 259, 84, 259, 85, 259, 87, 259, 97, 259, 592, 259, 593, 259, - 7426, 259, 98, 259, 100, 259, 101, 259, 601, 259, 603, 259, 604, 259, - 103, 259, 107, 259, 109, 259, 331, 259, 111, 259, 596, 259, 7446, 259, - 7447, 259, 112, 259, 116, 259, 117, 259, 7453, 259, 623, 259, 118, 259, - 7461, 259, 946, 259, 947, 259, 948, 259, 966, 259, 967, 261, 105, 261, - 114, 261, 117, 261, 118, 261, 946, 261, 947, 261, 961, 261, 966, 261, - 967, 259, 1085, 259, 594, 259, 99, 259, 597, 259, 240, 259, 604, 259, - 102, 259, 607, 259, 609, 259, 613, 259, 616, 259, 617, 259, 618, 259, - 7547, 259, 669, 259, 621, 259, 7557, 259, 671, 259, 625, 259, 624, 259, - 626, 259, 627, 259, 628, 259, 629, 259, 632, 259, 642, 259, 643, 259, - 427, 259, 649, 259, 650, 259, 7452, 259, 651, 259, 652, 259, 122, 259, - 656, 259, 657, 259, 658, 259, 952, 512, 65, 805, 512, 97, 805, 512, 66, - 775, 512, 98, 775, 512, 66, 803, 512, 98, 803, 512, 66, 817, 512, 98, - 817, 512, 199, 769, 512, 231, 769, 512, 68, 775, 512, 100, 775, 512, 68, - 803, 512, 100, 803, 512, 68, 817, 512, 100, 817, 512, 68, 807, 512, 100, - 807, 512, 68, 813, 512, 100, 813, 512, 274, 768, 512, 275, 768, 512, 274, - 769, 512, 275, 769, 512, 69, 813, 512, 101, 813, 512, 69, 816, 512, 101, - 816, 512, 552, 774, 512, 553, 774, 512, 70, 775, 512, 102, 775, 512, 71, - 772, 512, 103, 772, 512, 72, 775, 512, 104, 775, 512, 72, 803, 512, 104, - 803, 512, 72, 776, 512, 104, 776, 512, 72, 807, 512, 104, 807, 512, 72, - 814, 512, 104, 814, 512, 73, 816, 512, 105, 816, 512, 207, 769, 512, 239, - 769, 512, 75, 769, 512, 107, 769, 512, 75, 803, 512, 107, 803, 512, 75, - 817, 512, 107, 817, 512, 76, 803, 512, 108, 803, 512, 7734, 772, 512, - 7735, 772, 512, 76, 817, 512, 108, 817, 512, 76, 813, 512, 108, 813, 512, - 77, 769, 512, 109, 769, 512, 77, 775, 512, 109, 775, 512, 77, 803, 512, - 109, 803, 512, 78, 775, 512, 110, 775, 512, 78, 803, 512, 110, 803, 512, - 78, 817, 512, 110, 817, 512, 78, 813, 512, 110, 813, 512, 213, 769, 512, - 245, 769, 512, 213, 776, 512, 245, 776, 512, 332, 768, 512, 333, 768, - 512, 332, 769, 512, 333, 769, 512, 80, 769, 512, 112, 769, 512, 80, 775, - 512, 112, 775, 512, 82, 775, 512, 114, 775, 512, 82, 803, 512, 114, 803, - 512, 7770, 772, 512, 7771, 772, 512, 82, 817, 512, 114, 817, 512, 83, - 775, 512, 115, 775, 512, 83, 803, 512, 115, 803, 512, 346, 775, 512, 347, - 775, 512, 352, 775, 512, 353, 775, 512, 7778, 775, 512, 7779, 775, 512, - 84, 775, 512, 116, 775, 512, 84, 803, 512, 116, 803, 512, 84, 817, 512, - 116, 817, 512, 84, 813, 512, 116, 813, 512, 85, 804, 512, 117, 804, 512, - 85, 816, 512, 117, 816, 512, 85, 813, 512, 117, 813, 512, 360, 769, 512, - 361, 769, 512, 362, 776, 512, 363, 776, 512, 86, 771, 512, 118, 771, 512, - 86, 803, 512, 118, 803, 512, 87, 768, 512, 119, 768, 512, 87, 769, 512, - 119, 769, 512, 87, 776, 512, 119, 776, 512, 87, 775, 512, 119, 775, 512, - 87, 803, 512, 119, 803, 512, 88, 775, 512, 120, 775, 512, 88, 776, 512, - 120, 776, 512, 89, 775, 512, 121, 775, 512, 90, 770, 512, 122, 770, 512, - 90, 803, 512, 122, 803, 512, 90, 817, 512, 122, 817, 512, 104, 817, 512, - 116, 776, 512, 119, 778, 512, 121, 778, 514, 97, 702, 512, 383, 775, 512, - 65, 803, 512, 97, 803, 512, 65, 777, 512, 97, 777, 512, 194, 769, 512, - 226, 769, 512, 194, 768, 512, 226, 768, 512, 194, 777, 512, 226, 777, - 512, 194, 771, 512, 226, 771, 512, 7840, 770, 512, 7841, 770, 512, 258, - 769, 512, 259, 769, 512, 258, 768, 512, 259, 768, 512, 258, 777, 512, - 259, 777, 512, 258, 771, 512, 259, 771, 512, 7840, 774, 512, 7841, 774, - 512, 69, 803, 512, 101, 803, 512, 69, 777, 512, 101, 777, 512, 69, 771, - 512, 101, 771, 512, 202, 769, 512, 234, 769, 512, 202, 768, 512, 234, - 768, 512, 202, 777, 512, 234, 777, 512, 202, 771, 512, 234, 771, 512, - 7864, 770, 512, 7865, 770, 512, 73, 777, 512, 105, 777, 512, 73, 803, - 512, 105, 803, 512, 79, 803, 512, 111, 803, 512, 79, 777, 512, 111, 777, - 512, 212, 769, 512, 244, 769, 512, 212, 768, 512, 244, 768, 512, 212, - 777, 512, 244, 777, 512, 212, 771, 512, 244, 771, 512, 7884, 770, 512, - 7885, 770, 512, 416, 769, 512, 417, 769, 512, 416, 768, 512, 417, 768, - 512, 416, 777, 512, 417, 777, 512, 416, 771, 512, 417, 771, 512, 416, - 803, 512, 417, 803, 512, 85, 803, 512, 117, 803, 512, 85, 777, 512, 117, - 777, 512, 431, 769, 512, 432, 769, 512, 431, 768, 512, 432, 768, 512, - 431, 777, 512, 432, 777, 512, 431, 771, 512, 432, 771, 512, 431, 803, - 512, 432, 803, 512, 89, 768, 512, 121, 768, 512, 89, 803, 512, 121, 803, - 512, 89, 777, 512, 121, 777, 512, 89, 771, 512, 121, 771, 512, 945, 787, - 512, 945, 788, 512, 7936, 768, 512, 7937, 768, 512, 7936, 769, 512, 7937, - 769, 512, 7936, 834, 512, 7937, 834, 512, 913, 787, 512, 913, 788, 512, - 7944, 768, 512, 7945, 768, 512, 7944, 769, 512, 7945, 769, 512, 7944, - 834, 512, 7945, 834, 512, 949, 787, 512, 949, 788, 512, 7952, 768, 512, - 7953, 768, 512, 7952, 769, 512, 7953, 769, 512, 917, 787, 512, 917, 788, - 512, 7960, 768, 512, 7961, 768, 512, 7960, 769, 512, 7961, 769, 512, 951, - 787, 512, 951, 788, 512, 7968, 768, 512, 7969, 768, 512, 7968, 769, 512, - 7969, 769, 512, 7968, 834, 512, 7969, 834, 512, 919, 787, 512, 919, 788, - 512, 7976, 768, 512, 7977, 768, 512, 7976, 769, 512, 7977, 769, 512, - 7976, 834, 512, 7977, 834, 512, 953, 787, 512, 953, 788, 512, 7984, 768, - 512, 7985, 768, 512, 7984, 769, 512, 7985, 769, 512, 7984, 834, 512, + 59, 512, 168, 769, 512, 913, 769, 256, 183, 512, 917, 769, 512, 919, 769, + 512, 921, 769, 512, 927, 769, 512, 933, 769, 512, 937, 769, 512, 970, + 769, 512, 921, 776, 512, 933, 776, 512, 945, 769, 512, 949, 769, 512, + 951, 769, 512, 953, 769, 512, 971, 769, 512, 953, 776, 512, 965, 776, + 512, 959, 769, 512, 965, 769, 512, 969, 769, 258, 946, 258, 952, 258, + 933, 512, 978, 769, 512, 978, 776, 258, 966, 258, 960, 258, 954, 258, + 961, 258, 962, 258, 920, 258, 949, 258, 931, 512, 1045, 768, 512, 1045, + 776, 512, 1043, 769, 512, 1030, 776, 512, 1050, 769, 512, 1048, 768, 512, + 1059, 774, 512, 1048, 774, 512, 1080, 774, 512, 1077, 768, 512, 1077, + 776, 512, 1075, 769, 512, 1110, 776, 512, 1082, 769, 512, 1080, 768, 512, + 1091, 774, 512, 1140, 783, 512, 1141, 783, 512, 1046, 774, 512, 1078, + 774, 512, 1040, 774, 512, 1072, 774, 512, 1040, 776, 512, 1072, 776, 512, + 1045, 774, 512, 1077, 774, 512, 1240, 776, 512, 1241, 776, 512, 1046, + 776, 512, 1078, 776, 512, 1047, 776, 512, 1079, 776, 512, 1048, 772, 512, + 1080, 772, 512, 1048, 776, 512, 1080, 776, 512, 1054, 776, 512, 1086, + 776, 512, 1256, 776, 512, 1257, 776, 512, 1069, 776, 512, 1101, 776, 512, + 1059, 772, 512, 1091, 772, 512, 1059, 776, 512, 1091, 776, 512, 1059, + 779, 512, 1091, 779, 512, 1063, 776, 512, 1095, 776, 512, 1067, 776, 512, + 1099, 776, 514, 1381, 1410, 512, 1575, 1619, 512, 1575, 1620, 512, 1608, + 1620, 512, 1575, 1621, 512, 1610, 1620, 514, 1575, 1652, 514, 1608, 1652, + 514, 1735, 1652, 514, 1610, 1652, 512, 1749, 1620, 512, 1729, 1620, 512, + 1746, 1620, 512, 2344, 2364, 512, 2352, 2364, 512, 2355, 2364, 512, 2325, + 2364, 512, 2326, 2364, 512, 2327, 2364, 512, 2332, 2364, 512, 2337, 2364, + 512, 2338, 2364, 512, 2347, 2364, 512, 2351, 2364, 512, 2503, 2494, 512, + 2503, 2519, 512, 2465, 2492, 512, 2466, 2492, 512, 2479, 2492, 512, 2610, + 2620, 512, 2616, 2620, 512, 2582, 2620, 512, 2583, 2620, 512, 2588, 2620, + 512, 2603, 2620, 512, 2887, 2902, 512, 2887, 2878, 512, 2887, 2903, 512, + 2849, 2876, 512, 2850, 2876, 512, 2962, 3031, 512, 3014, 3006, 512, 3015, + 3006, 512, 3014, 3031, 512, 3142, 3158, 512, 3263, 3285, 512, 3270, 3285, + 512, 3270, 3286, 512, 3270, 3266, 512, 3274, 3285, 512, 3398, 3390, 512, + 3399, 3390, 512, 3398, 3415, 512, 3545, 3530, 512, 3545, 3535, 512, 3548, + 3530, 512, 3545, 3551, 514, 3661, 3634, 514, 3789, 3762, 514, 3755, 3737, + 514, 3755, 3745, 257, 3851, 512, 3906, 4023, 512, 3916, 4023, 512, 3921, + 4023, 512, 3926, 4023, 512, 3931, 4023, 512, 3904, 4021, 512, 3953, 3954, + 512, 3953, 3956, 512, 4018, 3968, 514, 4018, 3969, 512, 4019, 3968, 514, + 4019, 3969, 512, 3953, 3968, 512, 3986, 4023, 512, 3996, 4023, 512, 4001, + 4023, 512, 4006, 4023, 512, 4011, 4023, 512, 3984, 4021, 512, 4133, 4142, + 259, 4316, 512, 6917, 6965, 512, 6919, 6965, 512, 6921, 6965, 512, 6923, + 6965, 512, 6925, 6965, 512, 6929, 6965, 512, 6970, 6965, 512, 6972, 6965, + 512, 6974, 6965, 512, 6975, 6965, 512, 6978, 6965, 259, 65, 259, 198, + 259, 66, 259, 68, 259, 69, 259, 398, 259, 71, 259, 72, 259, 73, 259, 74, + 259, 75, 259, 76, 259, 77, 259, 78, 259, 79, 259, 546, 259, 80, 259, 82, + 259, 84, 259, 85, 259, 87, 259, 592, 259, 593, 259, 7426, 259, 98, 259, + 100, 259, 101, 259, 601, 259, 603, 259, 604, 259, 103, 259, 107, 259, + 109, 259, 331, 259, 596, 259, 7446, 259, 7447, 259, 112, 259, 116, 259, + 117, 259, 7453, 259, 623, 259, 118, 259, 7461, 259, 946, 259, 947, 259, + 948, 259, 966, 259, 967, 261, 105, 261, 114, 261, 117, 261, 118, 261, + 946, 261, 947, 261, 961, 261, 966, 261, 967, 259, 1085, 259, 594, 259, + 99, 259, 597, 259, 240, 259, 102, 259, 607, 259, 609, 259, 613, 259, 616, + 259, 617, 259, 618, 259, 7547, 259, 669, 259, 621, 259, 7557, 259, 671, + 259, 625, 259, 624, 259, 626, 259, 627, 259, 628, 259, 629, 259, 632, + 259, 642, 259, 643, 259, 427, 259, 649, 259, 650, 259, 7452, 259, 651, + 259, 652, 259, 122, 259, 656, 259, 657, 259, 658, 259, 952, 512, 65, 805, + 512, 97, 805, 512, 66, 775, 512, 98, 775, 512, 66, 803, 512, 98, 803, + 512, 66, 817, 512, 98, 817, 512, 199, 769, 512, 231, 769, 512, 68, 775, + 512, 100, 775, 512, 68, 803, 512, 100, 803, 512, 68, 817, 512, 100, 817, + 512, 68, 807, 512, 100, 807, 512, 68, 813, 512, 100, 813, 512, 274, 768, + 512, 275, 768, 512, 274, 769, 512, 275, 769, 512, 69, 813, 512, 101, 813, + 512, 69, 816, 512, 101, 816, 512, 552, 774, 512, 553, 774, 512, 70, 775, + 512, 102, 775, 512, 71, 772, 512, 103, 772, 512, 72, 775, 512, 104, 775, + 512, 72, 803, 512, 104, 803, 512, 72, 776, 512, 104, 776, 512, 72, 807, + 512, 104, 807, 512, 72, 814, 512, 104, 814, 512, 73, 816, 512, 105, 816, + 512, 207, 769, 512, 239, 769, 512, 75, 769, 512, 107, 769, 512, 75, 803, + 512, 107, 803, 512, 75, 817, 512, 107, 817, 512, 76, 803, 512, 108, 803, + 512, 7734, 772, 512, 7735, 772, 512, 76, 817, 512, 108, 817, 512, 76, + 813, 512, 108, 813, 512, 77, 769, 512, 109, 769, 512, 77, 775, 512, 109, + 775, 512, 77, 803, 512, 109, 803, 512, 78, 775, 512, 110, 775, 512, 78, + 803, 512, 110, 803, 512, 78, 817, 512, 110, 817, 512, 78, 813, 512, 110, + 813, 512, 213, 769, 512, 245, 769, 512, 213, 776, 512, 245, 776, 512, + 332, 768, 512, 333, 768, 512, 332, 769, 512, 333, 769, 512, 80, 769, 512, + 112, 769, 512, 80, 775, 512, 112, 775, 512, 82, 775, 512, 114, 775, 512, + 82, 803, 512, 114, 803, 512, 7770, 772, 512, 7771, 772, 512, 82, 817, + 512, 114, 817, 512, 83, 775, 512, 115, 775, 512, 83, 803, 512, 115, 803, + 512, 346, 775, 512, 347, 775, 512, 352, 775, 512, 353, 775, 512, 7778, + 775, 512, 7779, 775, 512, 84, 775, 512, 116, 775, 512, 84, 803, 512, 116, + 803, 512, 84, 817, 512, 116, 817, 512, 84, 813, 512, 116, 813, 512, 85, + 804, 512, 117, 804, 512, 85, 816, 512, 117, 816, 512, 85, 813, 512, 117, + 813, 512, 360, 769, 512, 361, 769, 512, 362, 776, 512, 363, 776, 512, 86, + 771, 512, 118, 771, 512, 86, 803, 512, 118, 803, 512, 87, 768, 512, 119, + 768, 512, 87, 769, 512, 119, 769, 512, 87, 776, 512, 119, 776, 512, 87, + 775, 512, 119, 775, 512, 87, 803, 512, 119, 803, 512, 88, 775, 512, 120, + 775, 512, 88, 776, 512, 120, 776, 512, 89, 775, 512, 121, 775, 512, 90, + 770, 512, 122, 770, 512, 90, 803, 512, 122, 803, 512, 90, 817, 512, 122, + 817, 512, 104, 817, 512, 116, 776, 512, 119, 778, 512, 121, 778, 514, 97, + 702, 512, 383, 775, 512, 65, 803, 512, 97, 803, 512, 65, 777, 512, 97, + 777, 512, 194, 769, 512, 226, 769, 512, 194, 768, 512, 226, 768, 512, + 194, 777, 512, 226, 777, 512, 194, 771, 512, 226, 771, 512, 7840, 770, + 512, 7841, 770, 512, 258, 769, 512, 259, 769, 512, 258, 768, 512, 259, + 768, 512, 258, 777, 512, 259, 777, 512, 258, 771, 512, 259, 771, 512, + 7840, 774, 512, 7841, 774, 512, 69, 803, 512, 101, 803, 512, 69, 777, + 512, 101, 777, 512, 69, 771, 512, 101, 771, 512, 202, 769, 512, 234, 769, + 512, 202, 768, 512, 234, 768, 512, 202, 777, 512, 234, 777, 512, 202, + 771, 512, 234, 771, 512, 7864, 770, 512, 7865, 770, 512, 73, 777, 512, + 105, 777, 512, 73, 803, 512, 105, 803, 512, 79, 803, 512, 111, 803, 512, + 79, 777, 512, 111, 777, 512, 212, 769, 512, 244, 769, 512, 212, 768, 512, + 244, 768, 512, 212, 777, 512, 244, 777, 512, 212, 771, 512, 244, 771, + 512, 7884, 770, 512, 7885, 770, 512, 416, 769, 512, 417, 769, 512, 416, + 768, 512, 417, 768, 512, 416, 777, 512, 417, 777, 512, 416, 771, 512, + 417, 771, 512, 416, 803, 512, 417, 803, 512, 85, 803, 512, 117, 803, 512, + 85, 777, 512, 117, 777, 512, 431, 769, 512, 432, 769, 512, 431, 768, 512, + 432, 768, 512, 431, 777, 512, 432, 777, 512, 431, 771, 512, 432, 771, + 512, 431, 803, 512, 432, 803, 512, 89, 768, 512, 121, 768, 512, 89, 803, + 512, 121, 803, 512, 89, 777, 512, 121, 777, 512, 89, 771, 512, 121, 771, + 512, 945, 787, 512, 945, 788, 512, 7936, 768, 512, 7937, 768, 512, 7936, + 769, 512, 7937, 769, 512, 7936, 834, 512, 7937, 834, 512, 913, 787, 512, + 913, 788, 512, 7944, 768, 512, 7945, 768, 512, 7944, 769, 512, 7945, 769, + 512, 7944, 834, 512, 7945, 834, 512, 949, 787, 512, 949, 788, 512, 7952, + 768, 512, 7953, 768, 512, 7952, 769, 512, 7953, 769, 512, 917, 787, 512, + 917, 788, 512, 7960, 768, 512, 7961, 768, 512, 7960, 769, 512, 7961, 769, + 512, 951, 787, 512, 951, 788, 512, 7968, 768, 512, 7969, 768, 512, 7968, + 769, 512, 7969, 769, 512, 7968, 834, 512, 7969, 834, 512, 919, 787, 512, + 919, 788, 512, 7976, 768, 512, 7977, 768, 512, 7976, 769, 512, 7977, 769, + 512, 7976, 834, 512, 7977, 834, 512, 953, 787, 512, 953, 788, 512, 7984, + 768, 512, 7985, 768, 512, 7984, 769, 512, 7985, 769, 512, 7984, 834, 512, 7985, 834, 512, 921, 787, 512, 921, 788, 512, 7992, 768, 512, 7993, 768, 512, 7992, 769, 512, 7993, 769, 512, 7992, 834, 512, 7993, 834, 512, 959, 787, 512, 959, 788, 512, 8000, 768, 512, 8001, 768, 512, 8000, 769, 512, @@ -3561,124 +3587,121 @@ static const unsigned int decomp_data[] = { 8045, 837, 512, 8046, 837, 512, 8047, 837, 512, 945, 774, 512, 945, 772, 512, 8048, 837, 512, 945, 837, 512, 940, 837, 512, 945, 834, 512, 8118, 837, 512, 913, 774, 512, 913, 772, 512, 913, 768, 256, 902, 512, 913, - 837, 514, 32, 787, 256, 953, 514, 32, 787, 514, 32, 834, 512, 168, 834, - 512, 8052, 837, 512, 951, 837, 512, 942, 837, 512, 951, 834, 512, 8134, - 837, 512, 917, 768, 256, 904, 512, 919, 768, 256, 905, 512, 919, 837, - 512, 8127, 768, 512, 8127, 769, 512, 8127, 834, 512, 953, 774, 512, 953, - 772, 512, 970, 768, 256, 912, 512, 953, 834, 512, 970, 834, 512, 921, - 774, 512, 921, 772, 512, 921, 768, 256, 906, 512, 8190, 768, 512, 8190, - 769, 512, 8190, 834, 512, 965, 774, 512, 965, 772, 512, 971, 768, 256, - 944, 512, 961, 787, 512, 961, 788, 512, 965, 834, 512, 971, 834, 512, - 933, 774, 512, 933, 772, 512, 933, 768, 256, 910, 512, 929, 788, 512, - 168, 768, 256, 901, 256, 96, 512, 8060, 837, 512, 969, 837, 512, 974, - 837, 512, 969, 834, 512, 8182, 837, 512, 927, 768, 256, 908, 512, 937, - 768, 256, 911, 512, 937, 837, 256, 180, 514, 32, 788, 256, 8194, 256, - 8195, 258, 32, 258, 32, 258, 32, 258, 32, 258, 32, 257, 32, 258, 32, 258, - 32, 258, 32, 257, 8208, 514, 32, 819, 258, 46, 514, 46, 46, 770, 46, 46, - 46, 257, 32, 514, 8242, 8242, 770, 8242, 8242, 8242, 514, 8245, 8245, - 770, 8245, 8245, 8245, 514, 33, 33, 514, 32, 773, 514, 63, 63, 514, 63, - 33, 514, 33, 63, 1026, 8242, 8242, 8242, 8242, 258, 32, 259, 48, 259, - 105, 259, 52, 259, 53, 259, 54, 259, 55, 259, 56, 259, 57, 259, 43, 259, - 8722, 259, 61, 259, 40, 259, 41, 259, 110, 261, 48, 261, 49, 261, 50, - 261, 51, 261, 52, 261, 53, 261, 54, 261, 55, 261, 56, 261, 57, 261, 43, - 261, 8722, 261, 61, 261, 40, 261, 41, 261, 97, 261, 101, 261, 111, 261, - 120, 261, 601, 261, 104, 261, 107, 261, 108, 261, 109, 261, 110, 261, - 112, 261, 115, 261, 116, 514, 82, 115, 770, 97, 47, 99, 770, 97, 47, 115, - 262, 67, 514, 176, 67, 770, 99, 47, 111, 770, 99, 47, 117, 258, 400, 514, - 176, 70, 262, 103, 262, 72, 262, 72, 262, 72, 262, 104, 262, 295, 262, - 73, 262, 73, 262, 76, 262, 108, 262, 78, 514, 78, 111, 262, 80, 262, 81, - 262, 82, 262, 82, 262, 82, 515, 83, 77, 770, 84, 69, 76, 515, 84, 77, - 262, 90, 256, 937, 262, 90, 256, 75, 256, 197, 262, 66, 262, 67, 262, - 101, 262, 69, 262, 70, 262, 77, 262, 111, 258, 1488, 258, 1489, 258, - 1490, 258, 1491, 262, 105, 770, 70, 65, 88, 262, 960, 262, 947, 262, 915, - 262, 928, 262, 8721, 262, 68, 262, 100, 262, 101, 262, 105, 262, 106, - 772, 49, 8260, 55, 772, 49, 8260, 57, 1028, 49, 8260, 49, 48, 772, 49, - 8260, 51, 772, 50, 8260, 51, 772, 49, 8260, 53, 772, 50, 8260, 53, 772, - 51, 8260, 53, 772, 52, 8260, 53, 772, 49, 8260, 54, 772, 53, 8260, 54, - 772, 49, 8260, 56, 772, 51, 8260, 56, 772, 53, 8260, 56, 772, 55, 8260, - 56, 516, 49, 8260, 258, 73, 514, 73, 73, 770, 73, 73, 73, 514, 73, 86, - 258, 86, 514, 86, 73, 770, 86, 73, 73, 1026, 86, 73, 73, 73, 514, 73, 88, - 258, 88, 514, 88, 73, 770, 88, 73, 73, 258, 76, 258, 67, 258, 68, 258, - 77, 258, 105, 514, 105, 105, 770, 105, 105, 105, 514, 105, 118, 258, 118, - 514, 118, 105, 770, 118, 105, 105, 1026, 118, 105, 105, 105, 514, 105, - 120, 258, 120, 514, 120, 105, 770, 120, 105, 105, 258, 108, 258, 99, 258, - 100, 258, 109, 772, 48, 8260, 51, 512, 8592, 824, 512, 8594, 824, 512, - 8596, 824, 512, 8656, 824, 512, 8660, 824, 512, 8658, 824, 512, 8707, - 824, 512, 8712, 824, 512, 8715, 824, 512, 8739, 824, 512, 8741, 824, 514, - 8747, 8747, 770, 8747, 8747, 8747, 514, 8750, 8750, 770, 8750, 8750, - 8750, 512, 8764, 824, 512, 8771, 824, 512, 8773, 824, 512, 8776, 824, - 512, 61, 824, 512, 8801, 824, 512, 8781, 824, 512, 60, 824, 512, 62, 824, - 512, 8804, 824, 512, 8805, 824, 512, 8818, 824, 512, 8819, 824, 512, - 8822, 824, 512, 8823, 824, 512, 8826, 824, 512, 8827, 824, 512, 8834, - 824, 512, 8835, 824, 512, 8838, 824, 512, 8839, 824, 512, 8866, 824, 512, - 8872, 824, 512, 8873, 824, 512, 8875, 824, 512, 8828, 824, 512, 8829, - 824, 512, 8849, 824, 512, 8850, 824, 512, 8882, 824, 512, 8883, 824, 512, - 8884, 824, 512, 8885, 824, 256, 12296, 256, 12297, 263, 49, 263, 50, 263, - 51, 263, 52, 263, 53, 263, 54, 263, 55, 263, 56, 263, 57, 519, 49, 48, - 519, 49, 49, 519, 49, 50, 519, 49, 51, 519, 49, 52, 519, 49, 53, 519, 49, - 54, 519, 49, 55, 519, 49, 56, 519, 49, 57, 519, 50, 48, 770, 40, 49, 41, - 770, 40, 50, 41, 770, 40, 51, 41, 770, 40, 52, 41, 770, 40, 53, 41, 770, - 40, 54, 41, 770, 40, 55, 41, 770, 40, 56, 41, 770, 40, 57, 41, 1026, 40, - 49, 48, 41, 1026, 40, 49, 49, 41, 1026, 40, 49, 50, 41, 1026, 40, 49, 51, - 41, 1026, 40, 49, 52, 41, 1026, 40, 49, 53, 41, 1026, 40, 49, 54, 41, - 1026, 40, 49, 55, 41, 1026, 40, 49, 56, 41, 1026, 40, 49, 57, 41, 1026, - 40, 50, 48, 41, 514, 49, 46, 514, 50, 46, 514, 51, 46, 514, 52, 46, 514, - 53, 46, 514, 54, 46, 514, 55, 46, 514, 56, 46, 514, 57, 46, 770, 49, 48, - 46, 770, 49, 49, 46, 770, 49, 50, 46, 770, 49, 51, 46, 770, 49, 52, 46, - 770, 49, 53, 46, 770, 49, 54, 46, 770, 49, 55, 46, 770, 49, 56, 46, 770, - 49, 57, 46, 770, 50, 48, 46, 770, 40, 97, 41, 770, 40, 98, 41, 770, 40, - 99, 41, 770, 40, 100, 41, 770, 40, 101, 41, 770, 40, 102, 41, 770, 40, - 103, 41, 770, 40, 104, 41, 770, 40, 105, 41, 770, 40, 106, 41, 770, 40, - 107, 41, 770, 40, 108, 41, 770, 40, 109, 41, 770, 40, 110, 41, 770, 40, - 111, 41, 770, 40, 112, 41, 770, 40, 113, 41, 770, 40, 114, 41, 770, 40, - 115, 41, 770, 40, 116, 41, 770, 40, 117, 41, 770, 40, 118, 41, 770, 40, - 119, 41, 770, 40, 120, 41, 770, 40, 121, 41, 770, 40, 122, 41, 263, 65, - 263, 66, 263, 67, 263, 68, 263, 69, 263, 70, 263, 71, 263, 72, 263, 73, - 263, 74, 263, 75, 263, 76, 263, 77, 263, 78, 263, 79, 263, 80, 263, 81, - 263, 82, 263, 83, 263, 84, 263, 85, 263, 86, 263, 87, 263, 88, 263, 89, - 263, 90, 263, 97, 263, 98, 263, 99, 263, 100, 263, 101, 263, 102, 263, - 103, 263, 104, 263, 105, 263, 106, 263, 107, 263, 108, 263, 109, 263, - 110, 263, 111, 263, 112, 263, 113, 263, 114, 263, 115, 263, 116, 263, - 117, 263, 118, 263, 119, 263, 120, 263, 121, 263, 122, 263, 48, 1026, - 8747, 8747, 8747, 8747, 770, 58, 58, 61, 514, 61, 61, 770, 61, 61, 61, - 512, 10973, 824, 261, 106, 259, 86, 259, 11617, 258, 27597, 258, 40863, - 258, 19968, 258, 20008, 258, 20022, 258, 20031, 258, 20057, 258, 20101, - 258, 20108, 258, 20128, 258, 20154, 258, 20799, 258, 20837, 258, 20843, - 258, 20866, 258, 20886, 258, 20907, 258, 20960, 258, 20981, 258, 20992, - 258, 21147, 258, 21241, 258, 21269, 258, 21274, 258, 21304, 258, 21313, - 258, 21340, 258, 21353, 258, 21378, 258, 21430, 258, 21448, 258, 21475, - 258, 22231, 258, 22303, 258, 22763, 258, 22786, 258, 22794, 258, 22805, - 258, 22823, 258, 22899, 258, 23376, 258, 23424, 258, 23544, 258, 23567, - 258, 23586, 258, 23608, 258, 23662, 258, 23665, 258, 24027, 258, 24037, - 258, 24049, 258, 24062, 258, 24178, 258, 24186, 258, 24191, 258, 24308, - 258, 24318, 258, 24331, 258, 24339, 258, 24400, 258, 24417, 258, 24435, - 258, 24515, 258, 25096, 258, 25142, 258, 25163, 258, 25903, 258, 25908, - 258, 25991, 258, 26007, 258, 26020, 258, 26041, 258, 26080, 258, 26085, - 258, 26352, 258, 26376, 258, 26408, 258, 27424, 258, 27490, 258, 27513, - 258, 27571, 258, 27595, 258, 27604, 258, 27611, 258, 27663, 258, 27668, - 258, 27700, 258, 28779, 258, 29226, 258, 29238, 258, 29243, 258, 29247, - 258, 29255, 258, 29273, 258, 29275, 258, 29356, 258, 29572, 258, 29577, - 258, 29916, 258, 29926, 258, 29976, 258, 29983, 258, 29992, 258, 30000, - 258, 30091, 258, 30098, 258, 30326, 258, 30333, 258, 30382, 258, 30399, - 258, 30446, 258, 30683, 258, 30690, 258, 30707, 258, 31034, 258, 31160, - 258, 31166, 258, 31348, 258, 31435, 258, 31481, 258, 31859, 258, 31992, - 258, 32566, 258, 32593, 258, 32650, 258, 32701, 258, 32769, 258, 32780, - 258, 32786, 258, 32819, 258, 32895, 258, 32905, 258, 33251, 258, 33258, - 258, 33267, 258, 33276, 258, 33292, 258, 33307, 258, 33311, 258, 33390, - 258, 33394, 258, 33400, 258, 34381, 258, 34411, 258, 34880, 258, 34892, - 258, 34915, 258, 35198, 258, 35211, 258, 35282, 258, 35328, 258, 35895, - 258, 35910, 258, 35925, 258, 35960, 258, 35997, 258, 36196, 258, 36208, - 258, 36275, 258, 36523, 258, 36554, 258, 36763, 258, 36784, 258, 36789, - 258, 37009, 258, 37193, 258, 37318, 258, 37324, 258, 37329, 258, 38263, - 258, 38272, 258, 38428, 258, 38582, 258, 38585, 258, 38632, 258, 38737, - 258, 38750, 258, 38754, 258, 38761, 258, 38859, 258, 38893, 258, 38899, - 258, 38913, 258, 39080, 258, 39131, 258, 39135, 258, 39318, 258, 39321, - 258, 39340, 258, 39592, 258, 39640, 258, 39647, 258, 39717, 258, 39727, - 258, 39730, 258, 39740, 258, 39770, 258, 40165, 258, 40565, 258, 40575, - 258, 40613, 258, 40635, 258, 40643, 258, 40653, 258, 40657, 258, 40697, - 258, 40701, 258, 40718, 258, 40723, 258, 40736, 258, 40763, 258, 40778, - 258, 40786, 258, 40845, 258, 40860, 258, 40864, 264, 32, 258, 12306, 258, - 21313, 258, 21316, 258, 21317, 512, 12363, 12441, 512, 12365, 12441, 512, + 837, 514, 32, 787, 256, 953, 514, 32, 834, 512, 168, 834, 512, 8052, 837, + 512, 951, 837, 512, 942, 837, 512, 951, 834, 512, 8134, 837, 512, 917, + 768, 256, 904, 512, 919, 768, 256, 905, 512, 919, 837, 512, 8127, 768, + 512, 8127, 769, 512, 8127, 834, 512, 953, 774, 512, 953, 772, 512, 970, + 768, 256, 912, 512, 953, 834, 512, 970, 834, 512, 921, 774, 512, 921, + 772, 512, 921, 768, 256, 906, 512, 8190, 768, 512, 8190, 769, 512, 8190, + 834, 512, 965, 774, 512, 965, 772, 512, 971, 768, 256, 944, 512, 961, + 787, 512, 961, 788, 512, 965, 834, 512, 971, 834, 512, 933, 774, 512, + 933, 772, 512, 933, 768, 256, 910, 512, 929, 788, 512, 168, 768, 256, + 901, 256, 96, 512, 8060, 837, 512, 969, 837, 512, 974, 837, 512, 969, + 834, 512, 8182, 837, 512, 927, 768, 256, 908, 512, 937, 768, 256, 911, + 512, 937, 837, 256, 180, 514, 32, 788, 256, 8194, 256, 8195, 258, 32, + 257, 8208, 514, 32, 819, 258, 46, 514, 46, 46, 770, 46, 46, 46, 514, + 8242, 8242, 770, 8242, 8242, 8242, 514, 8245, 8245, 770, 8245, 8245, + 8245, 514, 33, 33, 514, 32, 773, 514, 63, 63, 514, 63, 33, 514, 33, 63, + 1026, 8242, 8242, 8242, 8242, 259, 48, 259, 105, 259, 52, 259, 53, 259, + 54, 259, 55, 259, 56, 259, 57, 259, 43, 259, 8722, 259, 61, 259, 40, 259, + 41, 259, 110, 261, 48, 261, 49, 261, 50, 261, 51, 261, 52, 261, 53, 261, + 54, 261, 55, 261, 56, 261, 57, 261, 43, 261, 8722, 261, 61, 261, 40, 261, + 41, 261, 97, 261, 101, 261, 111, 261, 120, 261, 601, 261, 104, 261, 107, + 261, 108, 261, 109, 261, 110, 261, 112, 261, 115, 261, 116, 514, 82, 115, + 770, 97, 47, 99, 770, 97, 47, 115, 262, 67, 514, 176, 67, 770, 99, 47, + 111, 770, 99, 47, 117, 258, 400, 514, 176, 70, 262, 103, 262, 72, 262, + 104, 262, 295, 262, 73, 262, 76, 262, 108, 262, 78, 514, 78, 111, 262, + 80, 262, 81, 262, 82, 515, 83, 77, 770, 84, 69, 76, 515, 84, 77, 262, 90, + 256, 937, 256, 75, 256, 197, 262, 66, 262, 101, 262, 69, 262, 70, 262, + 77, 262, 111, 258, 1488, 258, 1489, 258, 1490, 258, 1491, 262, 105, 770, + 70, 65, 88, 262, 960, 262, 947, 262, 915, 262, 928, 262, 8721, 262, 68, + 262, 100, 262, 106, 772, 49, 8260, 55, 772, 49, 8260, 57, 1028, 49, 8260, + 49, 48, 772, 49, 8260, 51, 772, 50, 8260, 51, 772, 49, 8260, 53, 772, 50, + 8260, 53, 772, 51, 8260, 53, 772, 52, 8260, 53, 772, 49, 8260, 54, 772, + 53, 8260, 54, 772, 49, 8260, 56, 772, 51, 8260, 56, 772, 53, 8260, 56, + 772, 55, 8260, 56, 516, 49, 8260, 258, 73, 514, 73, 73, 770, 73, 73, 73, + 514, 73, 86, 258, 86, 514, 86, 73, 770, 86, 73, 73, 1026, 86, 73, 73, 73, + 514, 73, 88, 258, 88, 514, 88, 73, 770, 88, 73, 73, 258, 76, 258, 67, + 258, 68, 258, 77, 258, 105, 514, 105, 105, 770, 105, 105, 105, 514, 105, + 118, 258, 118, 514, 118, 105, 770, 118, 105, 105, 1026, 118, 105, 105, + 105, 514, 105, 120, 258, 120, 514, 120, 105, 770, 120, 105, 105, 258, + 108, 258, 99, 258, 100, 258, 109, 772, 48, 8260, 51, 512, 8592, 824, 512, + 8594, 824, 512, 8596, 824, 512, 8656, 824, 512, 8660, 824, 512, 8658, + 824, 512, 8707, 824, 512, 8712, 824, 512, 8715, 824, 512, 8739, 824, 512, + 8741, 824, 514, 8747, 8747, 770, 8747, 8747, 8747, 514, 8750, 8750, 770, + 8750, 8750, 8750, 512, 8764, 824, 512, 8771, 824, 512, 8773, 824, 512, + 8776, 824, 512, 61, 824, 512, 8801, 824, 512, 8781, 824, 512, 60, 824, + 512, 62, 824, 512, 8804, 824, 512, 8805, 824, 512, 8818, 824, 512, 8819, + 824, 512, 8822, 824, 512, 8823, 824, 512, 8826, 824, 512, 8827, 824, 512, + 8834, 824, 512, 8835, 824, 512, 8838, 824, 512, 8839, 824, 512, 8866, + 824, 512, 8872, 824, 512, 8873, 824, 512, 8875, 824, 512, 8828, 824, 512, + 8829, 824, 512, 8849, 824, 512, 8850, 824, 512, 8882, 824, 512, 8883, + 824, 512, 8884, 824, 512, 8885, 824, 256, 12296, 256, 12297, 263, 49, + 263, 50, 263, 51, 263, 52, 263, 53, 263, 54, 263, 55, 263, 56, 263, 57, + 519, 49, 48, 519, 49, 49, 519, 49, 50, 519, 49, 51, 519, 49, 52, 519, 49, + 53, 519, 49, 54, 519, 49, 55, 519, 49, 56, 519, 49, 57, 519, 50, 48, 770, + 40, 49, 41, 770, 40, 50, 41, 770, 40, 51, 41, 770, 40, 52, 41, 770, 40, + 53, 41, 770, 40, 54, 41, 770, 40, 55, 41, 770, 40, 56, 41, 770, 40, 57, + 41, 1026, 40, 49, 48, 41, 1026, 40, 49, 49, 41, 1026, 40, 49, 50, 41, + 1026, 40, 49, 51, 41, 1026, 40, 49, 52, 41, 1026, 40, 49, 53, 41, 1026, + 40, 49, 54, 41, 1026, 40, 49, 55, 41, 1026, 40, 49, 56, 41, 1026, 40, 49, + 57, 41, 1026, 40, 50, 48, 41, 514, 49, 46, 514, 50, 46, 514, 51, 46, 514, + 52, 46, 514, 53, 46, 514, 54, 46, 514, 55, 46, 514, 56, 46, 514, 57, 46, + 770, 49, 48, 46, 770, 49, 49, 46, 770, 49, 50, 46, 770, 49, 51, 46, 770, + 49, 52, 46, 770, 49, 53, 46, 770, 49, 54, 46, 770, 49, 55, 46, 770, 49, + 56, 46, 770, 49, 57, 46, 770, 50, 48, 46, 770, 40, 97, 41, 770, 40, 98, + 41, 770, 40, 99, 41, 770, 40, 100, 41, 770, 40, 101, 41, 770, 40, 102, + 41, 770, 40, 103, 41, 770, 40, 104, 41, 770, 40, 105, 41, 770, 40, 106, + 41, 770, 40, 107, 41, 770, 40, 108, 41, 770, 40, 109, 41, 770, 40, 110, + 41, 770, 40, 111, 41, 770, 40, 112, 41, 770, 40, 113, 41, 770, 40, 114, + 41, 770, 40, 115, 41, 770, 40, 116, 41, 770, 40, 117, 41, 770, 40, 118, + 41, 770, 40, 119, 41, 770, 40, 120, 41, 770, 40, 121, 41, 770, 40, 122, + 41, 263, 65, 263, 66, 263, 67, 263, 68, 263, 69, 263, 70, 263, 71, 263, + 72, 263, 73, 263, 74, 263, 75, 263, 76, 263, 77, 263, 78, 263, 79, 263, + 80, 263, 81, 263, 82, 263, 83, 263, 84, 263, 85, 263, 86, 263, 87, 263, + 88, 263, 89, 263, 90, 263, 97, 263, 98, 263, 99, 263, 100, 263, 101, 263, + 102, 263, 103, 263, 104, 263, 105, 263, 106, 263, 107, 263, 108, 263, + 109, 263, 110, 263, 111, 263, 112, 263, 113, 263, 114, 263, 115, 263, + 116, 263, 117, 263, 118, 263, 119, 263, 120, 263, 121, 263, 122, 263, 48, + 1026, 8747, 8747, 8747, 8747, 770, 58, 58, 61, 514, 61, 61, 770, 61, 61, + 61, 512, 10973, 824, 261, 106, 259, 86, 259, 11617, 258, 27597, 258, + 40863, 258, 19968, 258, 20008, 258, 20022, 258, 20031, 258, 20057, 258, + 20101, 258, 20108, 258, 20128, 258, 20154, 258, 20799, 258, 20837, 258, + 20843, 258, 20866, 258, 20886, 258, 20907, 258, 20960, 258, 20981, 258, + 20992, 258, 21147, 258, 21241, 258, 21269, 258, 21274, 258, 21304, 258, + 21313, 258, 21340, 258, 21353, 258, 21378, 258, 21430, 258, 21448, 258, + 21475, 258, 22231, 258, 22303, 258, 22763, 258, 22786, 258, 22794, 258, + 22805, 258, 22823, 258, 22899, 258, 23376, 258, 23424, 258, 23544, 258, + 23567, 258, 23586, 258, 23608, 258, 23662, 258, 23665, 258, 24027, 258, + 24037, 258, 24049, 258, 24062, 258, 24178, 258, 24186, 258, 24191, 258, + 24308, 258, 24318, 258, 24331, 258, 24339, 258, 24400, 258, 24417, 258, + 24435, 258, 24515, 258, 25096, 258, 25142, 258, 25163, 258, 25903, 258, + 25908, 258, 25991, 258, 26007, 258, 26020, 258, 26041, 258, 26080, 258, + 26085, 258, 26352, 258, 26376, 258, 26408, 258, 27424, 258, 27490, 258, + 27513, 258, 27571, 258, 27595, 258, 27604, 258, 27611, 258, 27663, 258, + 27668, 258, 27700, 258, 28779, 258, 29226, 258, 29238, 258, 29243, 258, + 29247, 258, 29255, 258, 29273, 258, 29275, 258, 29356, 258, 29572, 258, + 29577, 258, 29916, 258, 29926, 258, 29976, 258, 29983, 258, 29992, 258, + 30000, 258, 30091, 258, 30098, 258, 30326, 258, 30333, 258, 30382, 258, + 30399, 258, 30446, 258, 30683, 258, 30690, 258, 30707, 258, 31034, 258, + 31160, 258, 31166, 258, 31348, 258, 31435, 258, 31481, 258, 31859, 258, + 31992, 258, 32566, 258, 32593, 258, 32650, 258, 32701, 258, 32769, 258, + 32780, 258, 32786, 258, 32819, 258, 32895, 258, 32905, 258, 33251, 258, + 33258, 258, 33267, 258, 33276, 258, 33292, 258, 33307, 258, 33311, 258, + 33390, 258, 33394, 258, 33400, 258, 34381, 258, 34411, 258, 34880, 258, + 34892, 258, 34915, 258, 35198, 258, 35211, 258, 35282, 258, 35328, 258, + 35895, 258, 35910, 258, 35925, 258, 35960, 258, 35997, 258, 36196, 258, + 36208, 258, 36275, 258, 36523, 258, 36554, 258, 36763, 258, 36784, 258, + 36789, 258, 37009, 258, 37193, 258, 37318, 258, 37324, 258, 37329, 258, + 38263, 258, 38272, 258, 38428, 258, 38582, 258, 38585, 258, 38632, 258, + 38737, 258, 38750, 258, 38754, 258, 38761, 258, 38859, 258, 38893, 258, + 38899, 258, 38913, 258, 39080, 258, 39131, 258, 39135, 258, 39318, 258, + 39321, 258, 39340, 258, 39592, 258, 39640, 258, 39647, 258, 39717, 258, + 39727, 258, 39730, 258, 39740, 258, 39770, 258, 40165, 258, 40565, 258, + 40575, 258, 40613, 258, 40635, 258, 40643, 258, 40653, 258, 40657, 258, + 40697, 258, 40701, 258, 40718, 258, 40723, 258, 40736, 258, 40763, 258, + 40778, 258, 40786, 258, 40845, 258, 40860, 258, 40864, 264, 32, 258, + 12306, 258, 21316, 258, 21317, 512, 12363, 12441, 512, 12365, 12441, 512, 12367, 12441, 512, 12369, 12441, 512, 12371, 12441, 512, 12373, 12441, 512, 12375, 12441, 512, 12377, 12441, 512, 12379, 12441, 512, 12381, 12441, 512, 12383, 12441, 512, 12385, 12441, 512, 12388, 12441, 512, @@ -3844,43 +3867,42 @@ static const unsigned int decomp_data[] = { 51, 49, 26085, 778, 103, 97, 108, 259, 1098, 259, 1100, 259, 42863, 259, 67, 259, 70, 259, 81, 259, 294, 259, 339, 259, 42791, 259, 43831, 259, 619, 259, 43858, 259, 653, 256, 35912, 256, 26356, 256, 36554, 256, - 36040, 256, 28369, 256, 20018, 256, 21477, 256, 40860, 256, 40860, 256, - 22865, 256, 37329, 256, 21895, 256, 22856, 256, 25078, 256, 30313, 256, - 32645, 256, 34367, 256, 34746, 256, 35064, 256, 37007, 256, 27138, 256, - 27931, 256, 28889, 256, 29662, 256, 33853, 256, 37226, 256, 39409, 256, - 20098, 256, 21365, 256, 27396, 256, 29211, 256, 34349, 256, 40478, 256, - 23888, 256, 28651, 256, 34253, 256, 35172, 256, 25289, 256, 33240, 256, - 34847, 256, 24266, 256, 26391, 256, 28010, 256, 29436, 256, 37070, 256, - 20358, 256, 20919, 256, 21214, 256, 25796, 256, 27347, 256, 29200, 256, - 30439, 256, 32769, 256, 34310, 256, 34396, 256, 36335, 256, 38706, 256, - 39791, 256, 40442, 256, 30860, 256, 31103, 256, 32160, 256, 33737, 256, - 37636, 256, 40575, 256, 35542, 256, 22751, 256, 24324, 256, 31840, 256, - 32894, 256, 29282, 256, 30922, 256, 36034, 256, 38647, 256, 22744, 256, - 23650, 256, 27155, 256, 28122, 256, 28431, 256, 32047, 256, 32311, 256, - 38475, 256, 21202, 256, 32907, 256, 20956, 256, 20940, 256, 31260, 256, - 32190, 256, 33777, 256, 38517, 256, 35712, 256, 25295, 256, 27138, 256, - 35582, 256, 20025, 256, 23527, 256, 24594, 256, 29575, 256, 30064, 256, - 21271, 256, 30971, 256, 20415, 256, 24489, 256, 19981, 256, 27852, 256, - 25976, 256, 32034, 256, 21443, 256, 22622, 256, 30465, 256, 33865, 256, - 35498, 256, 27578, 256, 36784, 256, 27784, 256, 25342, 256, 33509, 256, - 25504, 256, 30053, 256, 20142, 256, 20841, 256, 20937, 256, 26753, 256, - 31975, 256, 33391, 256, 35538, 256, 37327, 256, 21237, 256, 21570, 256, - 22899, 256, 24300, 256, 26053, 256, 28670, 256, 31018, 256, 38317, 256, - 39530, 256, 40599, 256, 40654, 256, 21147, 256, 26310, 256, 27511, 256, - 36706, 256, 24180, 256, 24976, 256, 25088, 256, 25754, 256, 28451, 256, - 29001, 256, 29833, 256, 31178, 256, 32244, 256, 32879, 256, 36646, 256, - 34030, 256, 36899, 256, 37706, 256, 21015, 256, 21155, 256, 21693, 256, - 28872, 256, 35010, 256, 35498, 256, 24265, 256, 24565, 256, 25467, 256, - 27566, 256, 31806, 256, 29557, 256, 20196, 256, 22265, 256, 23527, 256, - 23994, 256, 24604, 256, 29618, 256, 29801, 256, 32666, 256, 32838, 256, - 37428, 256, 38646, 256, 38728, 256, 38936, 256, 20363, 256, 31150, 256, - 37300, 256, 38584, 256, 24801, 256, 20102, 256, 20698, 256, 23534, 256, - 23615, 256, 26009, 256, 27138, 256, 29134, 256, 30274, 256, 34044, 256, - 36988, 256, 40845, 256, 26248, 256, 38446, 256, 21129, 256, 26491, 256, - 26611, 256, 27969, 256, 28316, 256, 29705, 256, 30041, 256, 30827, 256, - 32016, 256, 39006, 256, 20845, 256, 25134, 256, 38520, 256, 20523, 256, - 23833, 256, 28138, 256, 36650, 256, 24459, 256, 24900, 256, 26647, 256, - 29575, 256, 38534, 256, 21033, 256, 21519, 256, 23653, 256, 26131, 256, + 36040, 256, 28369, 256, 20018, 256, 21477, 256, 40860, 256, 22865, 256, + 37329, 256, 21895, 256, 22856, 256, 25078, 256, 30313, 256, 32645, 256, + 34367, 256, 34746, 256, 35064, 256, 37007, 256, 27138, 256, 27931, 256, + 28889, 256, 29662, 256, 33853, 256, 37226, 256, 39409, 256, 20098, 256, + 21365, 256, 27396, 256, 29211, 256, 34349, 256, 40478, 256, 23888, 256, + 28651, 256, 34253, 256, 35172, 256, 25289, 256, 33240, 256, 34847, 256, + 24266, 256, 26391, 256, 28010, 256, 29436, 256, 37070, 256, 20358, 256, + 20919, 256, 21214, 256, 25796, 256, 27347, 256, 29200, 256, 30439, 256, + 32769, 256, 34310, 256, 34396, 256, 36335, 256, 38706, 256, 39791, 256, + 40442, 256, 30860, 256, 31103, 256, 32160, 256, 33737, 256, 37636, 256, + 40575, 256, 35542, 256, 22751, 256, 24324, 256, 31840, 256, 32894, 256, + 29282, 256, 30922, 256, 36034, 256, 38647, 256, 22744, 256, 23650, 256, + 27155, 256, 28122, 256, 28431, 256, 32047, 256, 32311, 256, 38475, 256, + 21202, 256, 32907, 256, 20956, 256, 20940, 256, 31260, 256, 32190, 256, + 33777, 256, 38517, 256, 35712, 256, 25295, 256, 35582, 256, 20025, 256, + 23527, 256, 24594, 256, 29575, 256, 30064, 256, 21271, 256, 30971, 256, + 20415, 256, 24489, 256, 19981, 256, 27852, 256, 25976, 256, 32034, 256, + 21443, 256, 22622, 256, 30465, 256, 33865, 256, 35498, 256, 27578, 256, + 36784, 256, 27784, 256, 25342, 256, 33509, 256, 25504, 256, 30053, 256, + 20142, 256, 20841, 256, 20937, 256, 26753, 256, 31975, 256, 33391, 256, + 35538, 256, 37327, 256, 21237, 256, 21570, 256, 22899, 256, 24300, 256, + 26053, 256, 28670, 256, 31018, 256, 38317, 256, 39530, 256, 40599, 256, + 40654, 256, 21147, 256, 26310, 256, 27511, 256, 36706, 256, 24180, 256, + 24976, 256, 25088, 256, 25754, 256, 28451, 256, 29001, 256, 29833, 256, + 31178, 256, 32244, 256, 32879, 256, 36646, 256, 34030, 256, 36899, 256, + 37706, 256, 21015, 256, 21155, 256, 21693, 256, 28872, 256, 35010, 256, + 24265, 256, 24565, 256, 25467, 256, 27566, 256, 31806, 256, 29557, 256, + 20196, 256, 22265, 256, 23994, 256, 24604, 256, 29618, 256, 29801, 256, + 32666, 256, 32838, 256, 37428, 256, 38646, 256, 38728, 256, 38936, 256, + 20363, 256, 31150, 256, 37300, 256, 38584, 256, 24801, 256, 20102, 256, + 20698, 256, 23534, 256, 23615, 256, 26009, 256, 29134, 256, 30274, 256, + 34044, 256, 36988, 256, 40845, 256, 26248, 256, 38446, 256, 21129, 256, + 26491, 256, 26611, 256, 27969, 256, 28316, 256, 29705, 256, 30041, 256, + 30827, 256, 32016, 256, 39006, 256, 20845, 256, 25134, 256, 38520, 256, + 20523, 256, 23833, 256, 28138, 256, 36650, 256, 24459, 256, 24900, 256, + 26647, 256, 38534, 256, 21033, 256, 21519, 256, 23653, 256, 26131, 256, 26446, 256, 26792, 256, 27877, 256, 29702, 256, 30178, 256, 32633, 256, 35023, 256, 35041, 256, 37324, 256, 38626, 256, 21311, 256, 28346, 256, 21533, 256, 29136, 256, 29848, 256, 34298, 256, 38563, 256, 40023, 256, @@ -3898,65 +3920,60 @@ static const unsigned int decomp_data[] = { 25935, 256, 26082, 256, 26257, 256, 26757, 256, 28023, 256, 28186, 256, 28450, 256, 29038, 256, 29227, 256, 29730, 256, 30865, 256, 31038, 256, 31049, 256, 31048, 256, 31056, 256, 31062, 256, 31069, 256, 31117, 256, - 31118, 256, 31296, 256, 31361, 256, 31680, 256, 32244, 256, 32265, 256, - 32321, 256, 32626, 256, 32773, 256, 33261, 256, 33401, 256, 33401, 256, - 33879, 256, 35088, 256, 35222, 256, 35585, 256, 35641, 256, 36051, 256, - 36104, 256, 36790, 256, 36920, 256, 38627, 256, 38911, 256, 38971, 256, - 24693, 256, 148206, 256, 33304, 256, 20006, 256, 20917, 256, 20840, 256, - 20352, 256, 20805, 256, 20864, 256, 21191, 256, 21242, 256, 21917, 256, - 21845, 256, 21913, 256, 21986, 256, 22618, 256, 22707, 256, 22852, 256, - 22868, 256, 23138, 256, 23336, 256, 24274, 256, 24281, 256, 24425, 256, - 24493, 256, 24792, 256, 24910, 256, 24840, 256, 24974, 256, 24928, 256, - 25074, 256, 25140, 256, 25540, 256, 25628, 256, 25682, 256, 25942, 256, - 26228, 256, 26391, 256, 26395, 256, 26454, 256, 27513, 256, 27578, 256, - 27969, 256, 28379, 256, 28363, 256, 28450, 256, 28702, 256, 29038, 256, - 30631, 256, 29237, 256, 29359, 256, 29482, 256, 29809, 256, 29958, 256, - 30011, 256, 30237, 256, 30239, 256, 30410, 256, 30427, 256, 30452, 256, - 30538, 256, 30528, 256, 30924, 256, 31409, 256, 31680, 256, 31867, 256, - 32091, 256, 32244, 256, 32574, 256, 32773, 256, 33618, 256, 33775, 256, - 34681, 256, 35137, 256, 35206, 256, 35222, 256, 35519, 256, 35576, 256, - 35531, 256, 35585, 256, 35582, 256, 35565, 256, 35641, 256, 35722, 256, - 36104, 256, 36664, 256, 36978, 256, 37273, 256, 37494, 256, 38524, 256, - 38627, 256, 38742, 256, 38875, 256, 38911, 256, 38923, 256, 38971, 256, - 39698, 256, 40860, 256, 141386, 256, 141380, 256, 144341, 256, 15261, - 256, 16408, 256, 16441, 256, 152137, 256, 154832, 256, 163539, 256, - 40771, 256, 40846, 514, 102, 102, 514, 102, 105, 514, 102, 108, 770, 102, - 102, 105, 770, 102, 102, 108, 514, 383, 116, 514, 115, 116, 514, 1396, - 1398, 514, 1396, 1381, 514, 1396, 1387, 514, 1406, 1398, 514, 1396, 1389, - 512, 1497, 1460, 512, 1522, 1463, 262, 1506, 262, 1488, 262, 1491, 262, - 1492, 262, 1499, 262, 1500, 262, 1501, 262, 1512, 262, 1514, 262, 43, - 512, 1513, 1473, 512, 1513, 1474, 512, 64329, 1473, 512, 64329, 1474, - 512, 1488, 1463, 512, 1488, 1464, 512, 1488, 1468, 512, 1489, 1468, 512, - 1490, 1468, 512, 1491, 1468, 512, 1492, 1468, 512, 1493, 1468, 512, 1494, - 1468, 512, 1496, 1468, 512, 1497, 1468, 512, 1498, 1468, 512, 1499, 1468, - 512, 1500, 1468, 512, 1502, 1468, 512, 1504, 1468, 512, 1505, 1468, 512, - 1507, 1468, 512, 1508, 1468, 512, 1510, 1468, 512, 1511, 1468, 512, 1512, - 1468, 512, 1513, 1468, 512, 1514, 1468, 512, 1493, 1465, 512, 1489, 1471, - 512, 1499, 1471, 512, 1508, 1471, 514, 1488, 1500, 267, 1649, 268, 1649, - 267, 1659, 268, 1659, 269, 1659, 270, 1659, 267, 1662, 268, 1662, 269, - 1662, 270, 1662, 267, 1664, 268, 1664, 269, 1664, 270, 1664, 267, 1658, - 268, 1658, 269, 1658, 270, 1658, 267, 1663, 268, 1663, 269, 1663, 270, - 1663, 267, 1657, 268, 1657, 269, 1657, 270, 1657, 267, 1700, 268, 1700, - 269, 1700, 270, 1700, 267, 1702, 268, 1702, 269, 1702, 270, 1702, 267, - 1668, 268, 1668, 269, 1668, 270, 1668, 267, 1667, 268, 1667, 269, 1667, - 270, 1667, 267, 1670, 268, 1670, 269, 1670, 270, 1670, 267, 1671, 268, - 1671, 269, 1671, 270, 1671, 267, 1677, 268, 1677, 267, 1676, 268, 1676, - 267, 1678, 268, 1678, 267, 1672, 268, 1672, 267, 1688, 268, 1688, 267, - 1681, 268, 1681, 267, 1705, 268, 1705, 269, 1705, 270, 1705, 267, 1711, - 268, 1711, 269, 1711, 270, 1711, 267, 1715, 268, 1715, 269, 1715, 270, - 1715, 267, 1713, 268, 1713, 269, 1713, 270, 1713, 267, 1722, 268, 1722, - 267, 1723, 268, 1723, 269, 1723, 270, 1723, 267, 1728, 268, 1728, 267, - 1729, 268, 1729, 269, 1729, 270, 1729, 267, 1726, 268, 1726, 269, 1726, - 270, 1726, 267, 1746, 268, 1746, 267, 1747, 268, 1747, 267, 1709, 268, - 1709, 269, 1709, 270, 1709, 267, 1735, 268, 1735, 267, 1734, 268, 1734, - 267, 1736, 268, 1736, 267, 1655, 267, 1739, 268, 1739, 267, 1733, 268, - 1733, 267, 1737, 268, 1737, 267, 1744, 268, 1744, 269, 1744, 270, 1744, - 269, 1609, 270, 1609, 523, 1574, 1575, 524, 1574, 1575, 523, 1574, 1749, - 524, 1574, 1749, 523, 1574, 1608, 524, 1574, 1608, 523, 1574, 1735, 524, - 1574, 1735, 523, 1574, 1734, 524, 1574, 1734, 523, 1574, 1736, 524, 1574, - 1736, 523, 1574, 1744, 524, 1574, 1744, 525, 1574, 1744, 523, 1574, 1609, - 524, 1574, 1609, 525, 1574, 1609, 267, 1740, 268, 1740, 269, 1740, 270, - 1740, 523, 1574, 1580, 523, 1574, 1581, 523, 1574, 1605, 523, 1574, 1609, + 31118, 256, 31296, 256, 31361, 256, 31680, 256, 32265, 256, 32321, 256, + 32626, 256, 32773, 256, 33261, 256, 33401, 256, 33879, 256, 35088, 256, + 35222, 256, 35585, 256, 35641, 256, 36051, 256, 36104, 256, 36790, 256, + 38627, 256, 38911, 256, 38971, 256, 24693, 256, 148206, 256, 33304, 256, + 20006, 256, 20917, 256, 20840, 256, 20352, 256, 20805, 256, 20864, 256, + 21191, 256, 21242, 256, 21845, 256, 21913, 256, 21986, 256, 22707, 256, + 22852, 256, 22868, 256, 23138, 256, 23336, 256, 24274, 256, 24281, 256, + 24425, 256, 24493, 256, 24792, 256, 24910, 256, 24840, 256, 24928, 256, + 25140, 256, 25540, 256, 25628, 256, 25682, 256, 25942, 256, 26395, 256, + 26454, 256, 27513, 256, 28379, 256, 28363, 256, 28702, 256, 30631, 256, + 29237, 256, 29359, 256, 29809, 256, 29958, 256, 30011, 256, 30237, 256, + 30239, 256, 30427, 256, 30452, 256, 30538, 256, 30528, 256, 30924, 256, + 31409, 256, 31867, 256, 32091, 256, 32574, 256, 33618, 256, 33775, 256, + 34681, 256, 35137, 256, 35206, 256, 35519, 256, 35531, 256, 35565, 256, + 35722, 256, 36664, 256, 36978, 256, 37273, 256, 37494, 256, 38524, 256, + 38875, 256, 38923, 256, 39698, 256, 141386, 256, 141380, 256, 144341, + 256, 15261, 256, 16408, 256, 16441, 256, 152137, 256, 154832, 256, + 163539, 256, 40771, 256, 40846, 514, 102, 102, 514, 102, 105, 514, 102, + 108, 770, 102, 102, 105, 770, 102, 102, 108, 514, 383, 116, 514, 115, + 116, 514, 1396, 1398, 514, 1396, 1381, 514, 1396, 1387, 514, 1406, 1398, + 514, 1396, 1389, 512, 1497, 1460, 512, 1522, 1463, 262, 1506, 262, 1488, + 262, 1491, 262, 1492, 262, 1499, 262, 1500, 262, 1501, 262, 1512, 262, + 1514, 262, 43, 512, 1513, 1473, 512, 1513, 1474, 512, 64329, 1473, 512, + 64329, 1474, 512, 1488, 1463, 512, 1488, 1464, 512, 1488, 1468, 512, + 1489, 1468, 512, 1490, 1468, 512, 1491, 1468, 512, 1492, 1468, 512, 1493, + 1468, 512, 1494, 1468, 512, 1496, 1468, 512, 1497, 1468, 512, 1498, 1468, + 512, 1499, 1468, 512, 1500, 1468, 512, 1502, 1468, 512, 1504, 1468, 512, + 1505, 1468, 512, 1507, 1468, 512, 1508, 1468, 512, 1510, 1468, 512, 1511, + 1468, 512, 1512, 1468, 512, 1513, 1468, 512, 1514, 1468, 512, 1493, 1465, + 512, 1489, 1471, 512, 1499, 1471, 512, 1508, 1471, 514, 1488, 1500, 267, + 1649, 268, 1649, 267, 1659, 268, 1659, 269, 1659, 270, 1659, 267, 1662, + 268, 1662, 269, 1662, 270, 1662, 267, 1664, 268, 1664, 269, 1664, 270, + 1664, 267, 1658, 268, 1658, 269, 1658, 270, 1658, 267, 1663, 268, 1663, + 269, 1663, 270, 1663, 267, 1657, 268, 1657, 269, 1657, 270, 1657, 267, + 1700, 268, 1700, 269, 1700, 270, 1700, 267, 1702, 268, 1702, 269, 1702, + 270, 1702, 267, 1668, 268, 1668, 269, 1668, 270, 1668, 267, 1667, 268, + 1667, 269, 1667, 270, 1667, 267, 1670, 268, 1670, 269, 1670, 270, 1670, + 267, 1671, 268, 1671, 269, 1671, 270, 1671, 267, 1677, 268, 1677, 267, + 1676, 268, 1676, 267, 1678, 268, 1678, 267, 1672, 268, 1672, 267, 1688, + 268, 1688, 267, 1681, 268, 1681, 267, 1705, 268, 1705, 269, 1705, 270, + 1705, 267, 1711, 268, 1711, 269, 1711, 270, 1711, 267, 1715, 268, 1715, + 269, 1715, 270, 1715, 267, 1713, 268, 1713, 269, 1713, 270, 1713, 267, + 1722, 268, 1722, 267, 1723, 268, 1723, 269, 1723, 270, 1723, 267, 1728, + 268, 1728, 267, 1729, 268, 1729, 269, 1729, 270, 1729, 267, 1726, 268, + 1726, 269, 1726, 270, 1726, 267, 1746, 268, 1746, 267, 1747, 268, 1747, + 267, 1709, 268, 1709, 269, 1709, 270, 1709, 267, 1735, 268, 1735, 267, + 1734, 268, 1734, 267, 1736, 268, 1736, 267, 1655, 267, 1739, 268, 1739, + 267, 1733, 268, 1733, 267, 1737, 268, 1737, 267, 1744, 268, 1744, 269, + 1744, 270, 1744, 269, 1609, 270, 1609, 523, 1574, 1575, 524, 1574, 1575, + 523, 1574, 1749, 524, 1574, 1749, 523, 1574, 1608, 524, 1574, 1608, 523, + 1574, 1735, 524, 1574, 1735, 523, 1574, 1734, 524, 1574, 1734, 523, 1574, + 1736, 524, 1574, 1736, 523, 1574, 1744, 524, 1574, 1744, 525, 1574, 1744, + 523, 1574, 1609, 524, 1574, 1609, 525, 1574, 1609, 267, 1740, 268, 1740, + 269, 1740, 270, 1740, 523, 1574, 1580, 523, 1574, 1581, 523, 1574, 1605, 523, 1574, 1610, 523, 1576, 1580, 523, 1576, 1581, 523, 1576, 1582, 523, 1576, 1605, 523, 1576, 1609, 523, 1576, 1610, 523, 1578, 1580, 523, 1578, 1581, 523, 1578, 1582, 523, 1578, 1605, 523, 1578, 1609, 523, 1578, 1610, @@ -3980,172 +3997,171 @@ static const unsigned int decomp_data[] = { 1610, 523, 1584, 1648, 523, 1585, 1648, 523, 1609, 1648, 779, 32, 1612, 1617, 779, 32, 1613, 1617, 779, 32, 1614, 1617, 779, 32, 1615, 1617, 779, 32, 1616, 1617, 779, 32, 1617, 1648, 524, 1574, 1585, 524, 1574, 1586, - 524, 1574, 1605, 524, 1574, 1606, 524, 1574, 1609, 524, 1574, 1610, 524, - 1576, 1585, 524, 1576, 1586, 524, 1576, 1605, 524, 1576, 1606, 524, 1576, - 1609, 524, 1576, 1610, 524, 1578, 1585, 524, 1578, 1586, 524, 1578, 1605, - 524, 1578, 1606, 524, 1578, 1609, 524, 1578, 1610, 524, 1579, 1585, 524, - 1579, 1586, 524, 1579, 1605, 524, 1579, 1606, 524, 1579, 1609, 524, 1579, - 1610, 524, 1601, 1609, 524, 1601, 1610, 524, 1602, 1609, 524, 1602, 1610, - 524, 1603, 1575, 524, 1603, 1604, 524, 1603, 1605, 524, 1603, 1609, 524, - 1603, 1610, 524, 1604, 1605, 524, 1604, 1609, 524, 1604, 1610, 524, 1605, - 1575, 524, 1605, 1605, 524, 1606, 1585, 524, 1606, 1586, 524, 1606, 1605, - 524, 1606, 1606, 524, 1606, 1609, 524, 1606, 1610, 524, 1609, 1648, 524, - 1610, 1585, 524, 1610, 1586, 524, 1610, 1605, 524, 1610, 1606, 524, 1610, - 1609, 524, 1610, 1610, 525, 1574, 1580, 525, 1574, 1581, 525, 1574, 1582, - 525, 1574, 1605, 525, 1574, 1607, 525, 1576, 1580, 525, 1576, 1581, 525, - 1576, 1582, 525, 1576, 1605, 525, 1576, 1607, 525, 1578, 1580, 525, 1578, - 1581, 525, 1578, 1582, 525, 1578, 1605, 525, 1578, 1607, 525, 1579, 1605, - 525, 1580, 1581, 525, 1580, 1605, 525, 1581, 1580, 525, 1581, 1605, 525, - 1582, 1580, 525, 1582, 1605, 525, 1587, 1580, 525, 1587, 1581, 525, 1587, - 1582, 525, 1587, 1605, 525, 1589, 1581, 525, 1589, 1582, 525, 1589, 1605, - 525, 1590, 1580, 525, 1590, 1581, 525, 1590, 1582, 525, 1590, 1605, 525, - 1591, 1581, 525, 1592, 1605, 525, 1593, 1580, 525, 1593, 1605, 525, 1594, - 1580, 525, 1594, 1605, 525, 1601, 1580, 525, 1601, 1581, 525, 1601, 1582, - 525, 1601, 1605, 525, 1602, 1581, 525, 1602, 1605, 525, 1603, 1580, 525, - 1603, 1581, 525, 1603, 1582, 525, 1603, 1604, 525, 1603, 1605, 525, 1604, - 1580, 525, 1604, 1581, 525, 1604, 1582, 525, 1604, 1605, 525, 1604, 1607, - 525, 1605, 1580, 525, 1605, 1581, 525, 1605, 1582, 525, 1605, 1605, 525, - 1606, 1580, 525, 1606, 1581, 525, 1606, 1582, 525, 1606, 1605, 525, 1606, - 1607, 525, 1607, 1580, 525, 1607, 1605, 525, 1607, 1648, 525, 1610, 1580, - 525, 1610, 1581, 525, 1610, 1582, 525, 1610, 1605, 525, 1610, 1607, 526, - 1574, 1605, 526, 1574, 1607, 526, 1576, 1605, 526, 1576, 1607, 526, 1578, - 1605, 526, 1578, 1607, 526, 1579, 1605, 526, 1579, 1607, 526, 1587, 1605, - 526, 1587, 1607, 526, 1588, 1605, 526, 1588, 1607, 526, 1603, 1604, 526, - 1603, 1605, 526, 1604, 1605, 526, 1606, 1605, 526, 1606, 1607, 526, 1610, - 1605, 526, 1610, 1607, 782, 1600, 1614, 1617, 782, 1600, 1615, 1617, 782, - 1600, 1616, 1617, 523, 1591, 1609, 523, 1591, 1610, 523, 1593, 1609, 523, - 1593, 1610, 523, 1594, 1609, 523, 1594, 1610, 523, 1587, 1609, 523, 1587, - 1610, 523, 1588, 1609, 523, 1588, 1610, 523, 1581, 1609, 523, 1581, 1610, - 523, 1580, 1609, 523, 1580, 1610, 523, 1582, 1609, 523, 1582, 1610, 523, - 1589, 1609, 523, 1589, 1610, 523, 1590, 1609, 523, 1590, 1610, 523, 1588, - 1580, 523, 1588, 1581, 523, 1588, 1582, 523, 1588, 1605, 523, 1588, 1585, - 523, 1587, 1585, 523, 1589, 1585, 523, 1590, 1585, 524, 1591, 1609, 524, - 1591, 1610, 524, 1593, 1609, 524, 1593, 1610, 524, 1594, 1609, 524, 1594, - 1610, 524, 1587, 1609, 524, 1587, 1610, 524, 1588, 1609, 524, 1588, 1610, - 524, 1581, 1609, 524, 1581, 1610, 524, 1580, 1609, 524, 1580, 1610, 524, - 1582, 1609, 524, 1582, 1610, 524, 1589, 1609, 524, 1589, 1610, 524, 1590, - 1609, 524, 1590, 1610, 524, 1588, 1580, 524, 1588, 1581, 524, 1588, 1582, - 524, 1588, 1605, 524, 1588, 1585, 524, 1587, 1585, 524, 1589, 1585, 524, - 1590, 1585, 525, 1588, 1580, 525, 1588, 1581, 525, 1588, 1582, 525, 1588, - 1605, 525, 1587, 1607, 525, 1588, 1607, 525, 1591, 1605, 526, 1587, 1580, - 526, 1587, 1581, 526, 1587, 1582, 526, 1588, 1580, 526, 1588, 1581, 526, - 1588, 1582, 526, 1591, 1605, 526, 1592, 1605, 524, 1575, 1611, 523, 1575, - 1611, 781, 1578, 1580, 1605, 780, 1578, 1581, 1580, 781, 1578, 1581, - 1580, 781, 1578, 1581, 1605, 781, 1578, 1582, 1605, 781, 1578, 1605, - 1580, 781, 1578, 1605, 1581, 781, 1578, 1605, 1582, 780, 1580, 1605, - 1581, 781, 1580, 1605, 1581, 780, 1581, 1605, 1610, 780, 1581, 1605, - 1609, 781, 1587, 1581, 1580, 781, 1587, 1580, 1581, 780, 1587, 1580, - 1609, 780, 1587, 1605, 1581, 781, 1587, 1605, 1581, 781, 1587, 1605, - 1580, 780, 1587, 1605, 1605, 781, 1587, 1605, 1605, 780, 1589, 1581, - 1581, 781, 1589, 1581, 1581, 780, 1589, 1605, 1605, 780, 1588, 1581, - 1605, 781, 1588, 1581, 1605, 780, 1588, 1580, 1610, 780, 1588, 1605, - 1582, 781, 1588, 1605, 1582, 780, 1588, 1605, 1605, 781, 1588, 1605, - 1605, 780, 1590, 1581, 1609, 780, 1590, 1582, 1605, 781, 1590, 1582, - 1605, 780, 1591, 1605, 1581, 781, 1591, 1605, 1581, 781, 1591, 1605, - 1605, 780, 1591, 1605, 1610, 780, 1593, 1580, 1605, 780, 1593, 1605, - 1605, 781, 1593, 1605, 1605, 780, 1593, 1605, 1609, 780, 1594, 1605, - 1605, 780, 1594, 1605, 1610, 780, 1594, 1605, 1609, 780, 1601, 1582, - 1605, 781, 1601, 1582, 1605, 780, 1602, 1605, 1581, 780, 1602, 1605, - 1605, 780, 1604, 1581, 1605, 780, 1604, 1581, 1610, 780, 1604, 1581, - 1609, 781, 1604, 1580, 1580, 780, 1604, 1580, 1580, 780, 1604, 1582, - 1605, 781, 1604, 1582, 1605, 780, 1604, 1605, 1581, 781, 1604, 1605, - 1581, 781, 1605, 1581, 1580, 781, 1605, 1581, 1605, 780, 1605, 1581, - 1610, 781, 1605, 1580, 1581, 781, 1605, 1580, 1605, 781, 1605, 1582, - 1580, 781, 1605, 1582, 1605, 781, 1605, 1580, 1582, 781, 1607, 1605, - 1580, 781, 1607, 1605, 1605, 781, 1606, 1581, 1605, 780, 1606, 1581, - 1609, 780, 1606, 1580, 1605, 781, 1606, 1580, 1605, 780, 1606, 1580, - 1609, 780, 1606, 1605, 1610, 780, 1606, 1605, 1609, 780, 1610, 1605, - 1605, 781, 1610, 1605, 1605, 780, 1576, 1582, 1610, 780, 1578, 1580, - 1610, 780, 1578, 1580, 1609, 780, 1578, 1582, 1610, 780, 1578, 1582, - 1609, 780, 1578, 1605, 1610, 780, 1578, 1605, 1609, 780, 1580, 1605, - 1610, 780, 1580, 1581, 1609, 780, 1580, 1605, 1609, 780, 1587, 1582, - 1609, 780, 1589, 1581, 1610, 780, 1588, 1581, 1610, 780, 1590, 1581, - 1610, 780, 1604, 1580, 1610, 780, 1604, 1605, 1610, 780, 1610, 1581, - 1610, 780, 1610, 1580, 1610, 780, 1610, 1605, 1610, 780, 1605, 1605, - 1610, 780, 1602, 1605, 1610, 780, 1606, 1581, 1610, 781, 1602, 1605, - 1581, 781, 1604, 1581, 1605, 780, 1593, 1605, 1610, 780, 1603, 1605, - 1610, 781, 1606, 1580, 1581, 780, 1605, 1582, 1610, 781, 1604, 1580, - 1605, 780, 1603, 1605, 1605, 780, 1604, 1580, 1605, 780, 1606, 1580, - 1581, 780, 1580, 1581, 1610, 780, 1581, 1580, 1610, 780, 1605, 1580, - 1610, 780, 1601, 1605, 1610, 780, 1576, 1581, 1610, 781, 1603, 1605, - 1605, 781, 1593, 1580, 1605, 781, 1589, 1605, 1605, 780, 1587, 1582, - 1610, 780, 1606, 1580, 1610, 779, 1589, 1604, 1746, 779, 1602, 1604, - 1746, 1035, 1575, 1604, 1604, 1607, 1035, 1575, 1603, 1576, 1585, 1035, - 1605, 1581, 1605, 1583, 1035, 1589, 1604, 1593, 1605, 1035, 1585, 1587, - 1608, 1604, 1035, 1593, 1604, 1610, 1607, 1035, 1608, 1587, 1604, 1605, - 779, 1589, 1604, 1609, 4619, 1589, 1604, 1609, 32, 1575, 1604, 1604, - 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 2059, 1580, - 1604, 32, 1580, 1604, 1575, 1604, 1607, 1035, 1585, 1740, 1575, 1604, - 265, 44, 265, 12289, 265, 12290, 265, 58, 265, 59, 265, 33, 265, 63, 265, - 12310, 265, 12311, 265, 8230, 265, 8229, 265, 8212, 265, 8211, 265, 95, - 265, 95, 265, 40, 265, 41, 265, 123, 265, 125, 265, 12308, 265, 12309, - 265, 12304, 265, 12305, 265, 12298, 265, 12299, 265, 12296, 265, 12297, - 265, 12300, 265, 12301, 265, 12302, 265, 12303, 265, 91, 265, 93, 258, - 8254, 258, 8254, 258, 8254, 258, 8254, 258, 95, 258, 95, 258, 95, 271, - 44, 271, 12289, 271, 46, 271, 59, 271, 58, 271, 63, 271, 33, 271, 8212, - 271, 40, 271, 41, 271, 123, 271, 125, 271, 12308, 271, 12309, 271, 35, - 271, 38, 271, 42, 271, 43, 271, 45, 271, 60, 271, 62, 271, 61, 271, 92, - 271, 36, 271, 37, 271, 64, 523, 32, 1611, 526, 1600, 1611, 523, 32, 1612, - 523, 32, 1613, 523, 32, 1614, 526, 1600, 1614, 523, 32, 1615, 526, 1600, - 1615, 523, 32, 1616, 526, 1600, 1616, 523, 32, 1617, 526, 1600, 1617, - 523, 32, 1618, 526, 1600, 1618, 267, 1569, 267, 1570, 268, 1570, 267, - 1571, 268, 1571, 267, 1572, 268, 1572, 267, 1573, 268, 1573, 267, 1574, - 268, 1574, 269, 1574, 270, 1574, 267, 1575, 268, 1575, 267, 1576, 268, - 1576, 269, 1576, 270, 1576, 267, 1577, 268, 1577, 267, 1578, 268, 1578, - 269, 1578, 270, 1578, 267, 1579, 268, 1579, 269, 1579, 270, 1579, 267, - 1580, 268, 1580, 269, 1580, 270, 1580, 267, 1581, 268, 1581, 269, 1581, - 270, 1581, 267, 1582, 268, 1582, 269, 1582, 270, 1582, 267, 1583, 268, - 1583, 267, 1584, 268, 1584, 267, 1585, 268, 1585, 267, 1586, 268, 1586, - 267, 1587, 268, 1587, 269, 1587, 270, 1587, 267, 1588, 268, 1588, 269, - 1588, 270, 1588, 267, 1589, 268, 1589, 269, 1589, 270, 1589, 267, 1590, - 268, 1590, 269, 1590, 270, 1590, 267, 1591, 268, 1591, 269, 1591, 270, - 1591, 267, 1592, 268, 1592, 269, 1592, 270, 1592, 267, 1593, 268, 1593, - 269, 1593, 270, 1593, 267, 1594, 268, 1594, 269, 1594, 270, 1594, 267, - 1601, 268, 1601, 269, 1601, 270, 1601, 267, 1602, 268, 1602, 269, 1602, - 270, 1602, 267, 1603, 268, 1603, 269, 1603, 270, 1603, 267, 1604, 268, - 1604, 269, 1604, 270, 1604, 267, 1605, 268, 1605, 269, 1605, 270, 1605, - 267, 1606, 268, 1606, 269, 1606, 270, 1606, 267, 1607, 268, 1607, 269, - 1607, 270, 1607, 267, 1608, 268, 1608, 267, 1609, 268, 1609, 267, 1610, - 268, 1610, 269, 1610, 270, 1610, 523, 1604, 1570, 524, 1604, 1570, 523, - 1604, 1571, 524, 1604, 1571, 523, 1604, 1573, 524, 1604, 1573, 523, 1604, - 1575, 524, 1604, 1575, 264, 33, 264, 34, 264, 35, 264, 36, 264, 37, 264, - 38, 264, 39, 264, 40, 264, 41, 264, 42, 264, 43, 264, 44, 264, 45, 264, - 46, 264, 47, 264, 48, 264, 49, 264, 50, 264, 51, 264, 52, 264, 53, 264, - 54, 264, 55, 264, 56, 264, 57, 264, 58, 264, 59, 264, 60, 264, 61, 264, - 62, 264, 63, 264, 64, 264, 65, 264, 66, 264, 67, 264, 68, 264, 69, 264, - 70, 264, 71, 264, 72, 264, 73, 264, 74, 264, 75, 264, 76, 264, 77, 264, - 78, 264, 79, 264, 80, 264, 81, 264, 82, 264, 83, 264, 84, 264, 85, 264, - 86, 264, 87, 264, 88, 264, 89, 264, 90, 264, 91, 264, 92, 264, 93, 264, - 94, 264, 95, 264, 96, 264, 97, 264, 98, 264, 99, 264, 100, 264, 101, 264, - 102, 264, 103, 264, 104, 264, 105, 264, 106, 264, 107, 264, 108, 264, - 109, 264, 110, 264, 111, 264, 112, 264, 113, 264, 114, 264, 115, 264, - 116, 264, 117, 264, 118, 264, 119, 264, 120, 264, 121, 264, 122, 264, - 123, 264, 124, 264, 125, 264, 126, 264, 10629, 264, 10630, 272, 12290, - 272, 12300, 272, 12301, 272, 12289, 272, 12539, 272, 12530, 272, 12449, - 272, 12451, 272, 12453, 272, 12455, 272, 12457, 272, 12515, 272, 12517, - 272, 12519, 272, 12483, 272, 12540, 272, 12450, 272, 12452, 272, 12454, - 272, 12456, 272, 12458, 272, 12459, 272, 12461, 272, 12463, 272, 12465, - 272, 12467, 272, 12469, 272, 12471, 272, 12473, 272, 12475, 272, 12477, - 272, 12479, 272, 12481, 272, 12484, 272, 12486, 272, 12488, 272, 12490, - 272, 12491, 272, 12492, 272, 12493, 272, 12494, 272, 12495, 272, 12498, - 272, 12501, 272, 12504, 272, 12507, 272, 12510, 272, 12511, 272, 12512, - 272, 12513, 272, 12514, 272, 12516, 272, 12518, 272, 12520, 272, 12521, - 272, 12522, 272, 12523, 272, 12524, 272, 12525, 272, 12527, 272, 12531, - 272, 12441, 272, 12442, 272, 12644, 272, 12593, 272, 12594, 272, 12595, - 272, 12596, 272, 12597, 272, 12598, 272, 12599, 272, 12600, 272, 12601, - 272, 12602, 272, 12603, 272, 12604, 272, 12605, 272, 12606, 272, 12607, - 272, 12608, 272, 12609, 272, 12610, 272, 12611, 272, 12612, 272, 12613, - 272, 12614, 272, 12615, 272, 12616, 272, 12617, 272, 12618, 272, 12619, - 272, 12620, 272, 12621, 272, 12622, 272, 12623, 272, 12624, 272, 12625, - 272, 12626, 272, 12627, 272, 12628, 272, 12629, 272, 12630, 272, 12631, - 272, 12632, 272, 12633, 272, 12634, 272, 12635, 272, 12636, 272, 12637, - 272, 12638, 272, 12639, 272, 12640, 272, 12641, 272, 12642, 272, 12643, - 264, 162, 264, 163, 264, 172, 264, 175, 264, 166, 264, 165, 264, 8361, - 272, 9474, 272, 8592, 272, 8593, 272, 8594, 272, 8595, 272, 9632, 272, - 9675, 259, 720, 259, 721, 259, 230, 259, 665, 259, 595, 259, 675, 259, - 43878, 259, 677, 259, 676, 259, 598, 259, 599, 259, 7569, 259, 600, 259, - 606, 259, 681, 259, 612, 259, 610, 259, 608, 259, 667, 259, 295, 259, - 668, 259, 615, 259, 644, 259, 682, 259, 683, 259, 620, 259, 122628, 259, + 524, 1574, 1605, 524, 1574, 1606, 524, 1574, 1610, 524, 1576, 1585, 524, + 1576, 1586, 524, 1576, 1605, 524, 1576, 1606, 524, 1576, 1609, 524, 1576, + 1610, 524, 1578, 1585, 524, 1578, 1586, 524, 1578, 1605, 524, 1578, 1606, + 524, 1578, 1609, 524, 1578, 1610, 524, 1579, 1585, 524, 1579, 1586, 524, + 1579, 1605, 524, 1579, 1606, 524, 1579, 1609, 524, 1579, 1610, 524, 1601, + 1609, 524, 1601, 1610, 524, 1602, 1609, 524, 1602, 1610, 524, 1603, 1575, + 524, 1603, 1604, 524, 1603, 1605, 524, 1603, 1609, 524, 1603, 1610, 524, + 1604, 1605, 524, 1604, 1609, 524, 1604, 1610, 524, 1605, 1575, 524, 1605, + 1605, 524, 1606, 1585, 524, 1606, 1586, 524, 1606, 1605, 524, 1606, 1606, + 524, 1606, 1609, 524, 1606, 1610, 524, 1609, 1648, 524, 1610, 1585, 524, + 1610, 1586, 524, 1610, 1605, 524, 1610, 1606, 524, 1610, 1609, 524, 1610, + 1610, 525, 1574, 1580, 525, 1574, 1581, 525, 1574, 1582, 525, 1574, 1605, + 525, 1574, 1607, 525, 1576, 1580, 525, 1576, 1581, 525, 1576, 1582, 525, + 1576, 1605, 525, 1576, 1607, 525, 1578, 1580, 525, 1578, 1581, 525, 1578, + 1582, 525, 1578, 1605, 525, 1578, 1607, 525, 1579, 1605, 525, 1580, 1581, + 525, 1580, 1605, 525, 1581, 1580, 525, 1581, 1605, 525, 1582, 1580, 525, + 1582, 1605, 525, 1587, 1580, 525, 1587, 1581, 525, 1587, 1582, 525, 1587, + 1605, 525, 1589, 1581, 525, 1589, 1582, 525, 1589, 1605, 525, 1590, 1580, + 525, 1590, 1581, 525, 1590, 1582, 525, 1590, 1605, 525, 1591, 1581, 525, + 1592, 1605, 525, 1593, 1580, 525, 1593, 1605, 525, 1594, 1580, 525, 1594, + 1605, 525, 1601, 1580, 525, 1601, 1581, 525, 1601, 1582, 525, 1601, 1605, + 525, 1602, 1581, 525, 1602, 1605, 525, 1603, 1580, 525, 1603, 1581, 525, + 1603, 1582, 525, 1603, 1604, 525, 1603, 1605, 525, 1604, 1580, 525, 1604, + 1581, 525, 1604, 1582, 525, 1604, 1605, 525, 1604, 1607, 525, 1605, 1580, + 525, 1605, 1581, 525, 1605, 1582, 525, 1605, 1605, 525, 1606, 1580, 525, + 1606, 1581, 525, 1606, 1582, 525, 1606, 1605, 525, 1606, 1607, 525, 1607, + 1580, 525, 1607, 1605, 525, 1607, 1648, 525, 1610, 1580, 525, 1610, 1581, + 525, 1610, 1582, 525, 1610, 1605, 525, 1610, 1607, 526, 1574, 1605, 526, + 1574, 1607, 526, 1576, 1605, 526, 1576, 1607, 526, 1578, 1605, 526, 1578, + 1607, 526, 1579, 1605, 526, 1579, 1607, 526, 1587, 1605, 526, 1587, 1607, + 526, 1588, 1605, 526, 1588, 1607, 526, 1603, 1604, 526, 1603, 1605, 526, + 1604, 1605, 526, 1606, 1605, 526, 1606, 1607, 526, 1610, 1605, 526, 1610, + 1607, 782, 1600, 1614, 1617, 782, 1600, 1615, 1617, 782, 1600, 1616, + 1617, 523, 1591, 1609, 523, 1591, 1610, 523, 1593, 1609, 523, 1593, 1610, + 523, 1594, 1609, 523, 1594, 1610, 523, 1587, 1609, 523, 1587, 1610, 523, + 1588, 1609, 523, 1588, 1610, 523, 1581, 1609, 523, 1581, 1610, 523, 1580, + 1609, 523, 1580, 1610, 523, 1582, 1609, 523, 1582, 1610, 523, 1589, 1609, + 523, 1589, 1610, 523, 1590, 1609, 523, 1590, 1610, 523, 1588, 1580, 523, + 1588, 1581, 523, 1588, 1582, 523, 1588, 1605, 523, 1588, 1585, 523, 1587, + 1585, 523, 1589, 1585, 523, 1590, 1585, 524, 1591, 1609, 524, 1591, 1610, + 524, 1593, 1609, 524, 1593, 1610, 524, 1594, 1609, 524, 1594, 1610, 524, + 1587, 1609, 524, 1587, 1610, 524, 1588, 1609, 524, 1588, 1610, 524, 1581, + 1609, 524, 1581, 1610, 524, 1580, 1609, 524, 1580, 1610, 524, 1582, 1609, + 524, 1582, 1610, 524, 1589, 1609, 524, 1589, 1610, 524, 1590, 1609, 524, + 1590, 1610, 524, 1588, 1580, 524, 1588, 1581, 524, 1588, 1582, 524, 1588, + 1605, 524, 1588, 1585, 524, 1587, 1585, 524, 1589, 1585, 524, 1590, 1585, + 525, 1588, 1580, 525, 1588, 1581, 525, 1588, 1582, 525, 1588, 1605, 525, + 1587, 1607, 525, 1588, 1607, 525, 1591, 1605, 526, 1587, 1580, 526, 1587, + 1581, 526, 1587, 1582, 526, 1588, 1580, 526, 1588, 1581, 526, 1588, 1582, + 526, 1591, 1605, 526, 1592, 1605, 524, 1575, 1611, 523, 1575, 1611, 781, + 1578, 1580, 1605, 780, 1578, 1581, 1580, 781, 1578, 1581, 1580, 781, + 1578, 1581, 1605, 781, 1578, 1582, 1605, 781, 1578, 1605, 1580, 781, + 1578, 1605, 1581, 781, 1578, 1605, 1582, 780, 1580, 1605, 1581, 781, + 1580, 1605, 1581, 780, 1581, 1605, 1610, 780, 1581, 1605, 1609, 781, + 1587, 1581, 1580, 781, 1587, 1580, 1581, 780, 1587, 1580, 1609, 780, + 1587, 1605, 1581, 781, 1587, 1605, 1581, 781, 1587, 1605, 1580, 780, + 1587, 1605, 1605, 781, 1587, 1605, 1605, 780, 1589, 1581, 1581, 781, + 1589, 1581, 1581, 780, 1589, 1605, 1605, 780, 1588, 1581, 1605, 781, + 1588, 1581, 1605, 780, 1588, 1580, 1610, 780, 1588, 1605, 1582, 781, + 1588, 1605, 1582, 780, 1588, 1605, 1605, 781, 1588, 1605, 1605, 780, + 1590, 1581, 1609, 780, 1590, 1582, 1605, 781, 1590, 1582, 1605, 780, + 1591, 1605, 1581, 781, 1591, 1605, 1581, 781, 1591, 1605, 1605, 780, + 1591, 1605, 1610, 780, 1593, 1580, 1605, 780, 1593, 1605, 1605, 781, + 1593, 1605, 1605, 780, 1593, 1605, 1609, 780, 1594, 1605, 1605, 780, + 1594, 1605, 1610, 780, 1594, 1605, 1609, 780, 1601, 1582, 1605, 781, + 1601, 1582, 1605, 780, 1602, 1605, 1581, 780, 1602, 1605, 1605, 780, + 1604, 1581, 1605, 780, 1604, 1581, 1610, 780, 1604, 1581, 1609, 781, + 1604, 1580, 1580, 780, 1604, 1580, 1580, 780, 1604, 1582, 1605, 781, + 1604, 1582, 1605, 780, 1604, 1605, 1581, 781, 1604, 1605, 1581, 781, + 1605, 1581, 1580, 781, 1605, 1581, 1605, 780, 1605, 1581, 1610, 781, + 1605, 1580, 1581, 781, 1605, 1580, 1605, 781, 1605, 1582, 1580, 781, + 1605, 1582, 1605, 781, 1605, 1580, 1582, 781, 1607, 1605, 1580, 781, + 1607, 1605, 1605, 781, 1606, 1581, 1605, 780, 1606, 1581, 1609, 780, + 1606, 1580, 1605, 781, 1606, 1580, 1605, 780, 1606, 1580, 1609, 780, + 1606, 1605, 1610, 780, 1606, 1605, 1609, 780, 1610, 1605, 1605, 781, + 1610, 1605, 1605, 780, 1576, 1582, 1610, 780, 1578, 1580, 1610, 780, + 1578, 1580, 1609, 780, 1578, 1582, 1610, 780, 1578, 1582, 1609, 780, + 1578, 1605, 1610, 780, 1578, 1605, 1609, 780, 1580, 1605, 1610, 780, + 1580, 1581, 1609, 780, 1580, 1605, 1609, 780, 1587, 1582, 1609, 780, + 1589, 1581, 1610, 780, 1588, 1581, 1610, 780, 1590, 1581, 1610, 780, + 1604, 1580, 1610, 780, 1604, 1605, 1610, 780, 1610, 1581, 1610, 780, + 1610, 1580, 1610, 780, 1610, 1605, 1610, 780, 1605, 1605, 1610, 780, + 1602, 1605, 1610, 780, 1606, 1581, 1610, 781, 1602, 1605, 1581, 781, + 1604, 1581, 1605, 780, 1593, 1605, 1610, 780, 1603, 1605, 1610, 781, + 1606, 1580, 1581, 780, 1605, 1582, 1610, 781, 1604, 1580, 1605, 780, + 1603, 1605, 1605, 780, 1604, 1580, 1605, 780, 1606, 1580, 1581, 780, + 1580, 1581, 1610, 780, 1581, 1580, 1610, 780, 1605, 1580, 1610, 780, + 1601, 1605, 1610, 780, 1576, 1581, 1610, 781, 1603, 1605, 1605, 781, + 1593, 1580, 1605, 781, 1589, 1605, 1605, 780, 1587, 1582, 1610, 780, + 1606, 1580, 1610, 779, 1589, 1604, 1746, 779, 1602, 1604, 1746, 1035, + 1575, 1604, 1604, 1607, 1035, 1575, 1603, 1576, 1585, 1035, 1605, 1581, + 1605, 1583, 1035, 1589, 1604, 1593, 1605, 1035, 1585, 1587, 1608, 1604, + 1035, 1593, 1604, 1610, 1607, 1035, 1608, 1587, 1604, 1605, 779, 1589, + 1604, 1609, 4619, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, + 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 2059, 1580, 1604, 32, 1580, + 1604, 1575, 1604, 1607, 1035, 1585, 1740, 1575, 1604, 265, 44, 265, + 12289, 265, 12290, 265, 58, 265, 59, 265, 33, 265, 63, 265, 12310, 265, + 12311, 265, 8230, 265, 8229, 265, 8212, 265, 8211, 265, 95, 265, 40, 265, + 41, 265, 123, 265, 125, 265, 12308, 265, 12309, 265, 12304, 265, 12305, + 265, 12298, 265, 12299, 265, 12296, 265, 12297, 265, 12300, 265, 12301, + 265, 12302, 265, 12303, 265, 91, 265, 93, 258, 8254, 258, 95, 271, 44, + 271, 12289, 271, 46, 271, 59, 271, 58, 271, 63, 271, 33, 271, 8212, 271, + 40, 271, 41, 271, 123, 271, 125, 271, 12308, 271, 12309, 271, 35, 271, + 38, 271, 42, 271, 43, 271, 45, 271, 60, 271, 62, 271, 61, 271, 92, 271, + 36, 271, 37, 271, 64, 523, 32, 1611, 526, 1600, 1611, 523, 32, 1612, 523, + 32, 1613, 523, 32, 1614, 526, 1600, 1614, 523, 32, 1615, 526, 1600, 1615, + 523, 32, 1616, 526, 1600, 1616, 523, 32, 1617, 526, 1600, 1617, 523, 32, + 1618, 526, 1600, 1618, 267, 1569, 267, 1570, 268, 1570, 267, 1571, 268, + 1571, 267, 1572, 268, 1572, 267, 1573, 268, 1573, 267, 1574, 268, 1574, + 269, 1574, 270, 1574, 267, 1575, 268, 1575, 267, 1576, 268, 1576, 269, + 1576, 270, 1576, 267, 1577, 268, 1577, 267, 1578, 268, 1578, 269, 1578, + 270, 1578, 267, 1579, 268, 1579, 269, 1579, 270, 1579, 267, 1580, 268, + 1580, 269, 1580, 270, 1580, 267, 1581, 268, 1581, 269, 1581, 270, 1581, + 267, 1582, 268, 1582, 269, 1582, 270, 1582, 267, 1583, 268, 1583, 267, + 1584, 268, 1584, 267, 1585, 268, 1585, 267, 1586, 268, 1586, 267, 1587, + 268, 1587, 269, 1587, 270, 1587, 267, 1588, 268, 1588, 269, 1588, 270, + 1588, 267, 1589, 268, 1589, 269, 1589, 270, 1589, 267, 1590, 268, 1590, + 269, 1590, 270, 1590, 267, 1591, 268, 1591, 269, 1591, 270, 1591, 267, + 1592, 268, 1592, 269, 1592, 270, 1592, 267, 1593, 268, 1593, 269, 1593, + 270, 1593, 267, 1594, 268, 1594, 269, 1594, 270, 1594, 267, 1601, 268, + 1601, 269, 1601, 270, 1601, 267, 1602, 268, 1602, 269, 1602, 270, 1602, + 267, 1603, 268, 1603, 269, 1603, 270, 1603, 267, 1604, 268, 1604, 269, + 1604, 270, 1604, 267, 1605, 268, 1605, 269, 1605, 270, 1605, 267, 1606, + 268, 1606, 269, 1606, 270, 1606, 267, 1607, 268, 1607, 269, 1607, 270, + 1607, 267, 1608, 268, 1608, 267, 1609, 268, 1609, 267, 1610, 268, 1610, + 269, 1610, 270, 1610, 523, 1604, 1570, 524, 1604, 1570, 523, 1604, 1571, + 524, 1604, 1571, 523, 1604, 1573, 524, 1604, 1573, 523, 1604, 1575, 524, + 1604, 1575, 264, 33, 264, 34, 264, 35, 264, 36, 264, 37, 264, 38, 264, + 39, 264, 40, 264, 41, 264, 42, 264, 43, 264, 44, 264, 45, 264, 46, 264, + 47, 264, 48, 264, 49, 264, 50, 264, 51, 264, 52, 264, 53, 264, 54, 264, + 55, 264, 56, 264, 57, 264, 58, 264, 59, 264, 60, 264, 61, 264, 62, 264, + 63, 264, 64, 264, 65, 264, 66, 264, 67, 264, 68, 264, 69, 264, 70, 264, + 71, 264, 72, 264, 73, 264, 74, 264, 75, 264, 76, 264, 77, 264, 78, 264, + 79, 264, 80, 264, 81, 264, 82, 264, 83, 264, 84, 264, 85, 264, 86, 264, + 87, 264, 88, 264, 89, 264, 90, 264, 91, 264, 92, 264, 93, 264, 94, 264, + 95, 264, 96, 264, 97, 264, 98, 264, 99, 264, 100, 264, 101, 264, 102, + 264, 103, 264, 104, 264, 105, 264, 106, 264, 107, 264, 108, 264, 109, + 264, 110, 264, 111, 264, 112, 264, 113, 264, 114, 264, 115, 264, 116, + 264, 117, 264, 118, 264, 119, 264, 120, 264, 121, 264, 122, 264, 123, + 264, 124, 264, 125, 264, 126, 264, 10629, 264, 10630, 272, 12290, 272, + 12300, 272, 12301, 272, 12289, 272, 12539, 272, 12530, 272, 12449, 272, + 12451, 272, 12453, 272, 12455, 272, 12457, 272, 12515, 272, 12517, 272, + 12519, 272, 12483, 272, 12540, 272, 12450, 272, 12452, 272, 12454, 272, + 12456, 272, 12458, 272, 12459, 272, 12461, 272, 12463, 272, 12465, 272, + 12467, 272, 12469, 272, 12471, 272, 12473, 272, 12475, 272, 12477, 272, + 12479, 272, 12481, 272, 12484, 272, 12486, 272, 12488, 272, 12490, 272, + 12491, 272, 12492, 272, 12493, 272, 12494, 272, 12495, 272, 12498, 272, + 12501, 272, 12504, 272, 12507, 272, 12510, 272, 12511, 272, 12512, 272, + 12513, 272, 12514, 272, 12516, 272, 12518, 272, 12520, 272, 12521, 272, + 12522, 272, 12523, 272, 12524, 272, 12525, 272, 12527, 272, 12531, 272, + 12441, 272, 12442, 272, 12644, 272, 12593, 272, 12594, 272, 12595, 272, + 12596, 272, 12597, 272, 12598, 272, 12599, 272, 12600, 272, 12601, 272, + 12602, 272, 12603, 272, 12604, 272, 12605, 272, 12606, 272, 12607, 272, + 12608, 272, 12609, 272, 12610, 272, 12611, 272, 12612, 272, 12613, 272, + 12614, 272, 12615, 272, 12616, 272, 12617, 272, 12618, 272, 12619, 272, + 12620, 272, 12621, 272, 12622, 272, 12623, 272, 12624, 272, 12625, 272, + 12626, 272, 12627, 272, 12628, 272, 12629, 272, 12630, 272, 12631, 272, + 12632, 272, 12633, 272, 12634, 272, 12635, 272, 12636, 272, 12637, 272, + 12638, 272, 12639, 272, 12640, 272, 12641, 272, 12642, 272, 12643, 264, + 162, 264, 163, 264, 172, 264, 175, 264, 166, 264, 165, 264, 8361, 272, + 9474, 272, 8592, 272, 8593, 272, 8594, 272, 8595, 272, 9632, 272, 9675, + 259, 720, 259, 721, 259, 230, 259, 665, 259, 595, 259, 675, 259, 43878, + 259, 677, 259, 676, 259, 598, 259, 599, 259, 7569, 259, 600, 259, 606, + 259, 681, 259, 612, 259, 610, 259, 608, 259, 667, 259, 295, 259, 668, + 259, 615, 259, 644, 259, 682, 259, 683, 259, 620, 259, 122628, 259, 42894, 259, 622, 259, 122629, 259, 654, 259, 122630, 259, 248, 259, 630, 259, 631, 259, 113, 259, 634, 259, 122632, 259, 637, 259, 638, 259, 640, 259, 680, 259, 678, 259, 43879, 259, 679, 259, 648, 259, 11377, 259, 655, @@ -4157,281 +4173,131 @@ static const unsigned int decomp_data[] = { 512, 119128, 119141, 512, 119135, 119150, 512, 119135, 119151, 512, 119135, 119152, 512, 119135, 119153, 512, 119135, 119154, 512, 119225, 119141, 512, 119226, 119141, 512, 119227, 119150, 512, 119228, 119150, - 512, 119227, 119151, 512, 119228, 119151, 262, 65, 262, 66, 262, 67, 262, - 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, - 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, - 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, - 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, - 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, - 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, - 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, - 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, - 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, - 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, - 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 105, 262, 106, 262, 107, - 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, - 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, - 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, - 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, - 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, - 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, - 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, - 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, - 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, - 262, 65, 262, 67, 262, 68, 262, 71, 262, 74, 262, 75, 262, 78, 262, 79, - 262, 80, 262, 81, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, - 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 102, 262, - 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, - 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, - 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, - 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, - 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, - 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, - 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, - 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, - 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, - 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 68, 262, 69, 262, 70, - 262, 71, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, - 262, 81, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, - 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, - 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, - 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, - 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 68, - 262, 69, 262, 70, 262, 71, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, - 262, 79, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, - 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, - 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, - 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, - 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, - 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, - 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, - 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, - 262, 98, 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, - 105, 262, 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, - 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, - 119, 262, 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, - 262, 69, 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, - 262, 77, 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, - 262, 85, 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, - 262, 99, 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, - 106, 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, - 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, - 120, 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, - 262, 70, 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, - 262, 78, 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, - 262, 86, 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, - 262, 100, 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, - 262, 107, 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, - 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, - 262, 121, 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, - 262, 71, 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, - 262, 79, 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, - 262, 87, 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, - 262, 101, 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, - 262, 108, 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, - 262, 115, 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, - 262, 122, 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, - 262, 72, 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, - 262, 80, 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, - 262, 88, 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, - 262, 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, - 262, 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, - 262, 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, - 262, 65, 262, 66, 262, 67, 262, 68, 262, 69, 262, 70, 262, 71, 262, 72, - 262, 73, 262, 74, 262, 75, 262, 76, 262, 77, 262, 78, 262, 79, 262, 80, - 262, 81, 262, 82, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, - 262, 89, 262, 90, 262, 97, 262, 98, 262, 99, 262, 100, 262, 101, 262, - 102, 262, 103, 262, 104, 262, 105, 262, 106, 262, 107, 262, 108, 262, - 109, 262, 110, 262, 111, 262, 112, 262, 113, 262, 114, 262, 115, 262, - 116, 262, 117, 262, 118, 262, 119, 262, 120, 262, 121, 262, 122, 262, - 305, 262, 567, 262, 913, 262, 914, 262, 915, 262, 916, 262, 917, 262, - 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, 923, 262, 924, 262, - 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, - 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, - 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, 950, 262, 951, 262, - 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 957, 262, 958, 262, - 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, 964, 262, 965, 262, - 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, - 1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, - 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, - 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, - 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, - 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, - 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, - 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, - 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, - 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 913, 262, - 914, 262, 915, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, - 921, 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, - 928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, - 935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, 946, 262, 947, 262, - 948, 262, 949, 262, 950, 262, 951, 262, 952, 262, 953, 262, 954, 262, - 955, 262, 956, 262, 957, 262, 958, 262, 959, 262, 960, 262, 961, 262, - 962, 262, 963, 262, 964, 262, 965, 262, 966, 262, 967, 262, 968, 262, - 969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, 981, 262, 1009, 262, - 982, 262, 913, 262, 914, 262, 915, 262, 916, 262, 917, 262, 918, 262, - 919, 262, 920, 262, 921, 262, 922, 262, 923, 262, 924, 262, 925, 262, - 926, 262, 927, 262, 928, 262, 929, 262, 1012, 262, 931, 262, 932, 262, - 933, 262, 934, 262, 935, 262, 936, 262, 937, 262, 8711, 262, 945, 262, - 946, 262, 947, 262, 948, 262, 949, 262, 950, 262, 951, 262, 952, 262, - 953, 262, 954, 262, 955, 262, 956, 262, 957, 262, 958, 262, 959, 262, - 960, 262, 961, 262, 962, 262, 963, 262, 964, 262, 965, 262, 966, 262, - 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, 977, 262, 1008, 262, - 981, 262, 1009, 262, 982, 262, 913, 262, 914, 262, 915, 262, 916, 262, - 917, 262, 918, 262, 919, 262, 920, 262, 921, 262, 922, 262, 923, 262, - 924, 262, 925, 262, 926, 262, 927, 262, 928, 262, 929, 262, 1012, 262, - 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 936, 262, 937, 262, - 8711, 262, 945, 262, 946, 262, 947, 262, 948, 262, 949, 262, 950, 262, - 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 957, 262, - 958, 262, 959, 262, 960, 262, 961, 262, 962, 262, 963, 262, 964, 262, - 965, 262, 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, - 977, 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 988, 262, 989, 262, - 48, 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, - 56, 262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, - 54, 262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, 50, 262, 51, 262, - 52, 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, 48, 262, 49, 262, - 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 262, - 48, 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, - 56, 262, 57, 262, 1575, 262, 1576, 262, 1580, 262, 1583, 262, 1608, 262, + 512, 119227, 119151, 512, 119228, 119151, 262, 65, 262, 71, 262, 74, 262, + 75, 262, 79, 262, 83, 262, 84, 262, 85, 262, 86, 262, 87, 262, 88, 262, + 89, 262, 97, 262, 98, 262, 99, 262, 102, 262, 107, 262, 109, 262, 110, + 262, 112, 262, 113, 262, 114, 262, 115, 262, 116, 262, 117, 262, 118, + 262, 119, 262, 120, 262, 121, 262, 122, 262, 305, 262, 567, 262, 913, + 262, 914, 262, 916, 262, 917, 262, 918, 262, 919, 262, 920, 262, 921, + 262, 922, 262, 923, 262, 924, 262, 925, 262, 926, 262, 927, 262, 929, + 262, 1012, 262, 931, 262, 932, 262, 933, 262, 934, 262, 935, 262, 936, + 262, 937, 262, 8711, 262, 945, 262, 946, 262, 948, 262, 949, 262, 950, + 262, 951, 262, 952, 262, 953, 262, 954, 262, 955, 262, 956, 262, 957, + 262, 958, 262, 959, 262, 961, 262, 962, 262, 963, 262, 964, 262, 965, + 262, 966, 262, 967, 262, 968, 262, 969, 262, 8706, 262, 1013, 262, 977, + 262, 1008, 262, 981, 262, 1009, 262, 982, 262, 988, 262, 989, 262, 48, + 262, 49, 262, 50, 262, 51, 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, + 262, 57, 262, 1575, 262, 1576, 262, 1580, 262, 1583, 262, 1608, 262, 1586, 262, 1581, 262, 1591, 262, 1610, 262, 1603, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, 1585, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1584, 262, 1590, 262, 1592, 262, 1594, 262, 1646, 262, 1722, 262, 1697, 262, 1647, 262, - 1576, 262, 1580, 262, 1607, 262, 1581, 262, 1610, 262, 1603, 262, 1604, - 262, 1605, 262, 1606, 262, 1587, 262, 1593, 262, 1601, 262, 1589, 262, - 1602, 262, 1588, 262, 1578, 262, 1579, 262, 1582, 262, 1590, 262, 1594, - 262, 1580, 262, 1581, 262, 1610, 262, 1604, 262, 1606, 262, 1587, 262, - 1593, 262, 1589, 262, 1602, 262, 1588, 262, 1582, 262, 1590, 262, 1594, - 262, 1722, 262, 1647, 262, 1576, 262, 1580, 262, 1607, 262, 1581, 262, - 1591, 262, 1610, 262, 1603, 262, 1605, 262, 1606, 262, 1587, 262, 1593, - 262, 1601, 262, 1589, 262, 1602, 262, 1588, 262, 1578, 262, 1579, 262, - 1582, 262, 1590, 262, 1592, 262, 1594, 262, 1646, 262, 1697, 262, 1575, - 262, 1576, 262, 1580, 262, 1583, 262, 1607, 262, 1608, 262, 1586, 262, - 1581, 262, 1591, 262, 1610, 262, 1604, 262, 1605, 262, 1606, 262, 1587, - 262, 1593, 262, 1601, 262, 1589, 262, 1602, 262, 1585, 262, 1588, 262, - 1578, 262, 1579, 262, 1582, 262, 1584, 262, 1590, 262, 1592, 262, 1594, - 262, 1576, 262, 1580, 262, 1583, 262, 1608, 262, 1586, 262, 1581, 262, - 1591, 262, 1610, 262, 1604, 262, 1605, 262, 1606, 262, 1587, 262, 1593, - 262, 1601, 262, 1589, 262, 1602, 262, 1585, 262, 1588, 262, 1578, 262, - 1579, 262, 1582, 262, 1584, 262, 1590, 262, 1592, 262, 1594, 514, 48, 46, - 514, 48, 44, 514, 49, 44, 514, 50, 44, 514, 51, 44, 514, 52, 44, 514, 53, - 44, 514, 54, 44, 514, 55, 44, 514, 56, 44, 514, 57, 44, 770, 40, 65, 41, - 770, 40, 66, 41, 770, 40, 67, 41, 770, 40, 68, 41, 770, 40, 69, 41, 770, - 40, 70, 41, 770, 40, 71, 41, 770, 40, 72, 41, 770, 40, 73, 41, 770, 40, - 74, 41, 770, 40, 75, 41, 770, 40, 76, 41, 770, 40, 77, 41, 770, 40, 78, - 41, 770, 40, 79, 41, 770, 40, 80, 41, 770, 40, 81, 41, 770, 40, 82, 41, - 770, 40, 83, 41, 770, 40, 84, 41, 770, 40, 85, 41, 770, 40, 86, 41, 770, - 40, 87, 41, 770, 40, 88, 41, 770, 40, 89, 41, 770, 40, 90, 41, 770, - 12308, 83, 12309, 263, 67, 263, 82, 519, 67, 68, 519, 87, 90, 266, 65, + 1607, 514, 48, 46, 514, 48, 44, 514, 49, 44, 514, 50, 44, 514, 51, 44, + 514, 52, 44, 514, 53, 44, 514, 54, 44, 514, 55, 44, 514, 56, 44, 514, 57, + 44, 770, 40, 65, 41, 770, 40, 66, 41, 770, 40, 67, 41, 770, 40, 68, 41, + 770, 40, 69, 41, 770, 40, 70, 41, 770, 40, 71, 41, 770, 40, 72, 41, 770, + 40, 73, 41, 770, 40, 74, 41, 770, 40, 75, 41, 770, 40, 76, 41, 770, 40, + 77, 41, 770, 40, 78, 41, 770, 40, 79, 41, 770, 40, 80, 41, 770, 40, 81, + 41, 770, 40, 82, 41, 770, 40, 83, 41, 770, 40, 84, 41, 770, 40, 85, 41, + 770, 40, 86, 41, 770, 40, 87, 41, 770, 40, 88, 41, 770, 40, 89, 41, 770, + 40, 90, 41, 770, 12308, 83, 12309, 519, 67, 68, 519, 87, 90, 266, 65, 266, 66, 266, 67, 266, 68, 266, 69, 266, 70, 266, 71, 266, 72, 266, 73, 266, 74, 266, 75, 266, 76, 266, 77, 266, 78, 266, 79, 266, 80, 266, 81, 266, 82, 266, 83, 266, 84, 266, 85, 266, 86, 266, 87, 266, 88, 266, 89, - 266, 90, 522, 72, 86, 522, 77, 86, 522, 83, 68, 522, 83, 83, 778, 80, 80, - 86, 522, 87, 67, 515, 77, 67, 515, 77, 68, 515, 77, 82, 522, 68, 74, 522, - 12411, 12363, 522, 12467, 12467, 266, 12469, 266, 25163, 266, 23383, 266, - 21452, 266, 12487, 266, 20108, 266, 22810, 266, 35299, 266, 22825, 266, - 20132, 266, 26144, 266, 28961, 266, 26009, 266, 21069, 266, 24460, 266, - 20877, 266, 26032, 266, 21021, 266, 32066, 266, 29983, 266, 36009, 266, - 22768, 266, 21561, 266, 28436, 266, 25237, 266, 25429, 266, 19968, 266, - 19977, 266, 36938, 266, 24038, 266, 20013, 266, 21491, 266, 25351, 266, - 36208, 266, 25171, 266, 31105, 266, 31354, 266, 21512, 266, 28288, 266, - 26377, 266, 26376, 266, 30003, 266, 21106, 266, 21942, 266, 37197, 770, - 12308, 26412, 12309, 770, 12308, 19977, 12309, 770, 12308, 20108, 12309, - 770, 12308, 23433, 12309, 770, 12308, 28857, 12309, 770, 12308, 25171, - 12309, 770, 12308, 30423, 12309, 770, 12308, 21213, 12309, 770, 12308, - 25943, 12309, 263, 24471, 263, 21487, 262, 48, 262, 49, 262, 50, 262, 51, - 262, 52, 262, 53, 262, 54, 262, 55, 262, 56, 262, 57, 256, 20029, 256, - 20024, 256, 20033, 256, 131362, 256, 20320, 256, 20398, 256, 20411, 256, - 20482, 256, 20602, 256, 20633, 256, 20711, 256, 20687, 256, 13470, 256, - 132666, 256, 20813, 256, 20820, 256, 20836, 256, 20855, 256, 132380, 256, - 13497, 256, 20839, 256, 20877, 256, 132427, 256, 20887, 256, 20900, 256, - 20172, 256, 20908, 256, 20917, 256, 168415, 256, 20981, 256, 20995, 256, + 266, 90, 522, 72, 86, 522, 83, 68, 522, 83, 83, 778, 80, 80, 86, 522, 87, + 67, 515, 77, 67, 515, 77, 68, 515, 77, 82, 522, 68, 74, 522, 12411, + 12363, 522, 12467, 12467, 266, 12469, 266, 25163, 266, 23383, 266, 21452, + 266, 12487, 266, 20108, 266, 22810, 266, 35299, 266, 22825, 266, 20132, + 266, 26144, 266, 28961, 266, 26009, 266, 21069, 266, 24460, 266, 20877, + 266, 26032, 266, 21021, 266, 32066, 266, 29983, 266, 36009, 266, 22768, + 266, 21561, 266, 28436, 266, 25237, 266, 25429, 266, 19968, 266, 19977, + 266, 36938, 266, 24038, 266, 20013, 266, 21491, 266, 25351, 266, 36208, + 266, 25171, 266, 31105, 266, 31354, 266, 21512, 266, 28288, 266, 26377, + 266, 26376, 266, 30003, 266, 21106, 266, 21942, 266, 37197, 770, 12308, + 26412, 12309, 770, 12308, 19977, 12309, 770, 12308, 20108, 12309, 770, + 12308, 23433, 12309, 770, 12308, 28857, 12309, 770, 12308, 25171, 12309, + 770, 12308, 30423, 12309, 770, 12308, 21213, 12309, 770, 12308, 25943, + 12309, 263, 24471, 263, 21487, 256, 20029, 256, 20024, 256, 20033, 256, + 131362, 256, 20320, 256, 20411, 256, 20482, 256, 20602, 256, 20633, 256, + 20687, 256, 13470, 256, 132666, 256, 20820, 256, 20836, 256, 20855, 256, + 132380, 256, 13497, 256, 20839, 256, 20877, 256, 132427, 256, 20887, 256, + 20900, 256, 20172, 256, 20908, 256, 168415, 256, 20981, 256, 20995, 256, 13535, 256, 21051, 256, 21062, 256, 21106, 256, 21111, 256, 13589, 256, - 21191, 256, 21193, 256, 21220, 256, 21242, 256, 21253, 256, 21254, 256, - 21271, 256, 21321, 256, 21329, 256, 21338, 256, 21363, 256, 21373, 256, - 21375, 256, 21375, 256, 21375, 256, 133676, 256, 28784, 256, 21450, 256, - 21471, 256, 133987, 256, 21483, 256, 21489, 256, 21510, 256, 21662, 256, - 21560, 256, 21576, 256, 21608, 256, 21666, 256, 21750, 256, 21776, 256, - 21843, 256, 21859, 256, 21892, 256, 21892, 256, 21913, 256, 21931, 256, - 21939, 256, 21954, 256, 22294, 256, 22022, 256, 22295, 256, 22097, 256, - 22132, 256, 20999, 256, 22766, 256, 22478, 256, 22516, 256, 22541, 256, + 21253, 256, 21254, 256, 21321, 256, 21338, 256, 21363, 256, 21373, 256, + 21375, 256, 133676, 256, 28784, 256, 21450, 256, 21471, 256, 133987, 256, + 21483, 256, 21489, 256, 21510, 256, 21662, 256, 21560, 256, 21576, 256, + 21608, 256, 21666, 256, 21750, 256, 21776, 256, 21843, 256, 21859, 256, + 21892, 256, 21931, 256, 21939, 256, 21954, 256, 22294, 256, 22295, 256, + 22097, 256, 22132, 256, 22766, 256, 22478, 256, 22516, 256, 22541, 256, 22411, 256, 22578, 256, 22577, 256, 22700, 256, 136420, 256, 22770, 256, 22775, 256, 22790, 256, 22810, 256, 22818, 256, 22882, 256, 136872, 256, 136938, 256, 23020, 256, 23067, 256, 23079, 256, 23000, 256, 23142, 256, - 14062, 256, 14076, 256, 23304, 256, 23358, 256, 23358, 256, 137672, 256, - 23491, 256, 23512, 256, 23527, 256, 23539, 256, 138008, 256, 23551, 256, - 23558, 256, 24403, 256, 23586, 256, 14209, 256, 23648, 256, 23662, 256, - 23744, 256, 23693, 256, 138724, 256, 23875, 256, 138726, 256, 23918, 256, - 23915, 256, 23932, 256, 24033, 256, 24034, 256, 14383, 256, 24061, 256, - 24104, 256, 24125, 256, 24169, 256, 14434, 256, 139651, 256, 14460, 256, - 24240, 256, 24243, 256, 24246, 256, 24266, 256, 172946, 256, 24318, 256, - 140081, 256, 140081, 256, 33281, 256, 24354, 256, 24354, 256, 14535, 256, + 14062, 256, 14076, 256, 23304, 256, 23358, 256, 137672, 256, 23491, 256, + 23512, 256, 23539, 256, 138008, 256, 23551, 256, 23558, 256, 24403, 256, + 23586, 256, 14209, 256, 23648, 256, 23744, 256, 23693, 256, 138724, 256, + 23875, 256, 138726, 256, 23918, 256, 23915, 256, 23932, 256, 24033, 256, + 24034, 256, 14383, 256, 24061, 256, 24104, 256, 24125, 256, 24169, 256, + 14434, 256, 139651, 256, 14460, 256, 24240, 256, 24243, 256, 24246, 256, + 172946, 256, 24318, 256, 140081, 256, 33281, 256, 24354, 256, 14535, 256, 144056, 256, 156122, 256, 24418, 256, 24427, 256, 14563, 256, 24474, 256, 24525, 256, 24535, 256, 24569, 256, 24705, 256, 14650, 256, 14620, 256, - 24724, 256, 141012, 256, 24775, 256, 24904, 256, 24908, 256, 24910, 256, - 24908, 256, 24954, 256, 24974, 256, 25010, 256, 24996, 256, 25007, 256, - 25054, 256, 25074, 256, 25078, 256, 25104, 256, 25115, 256, 25181, 256, + 141012, 256, 24775, 256, 24904, 256, 24908, 256, 24954, 256, 25010, 256, + 24996, 256, 25007, 256, 25054, 256, 25104, 256, 25115, 256, 25181, 256, 25265, 256, 25300, 256, 25424, 256, 142092, 256, 25405, 256, 25340, 256, 25448, 256, 25475, 256, 25572, 256, 142321, 256, 25634, 256, 25541, 256, 25513, 256, 14894, 256, 25705, 256, 25726, 256, 25757, 256, 25719, 256, - 14956, 256, 25935, 256, 25964, 256, 143370, 256, 26083, 256, 26360, 256, - 26185, 256, 15129, 256, 26257, 256, 15112, 256, 15076, 256, 20882, 256, - 20885, 256, 26368, 256, 26268, 256, 32941, 256, 17369, 256, 26391, 256, - 26395, 256, 26401, 256, 26462, 256, 26451, 256, 144323, 256, 15177, 256, - 26618, 256, 26501, 256, 26706, 256, 26757, 256, 144493, 256, 26766, 256, - 26655, 256, 26900, 256, 15261, 256, 26946, 256, 27043, 256, 27114, 256, + 14956, 256, 25964, 256, 143370, 256, 26083, 256, 26360, 256, 26185, 256, + 15129, 256, 15112, 256, 15076, 256, 20882, 256, 20885, 256, 26368, 256, + 26268, 256, 32941, 256, 17369, 256, 26401, 256, 26462, 256, 26451, 256, + 144323, 256, 15177, 256, 26618, 256, 26501, 256, 26706, 256, 144493, 256, + 26766, 256, 26655, 256, 26900, 256, 26946, 256, 27043, 256, 27114, 256, 27304, 256, 145059, 256, 27355, 256, 15384, 256, 27425, 256, 145575, 256, - 27476, 256, 15438, 256, 27506, 256, 27551, 256, 27578, 256, 27579, 256, - 146061, 256, 138507, 256, 146170, 256, 27726, 256, 146620, 256, 27839, - 256, 27853, 256, 27751, 256, 27926, 256, 27966, 256, 28023, 256, 27969, - 256, 28009, 256, 28024, 256, 28037, 256, 146718, 256, 27956, 256, 28207, - 256, 28270, 256, 15667, 256, 28363, 256, 28359, 256, 147153, 256, 28153, - 256, 28526, 256, 147294, 256, 147342, 256, 28614, 256, 28729, 256, 28702, - 256, 28699, 256, 15766, 256, 28746, 256, 28797, 256, 28791, 256, 28845, - 256, 132389, 256, 28997, 256, 148067, 256, 29084, 256, 148395, 256, - 29224, 256, 29237, 256, 29264, 256, 149000, 256, 29312, 256, 29333, 256, + 27476, 256, 15438, 256, 27506, 256, 27551, 256, 27579, 256, 146061, 256, + 138507, 256, 146170, 256, 27726, 256, 146620, 256, 27839, 256, 27853, + 256, 27751, 256, 27926, 256, 27966, 256, 28009, 256, 28024, 256, 28037, + 256, 146718, 256, 27956, 256, 28207, 256, 28270, 256, 15667, 256, 28359, + 256, 147153, 256, 28153, 256, 28526, 256, 147294, 256, 147342, 256, + 28614, 256, 28729, 256, 28699, 256, 15766, 256, 28746, 256, 28797, 256, + 28791, 256, 28845, 256, 132389, 256, 28997, 256, 148067, 256, 29084, 256, + 148395, 256, 29224, 256, 29264, 256, 149000, 256, 29312, 256, 29333, 256, 149301, 256, 149524, 256, 29562, 256, 29579, 256, 16044, 256, 29605, 256, - 16056, 256, 16056, 256, 29767, 256, 29788, 256, 29809, 256, 29829, 256, - 29898, 256, 16155, 256, 29988, 256, 150582, 256, 30014, 256, 150674, 256, - 30064, 256, 139679, 256, 30224, 256, 151457, 256, 151480, 256, 151620, - 256, 16380, 256, 16392, 256, 30452, 256, 151795, 256, 151794, 256, - 151833, 256, 151859, 256, 30494, 256, 30495, 256, 30495, 256, 30538, 256, - 16441, 256, 30603, 256, 16454, 256, 16534, 256, 152605, 256, 30798, 256, - 30860, 256, 30924, 256, 16611, 256, 153126, 256, 31062, 256, 153242, 256, - 153285, 256, 31119, 256, 31211, 256, 16687, 256, 31296, 256, 31306, 256, - 31311, 256, 153980, 256, 154279, 256, 154279, 256, 31470, 256, 16898, - 256, 154539, 256, 31686, 256, 31689, 256, 16935, 256, 154752, 256, 31954, - 256, 17056, 256, 31976, 256, 31971, 256, 32000, 256, 155526, 256, 32099, - 256, 17153, 256, 32199, 256, 32258, 256, 32325, 256, 17204, 256, 156200, - 256, 156231, 256, 17241, 256, 156377, 256, 32634, 256, 156478, 256, - 32661, 256, 32762, 256, 32773, 256, 156890, 256, 156963, 256, 32864, 256, - 157096, 256, 32880, 256, 144223, 256, 17365, 256, 32946, 256, 33027, 256, - 17419, 256, 33086, 256, 23221, 256, 157607, 256, 157621, 256, 144275, - 256, 144284, 256, 33281, 256, 33284, 256, 36766, 256, 17515, 256, 33425, - 256, 33419, 256, 33437, 256, 21171, 256, 33457, 256, 33459, 256, 33469, - 256, 33510, 256, 158524, 256, 33509, 256, 33565, 256, 33635, 256, 33709, - 256, 33571, 256, 33725, 256, 33767, 256, 33879, 256, 33619, 256, 33738, - 256, 33740, 256, 33756, 256, 158774, 256, 159083, 256, 158933, 256, - 17707, 256, 34033, 256, 34035, 256, 34070, 256, 160714, 256, 34148, 256, - 159532, 256, 17757, 256, 17761, 256, 159665, 256, 159954, 256, 17771, - 256, 34384, 256, 34396, 256, 34407, 256, 34409, 256, 34473, 256, 34440, - 256, 34574, 256, 34530, 256, 34681, 256, 34600, 256, 34667, 256, 34694, - 256, 17879, 256, 34785, 256, 34817, 256, 17913, 256, 34912, 256, 34915, - 256, 161383, 256, 35031, 256, 35038, 256, 17973, 256, 35066, 256, 13499, - 256, 161966, 256, 162150, 256, 18110, 256, 18119, 256, 35488, 256, 35565, - 256, 35722, 256, 35925, 256, 162984, 256, 36011, 256, 36033, 256, 36123, - 256, 36215, 256, 163631, 256, 133124, 256, 36299, 256, 36284, 256, 36336, - 256, 133342, 256, 36564, 256, 36664, 256, 165330, 256, 165357, 256, - 37012, 256, 37105, 256, 37137, 256, 165678, 256, 37147, 256, 37432, 256, - 37591, 256, 37592, 256, 37500, 256, 37881, 256, 37909, 256, 166906, 256, - 38283, 256, 18837, 256, 38327, 256, 167287, 256, 18918, 256, 38595, 256, - 23986, 256, 38691, 256, 168261, 256, 168474, 256, 19054, 256, 19062, 256, - 38880, 256, 168970, 256, 19122, 256, 169110, 256, 38923, 256, 38923, 256, - 38953, 256, 169398, 256, 39138, 256, 19251, 256, 39209, 256, 39335, 256, - 39362, 256, 39422, 256, 19406, 256, 170800, 256, 39698, 256, 40000, 256, - 40189, 256, 19662, 256, 19693, 256, 40295, 256, 172238, 256, 19704, 256, - 172293, 256, 172558, 256, 172689, 256, 40635, 256, 19798, 256, 40697, - 256, 40702, 256, 40709, 256, 40719, 256, 40726, 256, 40763, 256, 173568, + 16056, 256, 29767, 256, 29788, 256, 29829, 256, 29898, 256, 16155, 256, + 29988, 256, 150582, 256, 30014, 256, 150674, 256, 139679, 256, 30224, + 256, 151457, 256, 151480, 256, 151620, 256, 16380, 256, 16392, 256, + 151795, 256, 151794, 256, 151833, 256, 151859, 256, 30494, 256, 30495, + 256, 30603, 256, 16454, 256, 16534, 256, 152605, 256, 30798, 256, 16611, + 256, 153126, 256, 153242, 256, 153285, 256, 31211, 256, 16687, 256, + 31306, 256, 31311, 256, 153980, 256, 154279, 256, 31470, 256, 16898, 256, + 154539, 256, 31686, 256, 31689, 256, 16935, 256, 154752, 256, 31954, 256, + 17056, 256, 31976, 256, 31971, 256, 32000, 256, 155526, 256, 32099, 256, + 17153, 256, 32199, 256, 32258, 256, 32325, 256, 17204, 256, 156200, 256, + 156231, 256, 17241, 256, 156377, 256, 32634, 256, 156478, 256, 32661, + 256, 32762, 256, 156890, 256, 156963, 256, 32864, 256, 157096, 256, + 32880, 256, 144223, 256, 17365, 256, 32946, 256, 33027, 256, 17419, 256, + 33086, 256, 23221, 256, 157607, 256, 157621, 256, 144275, 256, 144284, + 256, 33284, 256, 36766, 256, 17515, 256, 33425, 256, 33419, 256, 33437, + 256, 21171, 256, 33457, 256, 33459, 256, 33469, 256, 33510, 256, 158524, + 256, 33565, 256, 33635, 256, 33709, 256, 33571, 256, 33725, 256, 33767, + 256, 33619, 256, 33738, 256, 33740, 256, 33756, 256, 158774, 256, 159083, + 256, 158933, 256, 17707, 256, 34033, 256, 34035, 256, 34070, 256, 160714, + 256, 34148, 256, 159532, 256, 17757, 256, 17761, 256, 159665, 256, + 159954, 256, 17771, 256, 34384, 256, 34407, 256, 34409, 256, 34473, 256, + 34440, 256, 34574, 256, 34530, 256, 34600, 256, 34667, 256, 34694, 256, + 17879, 256, 34785, 256, 34817, 256, 17913, 256, 34912, 256, 34915, 256, + 161383, 256, 35031, 256, 35038, 256, 17973, 256, 35066, 256, 13499, 256, + 161966, 256, 162150, 256, 18110, 256, 18119, 256, 35488, 256, 35925, 256, + 162984, 256, 36011, 256, 36033, 256, 36123, 256, 36215, 256, 163631, 256, + 133124, 256, 36299, 256, 36284, 256, 36336, 256, 133342, 256, 36564, 256, + 165330, 256, 165357, 256, 37012, 256, 37105, 256, 37137, 256, 165678, + 256, 37147, 256, 37432, 256, 37591, 256, 37592, 256, 37500, 256, 37881, + 256, 37909, 256, 166906, 256, 38283, 256, 18837, 256, 38327, 256, 167287, + 256, 18918, 256, 38595, 256, 23986, 256, 38691, 256, 168261, 256, 168474, + 256, 19054, 256, 19062, 256, 38880, 256, 168970, 256, 19122, 256, 169110, + 256, 38953, 256, 169398, 256, 39138, 256, 19251, 256, 39209, 256, 39335, + 256, 39362, 256, 39422, 256, 19406, 256, 170800, 256, 40000, 256, 40189, + 256, 19662, 256, 19693, 256, 40295, 256, 172238, 256, 19704, 256, 172293, + 256, 172558, 256, 172689, 256, 40635, 256, 19798, 256, 40697, 256, 40702, + 256, 40709, 256, 40719, 256, 40726, 256, 40763, 256, 173568, }; /* index tables for the decomposition data */ @@ -4849,116 +4715,116 @@ static const unsigned short decomp_index2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 894, 896, 0, 898, 900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, 0, 0, - 0, 905, 0, 0, 0, 908, 0, 0, 0, 0, 0, 910, 913, 916, 919, 921, 924, 927, - 0, 930, 0, 933, 936, 939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 942, 945, 948, 951, 954, 957, 960, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 963, 966, - 969, 972, 975, 0, 978, 980, 982, 984, 987, 990, 992, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 994, 996, 998, 0, - 1000, 1002, 0, 0, 0, 1004, 0, 0, 0, 0, 0, 0, 1006, 1009, 0, 1012, 0, 0, - 0, 1015, 0, 0, 0, 0, 1018, 1021, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1027, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1030, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1033, 1036, 0, 1039, 0, 0, 0, 1042, 0, 0, 0, - 0, 1045, 1048, 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1054, 1057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 905, 0, 0, 0, 908, 0, 0, 0, 0, 0, 15, 910, 913, 916, 918, 921, 924, 0, + 927, 0, 930, 933, 936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 939, 942, 945, 948, 951, 954, 957, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 960, 963, + 966, 969, 972, 0, 975, 977, 979, 981, 984, 987, 989, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 991, 993, 995, 0, + 997, 999, 0, 0, 0, 1001, 0, 0, 0, 0, 0, 0, 1003, 1006, 0, 1009, 0, 0, 0, + 1012, 0, 0, 0, 0, 1015, 1018, 1021, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1027, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1030, 1033, 0, 1036, 0, 0, 0, 1039, 0, 0, 0, 0, + 1042, 1045, 1048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1051, 1054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1060, 1063, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1066, 1069, 1072, 1075, 0, 0, 1078, 1081, 0, 0, 1084, 1087, - 1090, 1093, 1096, 1099, 0, 0, 1102, 1105, 1108, 1111, 1114, 1117, 0, 0, - 1120, 1123, 1126, 1129, 1132, 1135, 1138, 1141, 1144, 1147, 1150, 1153, - 0, 0, 1156, 1159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1057, 1060, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1063, 1066, 1069, 1072, 0, 0, 1075, 1078, 0, 0, 1081, 1084, + 1087, 1090, 1093, 1096, 0, 0, 1099, 1102, 1105, 1108, 1111, 1114, 0, 0, + 1117, 1120, 1123, 1126, 1129, 1132, 1135, 1138, 1141, 1144, 1147, 1150, + 0, 0, 1153, 1156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1165, 1168, 1171, 1174, 1177, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1162, 1165, 1168, 1171, 1174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1180, 1183, 1186, 1189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1177, 1180, 1183, 1186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1192, 0, 1195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1189, 0, 1192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1201, 0, 0, 0, - 0, 0, 0, 0, 1204, 0, 0, 1207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1210, - 1213, 1216, 1219, 1222, 1225, 1228, 1231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1198, 0, 0, 0, + 0, 0, 0, 0, 1201, 0, 0, 1204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1207, + 1210, 1213, 1216, 1219, 1222, 1225, 1228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1234, 1237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1240, 1243, - 0, 1246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1231, 1234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1237, 1240, + 0, 1243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1249, 0, 0, 1252, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1246, 0, 0, 1249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1255, 1258, 1261, 0, 0, 1264, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1252, 1255, 1258, 0, 0, 1261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1267, 0, 0, 1270, 1273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1276, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1264, 0, 0, 1267, 1270, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1273, 1276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1285, 1288, 1291, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1282, 1285, 1288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1297, 0, 0, 0, 0, 0, 0, 1300, 1303, 0, 1306, 1309, 0, 0, 0, 0, + 0, 0, 0, 1294, 0, 0, 0, 0, 0, 0, 1297, 1300, 0, 1303, 1306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1312, 1315, 1318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1309, 1312, 1315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1321, 0, 1324, 1327, 1330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1318, 0, 1321, 1324, 1327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1339, 1342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1336, 1339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1347, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1350, 0, 0, 0, 0, 1353, 0, 0, 0, 0, 1356, 0, 0, 0, 0, 1359, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1365, 0, - 1368, 1371, 1374, 1377, 1380, 0, 0, 0, 0, 0, 0, 0, 1383, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1386, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1389, 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1395, 0, 0, 0, 0, 1398, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1344, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1347, 0, 0, 0, 0, 1350, 0, 0, 0, 0, 1353, 0, 0, 0, 0, 1356, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1362, 0, + 1365, 1368, 1371, 1374, 1377, 0, 0, 0, 0, 0, 0, 0, 1380, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1383, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1386, 0, 0, 0, 0, 1389, 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1395, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1398, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1404, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4967,676 +4833,669 @@ static const unsigned short decomp_index2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1407, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1409, 0, 1412, 0, 1415, 0, 1418, 0, 1421, 0, 0, - 0, 1424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1427, 0, 1430, - 0, 0, 1433, 1436, 0, 1439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1404, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1406, 0, 1409, 0, 1412, 0, 1415, 0, 1418, 0, 0, + 0, 1421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1424, 0, 1427, + 0, 0, 1430, 1433, 0, 1436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1442, 1444, 1446, 0, - 1448, 1450, 1452, 1454, 1456, 1458, 1460, 1462, 1464, 1466, 1468, 0, - 1470, 1472, 1474, 1476, 1478, 1480, 1482, 1484, 1486, 1488, 1490, 1492, - 1494, 1496, 1498, 1500, 1502, 1504, 0, 1506, 1508, 1510, 1512, 1514, - 1516, 1518, 1520, 1522, 1524, 1526, 1528, 1530, 1532, 1534, 1536, 1538, - 1540, 1542, 1544, 1546, 1548, 1550, 1552, 1554, 1556, 1558, 1560, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1564, 1566, 1568, 1570, 1572, 1574, 1576, 1578, 1580, 1582, 1584, 1586, - 1588, 1590, 1592, 1594, 1596, 1598, 1600, 1602, 1604, 1606, 1608, 1610, - 1612, 1614, 1616, 1618, 1620, 1622, 1624, 1626, 1628, 1630, 1632, 1634, - 1636, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1638, 1641, 1644, - 1647, 1650, 1653, 1656, 1659, 1662, 1665, 1668, 1671, 1674, 1677, 1680, - 1683, 1686, 1689, 1692, 1695, 1698, 1701, 1704, 1707, 1710, 1713, 1716, - 1719, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743, 1746, 1749, 1752, - 1755, 1758, 1761, 1764, 1767, 1770, 1773, 1776, 1779, 1782, 1785, 1788, - 1791, 1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1818, 1821, 1824, - 1827, 1830, 1833, 1836, 1839, 1842, 1845, 1848, 1851, 1854, 1857, 1860, - 1863, 1866, 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, 1893, 1896, - 1899, 1902, 1905, 1908, 1911, 1914, 1917, 1920, 1923, 1926, 1929, 1932, - 1935, 1938, 1941, 1944, 1947, 1950, 1953, 1956, 1959, 1962, 1965, 1968, - 1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, 2001, 2004, - 2007, 2010, 2013, 2016, 2019, 2022, 2025, 2028, 2031, 2034, 2037, 2040, - 2043, 2046, 2049, 2052, 2055, 2058, 2061, 2064, 2067, 2070, 2073, 2076, - 2079, 2082, 2085, 2088, 2091, 2094, 2097, 2100, 2103, 0, 0, 0, 0, 2106, - 2109, 2112, 2115, 2118, 2121, 2124, 2127, 2130, 2133, 2136, 2139, 2142, - 2145, 2148, 2151, 2154, 2157, 2160, 2163, 2166, 2169, 2172, 2175, 2178, - 2181, 2184, 2187, 2190, 2193, 2196, 2199, 2202, 2205, 2208, 2211, 2214, - 2217, 2220, 2223, 2226, 2229, 2232, 2235, 2238, 2241, 2244, 2247, 2250, - 2253, 2256, 2259, 2262, 2265, 2268, 2271, 2274, 2277, 2280, 2283, 2286, - 2289, 2292, 2295, 2298, 2301, 2304, 2307, 2310, 2313, 2316, 2319, 2322, - 2325, 2328, 2331, 2334, 2337, 2340, 2343, 2346, 2349, 2352, 2355, 2358, - 2361, 2364, 2367, 2370, 2373, 0, 0, 0, 0, 0, 0, 2376, 2379, 2382, 2385, - 2388, 2391, 2394, 2397, 2400, 2403, 2406, 2409, 2412, 2415, 2418, 2421, - 2424, 2427, 2430, 2433, 2436, 2439, 0, 0, 2442, 2445, 2448, 2451, 2454, - 2457, 0, 0, 2460, 2463, 2466, 2469, 2472, 2475, 2478, 2481, 2484, 2487, - 2490, 2493, 2496, 2499, 2502, 2505, 2508, 2511, 2514, 2517, 2520, 2523, - 2526, 2529, 2532, 2535, 2538, 2541, 2544, 2547, 2550, 2553, 2556, 2559, - 2562, 2565, 2568, 2571, 0, 0, 2574, 2577, 2580, 2583, 2586, 2589, 0, 0, - 2592, 2595, 2598, 2601, 2604, 2607, 2610, 2613, 0, 2616, 0, 2619, 0, - 2622, 0, 2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, 2652, - 2655, 2658, 2661, 2664, 2667, 2670, 2673, 2676, 2679, 2681, 2684, 2686, - 2689, 2691, 2694, 2696, 2699, 2701, 2704, 2706, 2709, 0, 0, 2711, 2714, - 2717, 2720, 2723, 2726, 2729, 2732, 2735, 2738, 2741, 2744, 2747, 2750, - 2753, 2756, 2759, 2762, 2765, 2768, 2771, 2774, 2777, 2780, 2783, 2786, - 2789, 2792, 2795, 2798, 2801, 2804, 2807, 2810, 2813, 2816, 2819, 2822, - 2825, 2828, 2831, 2834, 2837, 2840, 2843, 2846, 2849, 2852, 2855, 2858, - 2861, 2864, 2867, 0, 2870, 2873, 2876, 2879, 2882, 2885, 2887, 2890, - 2893, 2895, 2898, 2901, 2904, 2907, 2910, 0, 2913, 2916, 2919, 2922, - 2924, 2927, 2929, 2932, 2935, 2938, 2941, 2944, 2947, 2950, 0, 0, 2952, - 2955, 2958, 2961, 2964, 2967, 0, 2969, 2972, 2975, 2978, 2981, 2984, - 2987, 2989, 2992, 2995, 2998, 3001, 3004, 3007, 3010, 3012, 3015, 3018, - 3020, 0, 0, 3022, 3025, 3028, 0, 3031, 3034, 3037, 3040, 3042, 3045, - 3047, 3050, 3052, 0, 3055, 3057, 3059, 3061, 3063, 3065, 3067, 3069, - 3071, 3073, 3075, 0, 0, 0, 0, 0, 0, 3077, 0, 0, 0, 0, 0, 3079, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3082, 3084, 3087, 0, 0, 0, 0, 0, 0, 0, 0, - 3091, 0, 0, 0, 3093, 3096, 0, 3100, 3103, 0, 0, 0, 0, 3107, 0, 3110, 0, - 0, 0, 0, 0, 0, 0, 0, 3113, 3116, 3119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3122, 0, 0, 0, 0, 0, 0, 0, 3127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3129, 3131, 0, 0, 3133, 3135, 3137, 3139, 3141, 3143, - 3145, 3147, 3149, 3151, 3153, 3155, 3157, 3159, 3161, 3163, 3165, 3167, - 3169, 3171, 3173, 3175, 3177, 3179, 3181, 3183, 3185, 0, 3187, 3189, - 3191, 3193, 3195, 3197, 3199, 3201, 3203, 3205, 3207, 3209, 3211, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3216, 3220, 3224, 3226, 0, 3229, 3233, 3237, 0, 3239, 3242, 3244, - 3246, 3248, 3250, 3252, 3254, 3256, 3258, 3260, 0, 3262, 3264, 0, 0, - 3267, 3269, 3271, 3273, 3275, 0, 0, 3277, 3280, 3284, 0, 3287, 0, 3289, - 0, 3291, 0, 3293, 3295, 3297, 3299, 0, 3301, 3303, 3305, 0, 3307, 3309, - 3311, 3313, 3315, 3317, 3319, 0, 3321, 3325, 3327, 3329, 3331, 3333, 0, - 0, 0, 0, 3335, 3337, 3339, 3341, 3343, 0, 0, 0, 0, 0, 0, 3345, 3349, - 3353, 3358, 3362, 3366, 3370, 3374, 3378, 3382, 3386, 3390, 3394, 3398, - 3402, 3406, 3409, 3411, 3414, 3418, 3421, 3423, 3426, 3430, 3435, 3438, - 3440, 3443, 3447, 3449, 3451, 3453, 3455, 3457, 3460, 3464, 3467, 3469, - 3472, 3476, 3481, 3484, 3486, 3489, 3493, 3495, 3497, 3499, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3501, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3505, 3508, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3511, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3514, 3517, 3520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3523, 0, 0, 0, 0, 3526, - 0, 0, 3529, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3532, 0, 3535, 0, 0, 0, 0, 0, 3538, 3541, 0, 3545, 3548, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3552, 0, 0, 3555, 0, 0, 3558, - 0, 3561, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3564, 0, 3567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3570, 3573, 3576, 3579, - 3582, 0, 0, 3585, 3588, 0, 0, 3591, 3594, 0, 0, 0, 0, 0, 0, 3597, 3600, - 0, 0, 3603, 3606, 0, 0, 3609, 3612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3615, - 3618, 3621, 3624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3627, 3630, 3633, 3636, 0, 0, 0, 0, 0, 0, 3639, 3642, - 3645, 3648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3651, 3653, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3655, 3657, 3659, 3661, 3663, 3665, 3667, 3669, - 3671, 3673, 3676, 3679, 3682, 3685, 3688, 3691, 3694, 3697, 3700, 3703, - 3706, 3710, 3714, 3718, 3722, 3726, 3730, 3734, 3738, 3742, 3747, 3752, - 3757, 3762, 3767, 3772, 3777, 3782, 3787, 3792, 3797, 3800, 3803, 3806, - 3809, 3812, 3815, 3818, 3821, 3824, 3828, 3832, 3836, 3840, 3844, 3848, - 3852, 3856, 3860, 3864, 3868, 3872, 3876, 3880, 3884, 3888, 3892, 3896, - 3900, 3904, 3908, 3912, 3916, 3920, 3924, 3928, 3932, 3936, 3940, 3944, - 3948, 3952, 3956, 3960, 3964, 3968, 3972, 3974, 3976, 3978, 3980, 3982, - 3984, 3986, 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 4006, - 4008, 4010, 4012, 4014, 4016, 4018, 4020, 4022, 4024, 4026, 4028, 4030, - 4032, 4034, 4036, 4038, 4040, 4042, 4044, 4046, 4048, 4050, 4052, 4054, - 4056, 4058, 4060, 4062, 4064, 4066, 4068, 4070, 4072, 4074, 4076, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4078, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4083, 4087, 4090, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4094, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4097, 4099, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4101, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4103, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4107, - 4109, 4111, 4113, 4115, 4117, 4119, 4121, 4123, 4125, 4127, 4129, 4131, - 4133, 4135, 4137, 4139, 4141, 4143, 4145, 4147, 4149, 4151, 4153, 4155, - 4157, 4159, 4161, 4163, 4165, 4167, 4169, 4171, 4173, 4175, 4177, 4179, - 4181, 4183, 4185, 4187, 4189, 4191, 4193, 4195, 4197, 4199, 4201, 4203, - 4205, 4207, 4209, 4211, 4213, 4215, 4217, 4219, 4221, 4223, 4225, 4227, - 4229, 4231, 4233, 4235, 4237, 4239, 4241, 4243, 4245, 4247, 4249, 4251, - 4253, 4255, 4257, 4259, 4261, 4263, 4265, 4267, 4269, 4271, 4273, 4275, - 4277, 4279, 4281, 4283, 4285, 4287, 4289, 4291, 4293, 4295, 4297, 4299, - 4301, 4303, 4305, 4307, 4309, 4311, 4313, 4315, 4317, 4319, 4321, 4323, - 4325, 4327, 4329, 4331, 4333, 4335, 4337, 4339, 4341, 4343, 4345, 4347, - 4349, 4351, 4353, 4355, 4357, 4359, 4361, 4363, 4365, 4367, 4369, 4371, - 4373, 4375, 4377, 4379, 4381, 4383, 4385, 4387, 4389, 4391, 4393, 4395, - 4397, 4399, 4401, 4403, 4405, 4407, 4409, 4411, 4413, 4415, 4417, 4419, - 4421, 4423, 4425, 4427, 4429, 4431, 4433, 4435, 4437, 4439, 4441, 4443, - 4445, 4447, 4449, 4451, 4453, 4455, 4457, 4459, 4461, 4463, 4465, 4467, - 4469, 4471, 4473, 4475, 4477, 4479, 4481, 4483, 4485, 4487, 4489, 4491, - 4493, 4495, 4497, 4499, 4501, 4503, 4505, 4507, 4509, 4511, 4513, 4515, - 4517, 4519, 4521, 4523, 4525, 4527, 4529, 4531, 4533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1439, 1441, 1443, 0, + 1445, 1447, 1449, 1451, 1453, 1455, 1457, 1459, 1461, 1463, 1465, 0, + 1467, 1469, 1471, 1473, 1475, 1477, 1479, 6, 1481, 1483, 1485, 1487, + 1489, 1491, 1493, 1495, 1497, 1499, 0, 1501, 1503, 1505, 25, 1507, 1509, + 1511, 1513, 1515, 1517, 1519, 1521, 1523, 1525, 1527, 1529, 1531, 1533, + 1535, 1537, 1539, 1541, 1543, 1545, 1547, 1549, 1551, 1553, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1557, + 1559, 1561, 1563, 1497, 1565, 1567, 1569, 1571, 1573, 1575, 1577, 1579, + 1581, 1583, 1585, 1587, 1589, 1591, 1593, 1595, 1597, 1599, 1601, 1603, + 1605, 1607, 1609, 1611, 1613, 1615, 1617, 1619, 1621, 1623, 1625, 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4537, 0, 4539, - 4541, 4543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4545, 0, - 4548, 0, 4551, 0, 4554, 0, 4557, 0, 4560, 0, 4563, 0, 4566, 0, 4569, 0, - 4572, 0, 4575, 0, 4578, 0, 0, 4581, 0, 4584, 0, 4587, 0, 0, 0, 0, 0, 0, - 4590, 4593, 0, 4596, 4599, 0, 4602, 4605, 0, 4608, 4611, 0, 4614, 4617, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4620, - 0, 0, 0, 0, 0, 0, 4623, 4626, 0, 4629, 4632, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4635, 0, 4638, 0, 4641, 0, 4644, 0, 4647, 0, 4650, 0, 4653, 0, - 4656, 0, 4659, 0, 4662, 0, 4665, 0, 4668, 0, 0, 4671, 0, 4674, 0, 4677, - 0, 0, 0, 0, 0, 0, 4680, 4683, 0, 4686, 4689, 0, 4692, 4695, 0, 4698, - 4701, 0, 4704, 4707, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4710, 0, 0, 4713, 4716, 4719, 4722, 0, 0, 0, 4725, 4728, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1629, 1632, 1635, 1638, + 1641, 1644, 1647, 1650, 1653, 1656, 1659, 1662, 1665, 1668, 1671, 1674, + 1677, 1680, 1683, 1686, 1689, 1692, 1695, 1698, 1701, 1704, 1707, 1710, + 1713, 1716, 1719, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743, 1746, + 1749, 1752, 1755, 1758, 1761, 1764, 1767, 1770, 1773, 1776, 1779, 1782, + 1785, 1788, 1791, 1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1818, + 1821, 1824, 1827, 1830, 1833, 1836, 1839, 1842, 1845, 1848, 1851, 1854, + 1857, 1860, 1863, 1866, 1869, 1872, 1875, 1878, 1881, 1884, 1887, 1890, + 1893, 1896, 1899, 1902, 1905, 1908, 1911, 1914, 1917, 1920, 1923, 1926, + 1929, 1932, 1935, 1938, 1941, 1944, 1947, 1950, 1953, 1956, 1959, 1962, + 1965, 1968, 1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, + 2001, 2004, 2007, 2010, 2013, 2016, 2019, 2022, 2025, 2028, 2031, 2034, + 2037, 2040, 2043, 2046, 2049, 2052, 2055, 2058, 2061, 2064, 2067, 2070, + 2073, 2076, 2079, 2082, 2085, 2088, 2091, 2094, 0, 0, 0, 0, 2097, 2100, + 2103, 2106, 2109, 2112, 2115, 2118, 2121, 2124, 2127, 2130, 2133, 2136, + 2139, 2142, 2145, 2148, 2151, 2154, 2157, 2160, 2163, 2166, 2169, 2172, + 2175, 2178, 2181, 2184, 2187, 2190, 2193, 2196, 2199, 2202, 2205, 2208, + 2211, 2214, 2217, 2220, 2223, 2226, 2229, 2232, 2235, 2238, 2241, 2244, + 2247, 2250, 2253, 2256, 2259, 2262, 2265, 2268, 2271, 2274, 2277, 2280, + 2283, 2286, 2289, 2292, 2295, 2298, 2301, 2304, 2307, 2310, 2313, 2316, + 2319, 2322, 2325, 2328, 2331, 2334, 2337, 2340, 2343, 2346, 2349, 2352, + 2355, 2358, 2361, 2364, 0, 0, 0, 0, 0, 0, 2367, 2370, 2373, 2376, 2379, + 2382, 2385, 2388, 2391, 2394, 2397, 2400, 2403, 2406, 2409, 2412, 2415, + 2418, 2421, 2424, 2427, 2430, 0, 0, 2433, 2436, 2439, 2442, 2445, 2448, + 0, 0, 2451, 2454, 2457, 2460, 2463, 2466, 2469, 2472, 2475, 2478, 2481, + 2484, 2487, 2490, 2493, 2496, 2499, 2502, 2505, 2508, 2511, 2514, 2517, + 2520, 2523, 2526, 2529, 2532, 2535, 2538, 2541, 2544, 2547, 2550, 2553, + 2556, 2559, 2562, 0, 0, 2565, 2568, 2571, 2574, 2577, 2580, 0, 0, 2583, + 2586, 2589, 2592, 2595, 2598, 2601, 2604, 0, 2607, 0, 2610, 0, 2613, 0, + 2616, 2619, 2622, 2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, + 2652, 2655, 2658, 2661, 2664, 2667, 2670, 2672, 2675, 2677, 2680, 2682, + 2685, 2687, 2690, 2692, 2695, 2697, 2700, 0, 0, 2702, 2705, 2708, 2711, + 2714, 2717, 2720, 2723, 2726, 2729, 2732, 2735, 2738, 2741, 2744, 2747, + 2750, 2753, 2756, 2759, 2762, 2765, 2768, 2771, 2774, 2777, 2780, 2783, + 2786, 2789, 2792, 2795, 2798, 2801, 2804, 2807, 2810, 2813, 2816, 2819, + 2822, 2825, 2828, 2831, 2834, 2837, 2840, 2843, 2846, 2849, 2852, 2855, + 2858, 0, 2861, 2864, 2867, 2870, 2873, 2876, 2878, 2881, 2884, 2881, + 2886, 2889, 2892, 2895, 2898, 0, 2901, 2904, 2907, 2910, 2912, 2915, + 2917, 2920, 2923, 2926, 2929, 2932, 2935, 2938, 0, 0, 2940, 2943, 2946, + 2949, 2952, 2955, 0, 2957, 2960, 2963, 2966, 2969, 2972, 2975, 2977, + 2980, 2983, 2986, 2989, 2992, 2995, 2998, 3000, 3003, 3006, 3008, 0, 0, + 3010, 3013, 3016, 0, 3019, 3022, 3025, 3028, 3030, 3033, 3035, 3038, + 3040, 0, 3043, 3045, 3047, 3047, 3047, 3047, 3047, 1, 3047, 3047, 3047, + 0, 0, 0, 0, 0, 0, 3049, 0, 0, 0, 0, 0, 3051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3054, 3056, 3059, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3063, + 3066, 0, 3070, 3073, 0, 0, 0, 0, 3077, 0, 3080, 0, 0, 0, 0, 0, 0, 0, 0, + 3083, 3086, 3089, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3092, 0, 0, 0, + 0, 0, 0, 0, 3047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3097, + 3099, 0, 0, 3101, 3103, 3105, 3107, 3109, 3111, 3113, 3115, 3117, 3119, + 3121, 3123, 3125, 3127, 3129, 3131, 3133, 3135, 3137, 3139, 3141, 3143, + 3145, 3147, 3149, 3151, 3153, 0, 3155, 3157, 3159, 3161, 3163, 3165, + 3167, 3169, 3171, 3173, 3175, 3177, 3179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3184, 3188, 3192, + 3194, 0, 3197, 3201, 3205, 0, 3207, 3210, 3212, 3212, 3212, 3214, 3216, + 3218, 3218, 3220, 3222, 0, 3224, 3226, 0, 0, 3229, 3231, 3233, 3233, + 3233, 0, 0, 3235, 3238, 3242, 0, 3245, 0, 3247, 0, 3245, 0, 3249, 3251, + 3253, 3192, 0, 3255, 3257, 3259, 0, 3261, 3263, 3265, 3267, 3269, 3271, + 3273, 0, 3275, 3279, 3281, 3283, 3285, 3287, 0, 0, 0, 0, 3289, 3291, + 3255, 3273, 3293, 0, 0, 0, 0, 0, 0, 3295, 3299, 3303, 3308, 3312, 3316, + 3320, 3324, 3328, 3332, 3336, 3340, 3344, 3348, 3352, 3356, 3359, 3361, + 3364, 3368, 3371, 3373, 3376, 3380, 3385, 3388, 3390, 3393, 3397, 3399, + 3401, 3403, 3405, 3407, 3410, 3414, 3417, 3419, 3422, 3426, 3431, 3434, + 3436, 3439, 3443, 3445, 3447, 3449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3451, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3455, 3458, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3461, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3464, + 3467, 3470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3473, 0, 0, 0, 0, 3476, 0, 0, 3479, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3482, 0, 3485, + 0, 0, 0, 0, 0, 3488, 3491, 0, 3495, 3498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3502, 0, 0, 3505, 0, 0, 3508, 0, 3511, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3514, 0, 3517, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3520, 3523, 3526, 3529, 3532, 0, 0, 3535, 3538, + 0, 0, 3541, 3544, 0, 0, 0, 0, 0, 0, 3547, 3550, 0, 0, 3553, 3556, 0, 0, + 3559, 3562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3565, 3568, 3571, 3574, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3577, + 3580, 3583, 3586, 0, 0, 0, 0, 0, 0, 3589, 3592, 3595, 3598, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3601, 3603, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3605, 3607, 3609, 3611, 3613, 3615, 3617, 3619, 3621, 3623, 3626, 3629, + 3632, 3635, 3638, 3641, 3644, 3647, 3650, 3653, 3656, 3660, 3664, 3668, + 3672, 3676, 3680, 3684, 3688, 3692, 3697, 3702, 3707, 3712, 3717, 3722, + 3727, 3732, 3737, 3742, 3747, 3750, 3753, 3756, 3759, 3762, 3765, 3768, + 3771, 3774, 3778, 3782, 3786, 3790, 3794, 3798, 3802, 3806, 3810, 3814, + 3818, 3822, 3826, 3830, 3834, 3838, 3842, 3846, 3850, 3854, 3858, 3862, + 3866, 3870, 3874, 3878, 3882, 3886, 3890, 3894, 3898, 3902, 3906, 3910, + 3914, 3918, 3922, 3924, 3926, 3928, 3930, 3932, 3934, 3936, 3938, 3940, + 3942, 3944, 3946, 3948, 3950, 3952, 3954, 3956, 3958, 3960, 3962, 3964, + 3966, 3968, 3970, 3972, 3974, 3976, 3978, 3980, 3982, 3984, 3986, 3988, + 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 4006, 4008, 4010, 4012, + 4014, 4016, 4018, 4020, 4022, 4024, 4026, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4731, 4733, 4735, 4737, 4739, 4741, 4743, 4745, 4747, 4749, 4751, - 4753, 4755, 4757, 4759, 4761, 4763, 4765, 4767, 4769, 4771, 4773, 4775, - 4777, 4779, 4781, 4783, 4785, 4787, 4789, 4791, 4793, 4795, 4797, 4799, - 4801, 4803, 4805, 4807, 4809, 4811, 4813, 4815, 4817, 4819, 4821, 4823, - 4825, 4827, 4829, 4831, 4833, 4835, 4837, 4839, 4841, 4843, 4845, 4847, - 4849, 4851, 4853, 4855, 4857, 4859, 4861, 4863, 4865, 4867, 4869, 4871, - 4873, 4875, 4877, 4879, 4881, 4883, 4885, 4887, 4889, 4891, 4893, 4895, - 4897, 4899, 4901, 4903, 4905, 4907, 4909, 4911, 4913, 4915, 4917, 0, 0, - 0, 4919, 4921, 4923, 4925, 4927, 4929, 4931, 4933, 4935, 4937, 4939, - 4941, 4943, 4945, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4033, 4037, 4040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4947, 4951, 4955, 4959, 4963, 4967, 4971, 4975, 4979, - 4983, 4987, 4991, 4995, 4999, 5003, 5008, 5013, 5018, 5023, 5028, 5033, - 5038, 5043, 5048, 5053, 5058, 5063, 5068, 5073, 5078, 5086, 0, 5093, - 5097, 5101, 5105, 5109, 5113, 5117, 5121, 5125, 5129, 5133, 5137, 5141, - 5145, 5149, 5153, 5157, 5161, 5165, 5169, 5173, 5177, 5181, 5185, 5189, - 5193, 5197, 5201, 5205, 5209, 5213, 5217, 5221, 5225, 5229, 5233, 5237, - 5239, 5241, 5243, 0, 0, 0, 0, 0, 0, 0, 0, 5245, 5249, 5252, 5255, 5258, - 5261, 5264, 5267, 5270, 5273, 5276, 5279, 5282, 5285, 5288, 5291, 5294, - 5296, 5298, 5300, 5302, 5304, 5306, 5308, 5310, 5312, 5314, 5316, 5318, - 5320, 5322, 5325, 5328, 5331, 5334, 5337, 5340, 5343, 5346, 5349, 5352, - 5355, 5358, 5361, 5364, 5370, 5375, 0, 5378, 5380, 5382, 5384, 5386, - 5388, 5390, 5392, 5394, 5396, 5398, 5400, 5402, 5404, 5406, 5408, 5410, - 5412, 5414, 5416, 5418, 5420, 5422, 5424, 5426, 5428, 5430, 5432, 5434, - 5436, 5438, 5440, 5442, 5444, 5446, 5448, 5450, 5452, 5454, 5456, 5458, - 5460, 5462, 5464, 5466, 5468, 5470, 5472, 5474, 5476, 5479, 5482, 5485, - 5488, 5491, 5494, 5497, 5500, 5503, 5506, 5509, 5512, 5515, 5518, 5521, - 5524, 5527, 5530, 5533, 5536, 5539, 5542, 5545, 5548, 5552, 5556, 5560, - 5563, 5567, 5570, 5574, 5576, 5578, 5580, 5582, 5584, 5586, 5588, 5590, - 5592, 5594, 5596, 5598, 5600, 5602, 5604, 5606, 5608, 5610, 5612, 5614, - 5616, 5618, 5620, 5622, 5624, 5626, 5628, 5630, 5632, 5634, 5636, 5638, - 5640, 5642, 5644, 5646, 5648, 5650, 5652, 5654, 5656, 5658, 5660, 5662, - 5664, 5666, 5668, 5671, 5676, 5681, 5686, 5690, 5695, 5699, 5703, 5709, - 5714, 5718, 5722, 5726, 5731, 5736, 5740, 5744, 5747, 5751, 5756, 5761, - 5764, 5770, 5777, 5783, 5787, 5793, 5799, 5804, 5808, 5812, 5816, 5821, - 5827, 5832, 5836, 5840, 5844, 5847, 5850, 5853, 5856, 5860, 5864, 5870, - 5874, 5879, 5885, 5889, 5892, 5895, 5901, 5906, 5912, 5916, 5922, 5925, - 5929, 5933, 5937, 5941, 5945, 5950, 5954, 5957, 5961, 5965, 5969, 5974, - 5978, 5982, 5986, 5992, 5997, 6000, 6006, 6009, 6014, 6019, 6023, 6027, - 6031, 6036, 6039, 6043, 6048, 6051, 6057, 6061, 6064, 6067, 6070, 6073, - 6076, 6079, 6082, 6085, 6088, 6091, 6095, 6099, 6103, 6107, 6111, 6115, - 6119, 6123, 6127, 6131, 6135, 6139, 6143, 6147, 6151, 6155, 6158, 6161, - 6165, 6168, 6171, 6174, 6178, 6182, 6185, 6188, 6191, 6194, 6197, 6202, - 6205, 6208, 6211, 6214, 6217, 6220, 6223, 6226, 6230, 6235, 6238, 6241, - 6244, 6247, 6250, 6253, 6256, 6260, 6264, 6268, 6272, 6275, 6278, 6281, - 6284, 6287, 6290, 6293, 6296, 6299, 6302, 6306, 6310, 6313, 6317, 6321, - 6325, 6328, 6332, 6336, 6341, 6344, 6348, 6352, 6356, 6360, 6366, 6373, - 6376, 6379, 6382, 6385, 6388, 6391, 6394, 6397, 6400, 6403, 6406, 6409, - 6412, 6415, 6418, 6421, 6424, 6427, 6432, 6435, 6438, 6441, 6446, 6450, - 6453, 6456, 6459, 6462, 6465, 6468, 6471, 6474, 6477, 6480, 6484, 6487, - 6490, 6494, 6498, 6501, 6506, 6510, 6513, 6516, 6519, 6522, 6526, 6530, - 6533, 6536, 6539, 6542, 6545, 6548, 6551, 6554, 6557, 6561, 6565, 6569, - 6573, 6577, 6581, 6585, 6589, 6593, 6597, 6601, 6605, 6609, 6613, 6617, - 6621, 6625, 6629, 6633, 6637, 6641, 6645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6649, 6651, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6653, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6655, 6657, 6659, 0, 0, 0, 6661, 6663, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6665, 6667, 6669, - 6671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6673, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6675, 6677, 6679, 6681, 6683, 6685, - 6687, 6689, 6691, 6693, 6695, 6697, 6699, 6701, 6703, 6705, 6707, 6709, - 6711, 6713, 6715, 6717, 6719, 6721, 6723, 6725, 6727, 6729, 6731, 6733, - 6735, 6737, 6739, 6741, 6743, 6745, 6747, 6749, 6751, 6753, 6755, 6757, - 6759, 6761, 6763, 6765, 6767, 6769, 6771, 6773, 6775, 6777, 6779, 6781, - 6783, 6785, 6787, 6789, 6791, 6793, 6795, 6797, 6799, 6801, 6803, 6805, - 6807, 6809, 6811, 6813, 6815, 6817, 6819, 6821, 6823, 6825, 6827, 6829, - 6831, 6833, 6835, 6837, 6839, 6841, 6843, 6845, 6847, 6849, 6851, 6853, - 6855, 6857, 6859, 6861, 6863, 6865, 6867, 6869, 6871, 6873, 6875, 6877, - 6879, 6881, 6883, 6885, 6887, 6889, 6891, 6893, 6895, 6897, 6899, 6901, - 6903, 6905, 6907, 6909, 6911, 6913, 6915, 6917, 6919, 6921, 6923, 6925, - 6927, 6929, 6931, 6933, 6935, 6937, 6939, 6941, 6943, 6945, 6947, 6949, - 6951, 6953, 6955, 6957, 6959, 6961, 6963, 6965, 6967, 6969, 6971, 6973, - 6975, 6977, 6979, 6981, 6983, 6985, 6987, 6989, 6991, 6993, 6995, 6997, - 6999, 7001, 7003, 7005, 7007, 7009, 7011, 7013, 7015, 7017, 7019, 7021, - 7023, 7025, 7027, 7029, 7031, 7033, 7035, 7037, 7039, 7041, 7043, 7045, - 7047, 7049, 7051, 7053, 7055, 7057, 7059, 7061, 7063, 7065, 7067, 7069, - 7071, 7073, 7075, 7077, 7079, 7081, 7083, 7085, 7087, 7089, 7091, 7093, - 7095, 7097, 7099, 7101, 7103, 7105, 7107, 7109, 7111, 7113, 7115, 7117, - 7119, 7121, 7123, 7125, 7127, 7129, 7131, 7133, 7135, 7137, 7139, 7141, - 7143, 7145, 7147, 7149, 7151, 7153, 7155, 7157, 7159, 7161, 7163, 7165, - 7167, 7169, 7171, 7173, 7175, 7177, 7179, 7181, 7183, 7185, 7187, 7189, - 7191, 7193, 7195, 7197, 7199, 7201, 7203, 7205, 7207, 7209, 7211, 7213, - 0, 0, 7215, 0, 7217, 0, 0, 7219, 7221, 7223, 7225, 7227, 7229, 7231, - 7233, 7235, 7237, 0, 7239, 0, 7241, 0, 0, 7243, 7245, 0, 0, 0, 7247, - 7249, 7251, 7253, 7255, 7257, 7259, 7261, 7263, 7265, 7267, 7269, 7271, - 7273, 7275, 7277, 7279, 7281, 7283, 7285, 7287, 7289, 7291, 7293, 7295, - 7297, 7299, 7301, 7303, 7305, 7307, 7309, 7311, 7313, 7315, 7317, 7319, - 7321, 7323, 7325, 7327, 7329, 7331, 7333, 7335, 7337, 7339, 7341, 7343, - 7345, 7347, 7349, 7351, 7353, 7355, 7357, 7359, 7361, 7363, 7365, 7367, - 7369, 7371, 7373, 7375, 7377, 7379, 7381, 0, 0, 7383, 7385, 7387, 7389, - 7391, 7393, 7395, 7397, 7399, 7401, 7403, 7405, 7407, 7409, 7411, 7413, - 7415, 7417, 7419, 7421, 7423, 7425, 7427, 7429, 7431, 7433, 7435, 7437, - 7439, 7441, 7443, 7445, 7447, 7449, 7451, 7453, 7455, 7457, 7459, 7461, - 7463, 7465, 7467, 7469, 7471, 7473, 7475, 7477, 7479, 7481, 7483, 7485, - 7487, 7489, 7491, 7493, 7495, 7497, 7499, 7501, 7503, 7505, 7507, 7509, - 7511, 7513, 7515, 7517, 7519, 7521, 7523, 7525, 7527, 7529, 7531, 7533, - 7535, 7537, 7539, 7541, 7543, 7545, 7547, 7549, 7551, 7553, 7555, 7557, - 7559, 7561, 7563, 7565, 7567, 7569, 7571, 7573, 7575, 7577, 7579, 7581, - 7583, 7585, 7587, 7589, 7591, 7593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 7595, 7598, 7601, 7604, 7608, 7612, 7615, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7618, 7621, 7624, 7627, 7630, 0, 0, 0, 0, 0, 7633, 0, 7636, - 7639, 7641, 7643, 7645, 7647, 7649, 7651, 7653, 7655, 7657, 7659, 7662, - 7665, 7668, 7671, 7674, 7677, 7680, 7683, 7686, 7689, 7692, 7695, 0, - 7698, 7701, 7704, 7707, 7710, 0, 7713, 0, 7716, 7719, 0, 7722, 7725, 0, - 7728, 7731, 7734, 7737, 7740, 7743, 7746, 7749, 7752, 7755, 7758, 7760, - 7762, 7764, 7766, 7768, 7770, 7772, 7774, 7776, 7778, 7780, 7782, 7784, - 7786, 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, 7804, 7806, 7808, - 7810, 7812, 7814, 7816, 7818, 7820, 7822, 7824, 7826, 7828, 7830, 7832, - 7834, 7836, 7838, 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, 7856, - 7858, 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, 7876, 7878, 7880, - 7882, 7884, 7886, 7888, 7890, 7892, 7894, 7896, 7898, 7900, 7902, 7904, - 7906, 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, 7924, 7926, 7928, - 7930, 7932, 7934, 7936, 7938, 7940, 7942, 7944, 7946, 7948, 7950, 7952, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 7954, 7956, 7958, 7960, 7962, 7964, 7966, - 7968, 7970, 7972, 7974, 7976, 7978, 7980, 7982, 7984, 7986, 7988, 7990, - 7992, 7994, 7996, 7998, 8000, 8003, 8006, 8009, 8012, 8015, 8018, 8021, - 8024, 8027, 8030, 8033, 8036, 8039, 8042, 8045, 8048, 8051, 8054, 8056, - 8058, 8060, 8062, 8065, 8068, 8071, 8074, 8077, 8080, 8083, 8086, 8089, - 8092, 8095, 8098, 8101, 8104, 8107, 8110, 8113, 8116, 8119, 8122, 8125, - 8128, 8131, 8134, 8137, 8140, 8143, 8146, 8149, 8152, 8155, 8158, 8161, - 8164, 8167, 8170, 8173, 8176, 8179, 8182, 8185, 8188, 8191, 8194, 8197, - 8200, 8203, 8206, 8209, 8212, 8215, 8218, 8221, 8224, 8227, 8230, 8233, - 8236, 8239, 8242, 8245, 8248, 8251, 8254, 8257, 8260, 8263, 8266, 8269, - 8272, 8275, 8278, 8281, 8284, 8287, 8290, 8293, 8296, 8299, 8302, 8305, - 8308, 8311, 8314, 8317, 8320, 8323, 8326, 8329, 8332, 8335, 8338, 8341, - 8344, 8348, 8352, 8356, 8360, 8364, 8368, 8371, 8374, 8377, 8380, 8383, - 8386, 8389, 8392, 8395, 8398, 8401, 8404, 8407, 8410, 8413, 8416, 8419, - 8422, 8425, 8428, 8431, 8434, 8437, 8440, 8443, 8446, 8449, 8452, 8455, - 8458, 8461, 8464, 8467, 8470, 8473, 8476, 8479, 8482, 8485, 8488, 8491, - 8494, 8497, 8500, 8503, 8506, 8509, 8512, 8515, 8518, 8521, 8524, 8527, - 8530, 8533, 8536, 8539, 8542, 8545, 8548, 8551, 8554, 8557, 8560, 8563, - 8566, 8569, 8572, 8575, 8578, 8581, 8584, 8587, 8590, 8593, 8596, 8599, - 8602, 8605, 8608, 8611, 8614, 8617, 8620, 8623, 8626, 8629, 8632, 8635, - 8638, 8641, 8644, 8647, 8650, 8653, 8656, 8659, 8662, 8665, 8668, 8671, - 8674, 8677, 8680, 8683, 8686, 8689, 8692, 8695, 8698, 8701, 8704, 8707, - 8710, 8713, 8716, 8719, 8722, 8725, 8728, 8731, 8734, 8737, 8740, 8743, - 8746, 8749, 8752, 8755, 8758, 8761, 8764, 8767, 8770, 8773, 8776, 8779, - 8782, 8785, 8788, 8791, 8794, 8798, 8802, 8806, 8809, 8812, 8815, 8818, - 8821, 8824, 8827, 8830, 8833, 8836, 8839, 8842, 8845, 8848, 8851, 8854, - 8857, 8860, 8863, 8866, 8869, 8872, 8875, 8878, 8881, 8884, 8887, 8890, - 8893, 8896, 8899, 8902, 8905, 8908, 8911, 8914, 8917, 8920, 8923, 8926, - 8929, 8932, 8935, 8938, 8941, 8944, 8947, 8950, 8953, 8956, 8959, 8962, - 8965, 8968, 8971, 8974, 8977, 8980, 8983, 8986, 8989, 8992, 8995, 8998, - 9001, 9004, 9007, 9010, 9013, 9016, 9019, 9022, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9025, 9029, 9033, 9037, 9041, 9045, 9049, - 9053, 9057, 9061, 9065, 9069, 9073, 9077, 9081, 9085, 9089, 9093, 9097, - 9101, 9105, 9109, 9113, 9117, 9121, 9125, 9129, 9133, 9137, 9141, 9145, - 9149, 9153, 9157, 9161, 9165, 9169, 9173, 9177, 9181, 9185, 9189, 9193, - 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9233, 9237, 9241, - 9245, 9249, 9253, 9257, 9261, 9265, 9269, 9273, 9277, 0, 0, 9281, 9285, - 9289, 9293, 9297, 9301, 9305, 9309, 9313, 9317, 9321, 9325, 9329, 9333, - 9337, 9341, 9345, 9349, 9353, 9357, 9361, 9365, 9369, 9373, 9377, 9381, - 9385, 9389, 9393, 9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, - 9433, 9437, 9441, 9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, - 9481, 9485, 9489, 9493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9497, 9501, 9505, 9510, 9515, 9520, 9525, 9530, 9535, 9540, 9544, 9563, - 9572, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9577, - 9579, 9581, 9583, 9585, 9587, 9589, 9591, 9593, 9595, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9597, 9599, 9601, 9603, - 9605, 9607, 9609, 9611, 9613, 9615, 9617, 9619, 9621, 9623, 9625, 9627, - 9629, 9631, 9633, 9635, 9637, 0, 0, 9639, 9641, 9643, 9645, 9647, 9649, - 9651, 9653, 9655, 9657, 9659, 9661, 0, 9663, 9665, 9667, 9669, 9671, - 9673, 9675, 9677, 9679, 9681, 9683, 9685, 9687, 9689, 9691, 9693, 9695, - 9697, 9699, 0, 9701, 9703, 9705, 9707, 0, 0, 0, 0, 9709, 9712, 9715, 0, - 9718, 0, 9721, 9724, 9727, 9730, 9733, 9736, 9739, 9742, 9745, 9748, - 9751, 9753, 9755, 9757, 9759, 9761, 9763, 9765, 9767, 9769, 9771, 9773, - 9775, 9777, 9779, 9781, 9783, 9785, 9787, 9789, 9791, 9793, 9795, 9797, - 9799, 9801, 9803, 9805, 9807, 9809, 9811, 9813, 9815, 9817, 9819, 9821, - 9823, 9825, 9827, 9829, 9831, 9833, 9835, 9837, 9839, 9841, 9843, 9845, - 9847, 9849, 9851, 9853, 9855, 9857, 9859, 9861, 9863, 9865, 9867, 9869, - 9871, 9873, 9875, 9877, 9879, 9881, 9883, 9885, 9887, 9889, 9891, 9893, - 9895, 9897, 9899, 9901, 9903, 9905, 9907, 9909, 9911, 9913, 9915, 9917, - 9919, 9921, 9923, 9925, 9927, 9929, 9931, 9933, 9935, 9937, 9939, 9941, - 9943, 9945, 9947, 9949, 9951, 9953, 9955, 9957, 9959, 9961, 9963, 9965, - 9967, 9969, 9971, 9973, 9975, 9977, 9979, 9981, 9983, 9985, 9988, 9991, - 9994, 9997, 10000, 10003, 10006, 0, 0, 0, 0, 10009, 10011, 10013, 10015, - 10017, 10019, 10021, 10023, 10025, 10027, 10029, 10031, 10033, 10035, - 10037, 10039, 10041, 10043, 10045, 10047, 10049, 10051, 10053, 10055, - 10057, 10059, 10061, 10063, 10065, 10067, 10069, 10071, 10073, 10075, - 10077, 10079, 10081, 10083, 10085, 10087, 10089, 10091, 10093, 10095, - 10097, 10099, 10101, 10103, 10105, 10107, 10109, 10111, 10113, 10115, - 10117, 10119, 10121, 10123, 10125, 10127, 10129, 10131, 10133, 10135, - 10137, 10139, 10141, 10143, 10145, 10147, 10149, 10151, 10153, 10155, - 10157, 10159, 10161, 10163, 10165, 10167, 10169, 10171, 10173, 10175, - 10177, 10179, 10181, 10183, 10185, 10187, 10189, 10191, 10193, 10195, - 10197, 10199, 10201, 10203, 10205, 10207, 10209, 10211, 10213, 10215, - 10217, 10219, 10221, 10223, 10225, 10227, 10229, 10231, 10233, 10235, - 10237, 10239, 10241, 10243, 10245, 10247, 10249, 10251, 10253, 10255, - 10257, 10259, 10261, 10263, 10265, 10267, 10269, 10271, 10273, 10275, - 10277, 10279, 10281, 10283, 10285, 10287, 10289, 10291, 10293, 10295, - 10297, 10299, 10301, 10303, 10305, 10307, 10309, 10311, 10313, 10315, - 10317, 10319, 10321, 10323, 10325, 10327, 10329, 10331, 10333, 10335, - 10337, 10339, 10341, 10343, 10345, 10347, 10349, 10351, 10353, 10355, - 10357, 10359, 10361, 10363, 10365, 10367, 10369, 10371, 10373, 10375, - 10377, 10379, 10381, 10383, 10385, 10387, 0, 0, 0, 10389, 10391, 10393, - 10395, 10397, 10399, 0, 0, 10401, 10403, 10405, 10407, 10409, 10411, 0, - 0, 10413, 10415, 10417, 10419, 10421, 10423, 0, 0, 10425, 10427, 10429, - 0, 0, 0, 10431, 10433, 10435, 10437, 10439, 10441, 10443, 0, 10445, - 10447, 10449, 10451, 10453, 10455, 10457, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 10459, 10461, 10463, 10465, 10467, 0, 10469, - 10471, 10473, 10475, 10477, 10479, 10481, 10483, 10485, 10487, 10489, - 10491, 10493, 10495, 10497, 10499, 10501, 10503, 10505, 10507, 10509, - 10511, 10513, 10515, 10517, 10519, 10521, 10523, 10525, 10527, 10529, - 10531, 10533, 10535, 10537, 10539, 10541, 10543, 10545, 10547, 10549, - 10551, 0, 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, 10569, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4044, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4047, 4049, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4051, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4053, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10571, 0, 10574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10577, 0, 0, + 4055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4057, 4059, 4061, 4063, 4065, + 4067, 4069, 4071, 4073, 4075, 4077, 4079, 4081, 4083, 4085, 4087, 4089, + 4091, 4093, 4095, 4097, 4099, 4101, 4103, 4105, 4107, 4109, 4111, 4113, + 4115, 4117, 4119, 4121, 4123, 4125, 4127, 4129, 4131, 4133, 4135, 4137, + 4139, 4141, 4143, 4145, 4147, 4149, 4151, 4153, 4155, 4157, 4159, 4161, + 4163, 4165, 4167, 4169, 4171, 4173, 4175, 4177, 4179, 4181, 4183, 4185, + 4187, 4189, 4191, 4193, 4195, 4197, 4199, 4201, 4203, 4205, 4207, 4209, + 4211, 4213, 4215, 4217, 4219, 4221, 4223, 4225, 4227, 4229, 4231, 4233, + 4235, 4237, 4239, 4241, 4243, 4245, 4247, 4249, 4251, 4253, 4255, 4257, + 4259, 4261, 4263, 4265, 4267, 4269, 4271, 4273, 4275, 4277, 4279, 4281, + 4283, 4285, 4287, 4289, 4291, 4293, 4295, 4297, 4299, 4301, 4303, 4305, + 4307, 4309, 4311, 4313, 4315, 4317, 4319, 4321, 4323, 4325, 4327, 4329, + 4331, 4333, 4335, 4337, 4339, 4341, 4343, 4345, 4347, 4349, 4351, 4353, + 4355, 4357, 4359, 4361, 4363, 4365, 4367, 4369, 4371, 4373, 4375, 4377, + 4379, 4381, 4383, 4385, 4387, 4389, 4391, 4393, 4395, 4397, 4399, 4401, + 4403, 4405, 4407, 4409, 4411, 4413, 4415, 4417, 4419, 4421, 4423, 4425, + 4427, 4429, 4431, 4433, 4435, 4437, 4439, 4441, 4443, 4445, 4447, 4449, + 4451, 4453, 4455, 4457, 4459, 4461, 4463, 4465, 4467, 4469, 4471, 4473, + 4475, 4477, 4479, 4481, 4483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4487, 0, 4103, 4489, 4491, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4493, 0, 4496, 0, 4499, 0, 4502, + 0, 4505, 0, 4508, 0, 4511, 0, 4514, 0, 4517, 0, 4520, 0, 4523, 0, 4526, + 0, 0, 4529, 0, 4532, 0, 4535, 0, 0, 0, 0, 0, 0, 4538, 4541, 0, 4544, + 4547, 0, 4550, 4553, 0, 4556, 4559, 0, 4562, 4565, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4568, 0, 0, 0, 0, 0, 0, + 4571, 4574, 0, 4577, 4580, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4583, 0, + 4586, 0, 4589, 0, 4592, 0, 4595, 0, 4598, 0, 4601, 0, 4604, 0, 4607, 0, + 4610, 0, 4613, 0, 4616, 0, 0, 4619, 0, 4622, 0, 4625, 0, 0, 0, 0, 0, 0, + 4628, 4631, 0, 4634, 4637, 0, 4640, 4643, 0, 4646, 4649, 0, 4652, 4655, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4658, + 0, 0, 4661, 4664, 4667, 4670, 0, 0, 0, 4673, 4676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4679, 4681, 4683, + 4685, 4687, 4689, 4691, 4693, 4695, 4697, 4699, 4701, 4703, 4705, 4707, + 4709, 4711, 4713, 4715, 4717, 4719, 4721, 4723, 4725, 4727, 4729, 4731, + 4733, 4735, 4737, 4739, 4741, 4743, 4745, 4747, 4749, 4751, 4753, 4755, + 4757, 4759, 4761, 4763, 4765, 4767, 4769, 4771, 4773, 4775, 4777, 4779, + 4781, 4783, 4785, 4787, 4789, 4791, 4793, 4795, 4797, 4799, 4801, 4803, + 4805, 4807, 4809, 4811, 4813, 4815, 4817, 4819, 4821, 4823, 4825, 4827, + 4829, 4831, 4833, 4835, 4837, 4839, 4841, 4843, 4845, 4847, 4849, 4851, + 4853, 4855, 4857, 4859, 4861, 4863, 4865, 0, 0, 0, 4867, 4869, 4871, + 4873, 4875, 4877, 4879, 4881, 4883, 4885, 4887, 4889, 4891, 4893, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 10580, 10583, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4895, + 4899, 4903, 4907, 4911, 4915, 4919, 4923, 4927, 4931, 4935, 4939, 4943, + 4947, 4951, 4956, 4961, 4966, 4971, 4976, 4981, 4986, 4991, 4996, 5001, + 5006, 5011, 5016, 5021, 5026, 5034, 0, 5041, 5045, 5049, 5053, 5057, + 5061, 5065, 5069, 5073, 5077, 5081, 5085, 5089, 5093, 5097, 5101, 5105, + 5109, 5113, 5117, 5121, 5125, 5129, 5133, 5137, 5141, 5145, 5149, 5153, + 5157, 5161, 5165, 5169, 5173, 5177, 5181, 5185, 5187, 5189, 5191, 0, 0, + 0, 0, 0, 0, 0, 0, 5193, 5197, 5200, 5203, 5206, 5209, 5212, 5215, 5218, + 5221, 5224, 5227, 5230, 5233, 5236, 5239, 5242, 5244, 5246, 5248, 5250, + 5252, 5254, 5256, 5258, 5260, 5262, 5264, 5266, 5268, 5270, 5273, 5276, + 5279, 5282, 5285, 5288, 5291, 5294, 5297, 5300, 5303, 5306, 5309, 5312, + 5318, 5323, 0, 5326, 5328, 5330, 5332, 5334, 5336, 5338, 5340, 5342, + 5344, 5346, 5348, 5350, 5352, 5354, 5356, 5358, 5360, 5362, 5364, 5366, + 5368, 5370, 5372, 5374, 5376, 5378, 5380, 5382, 5384, 5386, 5388, 5390, + 5392, 5394, 5396, 5398, 5400, 5402, 5404, 5406, 5408, 5410, 5412, 5414, + 5416, 5418, 5420, 5422, 5424, 5427, 5430, 5433, 5436, 5439, 5442, 5445, + 5448, 5451, 5454, 5457, 5460, 5463, 5466, 5469, 5472, 5475, 5478, 5481, + 5484, 5487, 5490, 5493, 5496, 5500, 5504, 5508, 5511, 5515, 5518, 5522, + 5524, 5526, 5528, 5530, 5532, 5534, 5536, 5538, 5540, 5542, 5544, 5546, + 5548, 5550, 5552, 5554, 5556, 5558, 5560, 5562, 5564, 5566, 5568, 5570, + 5572, 5574, 5576, 5578, 5580, 5582, 5584, 5586, 5588, 5590, 5592, 5594, + 5596, 5598, 5600, 5602, 5604, 5606, 5608, 5610, 5612, 5614, 5616, 5619, + 5624, 5629, 5634, 5638, 5643, 5647, 5651, 5657, 5662, 5666, 5670, 5674, + 5679, 5684, 5688, 5692, 5695, 5699, 5704, 5709, 5712, 5718, 5725, 5731, + 5735, 5741, 5747, 5752, 5756, 5760, 5764, 5769, 5775, 5780, 5784, 5788, + 5792, 5795, 5798, 5801, 5804, 5808, 5812, 5818, 5822, 5827, 5833, 5837, + 5840, 5843, 5849, 5854, 5860, 5864, 5870, 5873, 5877, 5881, 5885, 5889, + 5893, 5898, 5902, 5905, 5909, 5913, 5917, 5922, 5926, 5930, 5934, 5940, + 5945, 5948, 5954, 5957, 5962, 5967, 5971, 5975, 5979, 5984, 5987, 5991, + 5996, 5999, 6005, 6009, 6012, 6015, 6018, 6021, 6024, 6027, 6030, 6033, + 6036, 6039, 6043, 6047, 6051, 6055, 6059, 6063, 6067, 6071, 6075, 6079, + 6083, 6087, 6091, 6095, 6099, 6103, 6106, 6109, 6113, 6116, 6119, 6122, + 6126, 6130, 6133, 6136, 6139, 6142, 6145, 6150, 6153, 6156, 6159, 6162, + 6165, 6168, 6171, 6174, 6178, 6183, 6186, 6189, 6192, 6195, 6198, 6201, + 6204, 6208, 6212, 6216, 6220, 6223, 6226, 6229, 6232, 6235, 6238, 6241, + 6244, 6247, 6250, 6254, 6258, 6261, 6265, 6269, 6273, 6276, 6280, 6284, + 6289, 6292, 6296, 6300, 6304, 6308, 6314, 6321, 6324, 6327, 6330, 6333, + 6336, 6339, 6342, 6345, 6348, 6351, 6354, 6357, 6360, 6363, 6366, 6369, + 6372, 6375, 6380, 6383, 6386, 6389, 6394, 6398, 6401, 6404, 6407, 6410, + 6413, 6416, 6419, 6422, 6425, 6428, 6432, 6435, 6438, 6442, 6446, 6449, + 6454, 6458, 6461, 6464, 6467, 6470, 6474, 6478, 6481, 6484, 6487, 6490, + 6493, 6496, 6499, 6502, 6505, 6509, 6513, 6517, 6521, 6525, 6529, 6533, + 6537, 6541, 6545, 6549, 6553, 6557, 6561, 6565, 6569, 6573, 6577, 6581, + 6585, 6589, 6593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6597, 6599, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6601, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6603, 6605, + 6607, 0, 0, 0, 6609, 6611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6613, 6615, 6617, 6619, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6621, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6623, 6625, 6627, 6629, 6631, 6633, 6635, 6637, 6637, 6639, + 6641, 6643, 6645, 6647, 6649, 6651, 6653, 6655, 6657, 6659, 6661, 6663, + 6665, 6667, 6669, 6671, 6673, 6675, 6677, 6679, 6681, 6683, 6685, 6687, + 6689, 6691, 6693, 6695, 6697, 6699, 6701, 6703, 6705, 6707, 6709, 6711, + 6713, 6715, 6717, 6719, 6721, 6723, 6725, 6727, 6729, 6731, 6733, 6735, + 6737, 6739, 6741, 6743, 6745, 6747, 6749, 6751, 6753, 6755, 6757, 6759, + 6761, 6763, 6765, 6767, 6769, 6771, 6773, 6775, 6777, 6779, 6781, 6783, + 6785, 6787, 6789, 6791, 6793, 6795, 6797, 6799, 6801, 6803, 6661, 6805, + 6807, 6809, 6811, 6813, 6815, 6817, 6819, 6821, 6823, 6825, 6827, 6829, + 6831, 6833, 6835, 6837, 6839, 6841, 6843, 6845, 6847, 6849, 6851, 6853, + 6855, 6857, 6859, 6861, 6863, 6865, 6867, 6869, 6871, 6873, 6875, 6877, + 6879, 6881, 6883, 6885, 6887, 6889, 6891, 6893, 6895, 6897, 6899, 6901, + 6903, 6905, 6907, 6909, 6911, 6913, 6915, 6917, 6919, 6921, 6923, 6925, + 6927, 6929, 6931, 6933, 6935, 6937, 6939, 6841, 6941, 6943, 6945, 6947, + 6949, 6951, 6953, 6955, 6809, 6957, 6959, 6961, 6963, 6965, 6967, 6969, + 6971, 6973, 6975, 6977, 6979, 6981, 6983, 6985, 6987, 6989, 6991, 6993, + 6995, 6661, 6997, 6999, 7001, 7003, 7005, 7007, 7009, 7011, 7013, 7015, + 7017, 7019, 7021, 7023, 7025, 7027, 7029, 7031, 7033, 7035, 7037, 7039, + 7041, 7043, 7045, 7047, 7049, 6813, 7051, 7053, 7055, 7057, 7059, 7061, + 7063, 7065, 7067, 7069, 7071, 7073, 7075, 7077, 7079, 7081, 7083, 7085, + 7087, 7089, 7091, 7093, 7095, 7097, 7099, 7101, 7103, 7105, 7107, 7109, + 7111, 7113, 7115, 7117, 7119, 7121, 7123, 7125, 7127, 7129, 7131, 7133, + 7135, 7137, 7139, 7141, 7143, 7145, 7147, 7149, 0, 0, 7151, 0, 7153, 0, + 0, 7155, 7157, 7159, 7161, 7163, 7165, 7167, 7169, 7171, 7173, 0, 7175, + 0, 7177, 0, 0, 7179, 7181, 0, 0, 0, 7183, 7185, 7187, 7189, 7191, 7193, + 7195, 7197, 7199, 7201, 7203, 7205, 7207, 7209, 7211, 7213, 7215, 7217, + 7219, 7221, 7223, 7225, 7227, 7229, 7231, 7233, 7235, 7237, 7239, 7241, + 7243, 7245, 7247, 7249, 7251, 7253, 7255, 7257, 7259, 7261, 7263, 7265, + 7267, 7269, 7271, 6919, 7273, 7275, 7277, 7279, 7281, 7283, 7283, 7285, + 7287, 7289, 7291, 7293, 7295, 7297, 7299, 7179, 7301, 7303, 7305, 7307, + 7309, 7311, 0, 0, 7313, 7315, 7317, 7319, 7321, 7323, 7325, 7327, 7207, + 7329, 7331, 7333, 7151, 7335, 7337, 7339, 7341, 7343, 7345, 7347, 7349, + 7351, 7353, 7355, 7357, 7225, 7359, 7227, 7361, 7363, 7365, 7367, 7369, + 7153, 6703, 7371, 7373, 7375, 6843, 7017, 7377, 7379, 7241, 7381, 7243, + 7383, 7385, 7387, 7157, 7389, 7391, 7393, 7395, 7397, 7159, 7399, 7401, + 7403, 7405, 7407, 7409, 7271, 7411, 7413, 6919, 7415, 7279, 7417, 7419, + 7421, 7423, 7425, 7289, 7427, 7177, 7429, 7291, 6805, 7431, 7293, 7433, + 7297, 7435, 7437, 7439, 7441, 7443, 7301, 7169, 7445, 7303, 7447, 7305, + 7449, 6637, 7451, 7453, 7455, 7457, 7459, 7461, 7463, 7465, 7467, 7469, + 7471, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7473, 7476, 7479, 7482, + 7486, 7490, 7493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7496, 7499, 7502, + 7505, 7508, 0, 0, 0, 0, 0, 7511, 0, 7514, 7517, 7519, 7521, 7523, 7525, + 7527, 7529, 7531, 7533, 7535, 7537, 7540, 7543, 7546, 7549, 7552, 7555, + 7558, 7561, 7564, 7567, 7570, 7573, 0, 7576, 7579, 7582, 7585, 7588, 0, + 7591, 0, 7594, 7597, 0, 7600, 7603, 0, 7606, 7609, 7612, 7615, 7618, + 7621, 7624, 7627, 7630, 7633, 7636, 7638, 7640, 7642, 7644, 7646, 7648, + 7650, 7652, 7654, 7656, 7658, 7660, 7662, 7664, 7666, 7668, 7670, 7672, + 7674, 7676, 7678, 7680, 7682, 7684, 7686, 7688, 7690, 7692, 7694, 7696, + 7698, 7700, 7702, 7704, 7706, 7708, 7710, 7712, 7714, 7716, 7718, 7720, + 7722, 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, 7740, 7742, 7744, + 7746, 7748, 7750, 7752, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, + 7770, 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, + 7794, 7796, 7798, 7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, + 7818, 7820, 7822, 7824, 7826, 7828, 7830, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7832, 7834, 7836, 7838, 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, + 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, 7876, 7878, + 7881, 7884, 7887, 7890, 7893, 7896, 7899, 7902, 7905, 7908, 7911, 7914, + 7917, 7920, 7923, 7926, 7929, 7932, 7934, 7936, 7938, 7940, 7943, 7946, + 7923, 7949, 7952, 7955, 7958, 7961, 7964, 7967, 7970, 7973, 7976, 7979, + 7982, 7985, 7988, 7991, 7994, 7997, 8000, 8003, 8006, 8009, 8012, 8015, + 8018, 8021, 8024, 8027, 8030, 8033, 8036, 8039, 8042, 8045, 8048, 8051, + 8054, 8057, 8060, 8063, 8066, 8069, 8072, 8075, 8078, 8081, 8084, 8087, + 8090, 8093, 8096, 8099, 8102, 8105, 8108, 8111, 8114, 8117, 8120, 8123, + 8126, 8129, 8132, 8135, 8138, 8141, 8144, 8147, 8150, 8153, 8156, 8159, + 8162, 8165, 8168, 8171, 8174, 8177, 8180, 8183, 8186, 8189, 8192, 8195, + 8198, 8201, 8204, 8207, 8210, 8213, 8216, 8219, 8223, 8227, 8231, 8235, + 8239, 8243, 8246, 8249, 8252, 7926, 8255, 8258, 8261, 8264, 8267, 8270, + 8273, 8276, 8279, 8282, 8285, 8288, 8291, 8294, 8297, 8300, 8303, 8306, + 8309, 8312, 8315, 8318, 8321, 8324, 8327, 8330, 8333, 8336, 8339, 8342, + 8345, 8348, 8351, 8354, 8357, 8360, 8363, 8366, 8369, 8372, 8375, 8378, + 8381, 8384, 8387, 8390, 8393, 8396, 8399, 8402, 8405, 8408, 8411, 8414, + 8417, 8420, 8423, 8426, 8429, 8432, 8435, 8438, 8441, 8444, 8447, 8450, + 8453, 8456, 8459, 8462, 8465, 8468, 8471, 8474, 8477, 8480, 8483, 8486, + 8489, 8492, 8495, 8498, 8501, 8504, 8507, 8510, 8513, 8516, 8519, 8522, + 8525, 8528, 8531, 8534, 8537, 8540, 8543, 8546, 8549, 8552, 8555, 8558, + 8561, 8564, 8567, 8570, 8573, 8576, 8579, 8582, 8585, 8588, 8591, 8594, + 8597, 8600, 8603, 8606, 8609, 8612, 8615, 8618, 8621, 8624, 8627, 8630, + 8633, 8636, 8639, 8642, 8645, 8648, 8651, 8654, 8657, 8660, 8663, 8666, + 8670, 8674, 8678, 8681, 8684, 8687, 8690, 8693, 8696, 8699, 8702, 8705, + 8708, 8711, 8714, 8717, 8720, 8723, 8726, 8729, 8732, 8735, 8738, 8741, + 8744, 8747, 8750, 8753, 8756, 8759, 8762, 8765, 8768, 8771, 8774, 8777, + 8780, 8783, 8786, 8789, 8792, 8795, 8798, 8801, 8804, 8807, 8810, 8813, + 8816, 8819, 8822, 8825, 8828, 8831, 8834, 8837, 8840, 8843, 8846, 8849, + 8852, 8855, 8858, 8861, 8864, 8867, 8870, 8873, 8876, 8879, 8882, 8885, + 8888, 8891, 8894, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8897, 8901, 8905, 8909, 8913, 8917, 8921, 8925, 8929, 8933, 8937, 8941, + 8945, 8949, 8953, 8957, 8961, 8965, 8969, 8973, 8977, 8981, 8985, 8989, + 8993, 8997, 9001, 9005, 9009, 9013, 9017, 9021, 9025, 9029, 9033, 9037, + 9041, 9045, 9049, 9053, 9057, 9061, 9065, 9069, 9073, 9077, 9081, 9085, + 9089, 9093, 9097, 9101, 9105, 9109, 9113, 9117, 9121, 9125, 9129, 9133, + 9137, 9141, 9145, 9149, 0, 0, 9153, 9157, 9161, 9165, 9169, 9173, 9177, + 9181, 9185, 9189, 9193, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, + 9229, 9233, 9237, 9241, 9245, 9249, 9253, 9257, 9261, 9265, 9269, 9273, + 9277, 9281, 9285, 9289, 9293, 9297, 9301, 9305, 9309, 9313, 9317, 9321, + 9325, 9329, 9333, 9337, 9341, 9345, 9349, 9353, 9357, 9361, 9365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9369, 9373, 9377, 9382, 9387, + 9392, 9397, 9402, 9407, 9412, 9416, 9435, 9444, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9449, 9451, 9453, 9455, 9457, 9459, + 9461, 9463, 9465, 9467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9469, 9471, 9473, 9475, 9475, 9477, 9479, 9481, 9483, + 9485, 9487, 9489, 9491, 9493, 9495, 9497, 9499, 9501, 9503, 9505, 9507, + 0, 0, 9509, 9511, 9513, 9513, 9513, 9513, 9515, 9515, 9515, 9517, 9519, + 9521, 0, 9523, 9525, 9527, 9529, 9531, 9533, 9535, 9537, 9539, 9541, + 9543, 9545, 9547, 9549, 9551, 9553, 9555, 9557, 9559, 0, 9561, 9563, + 9565, 9567, 0, 0, 0, 0, 9569, 9572, 9575, 0, 9578, 0, 9581, 9584, 9587, + 9590, 9593, 9596, 9599, 9602, 9605, 9608, 9611, 9613, 9615, 9617, 9619, + 9621, 9623, 9625, 9627, 9629, 9631, 9633, 9635, 9637, 9639, 9641, 9643, + 9645, 9647, 9649, 9651, 9653, 9655, 9657, 9659, 9661, 9663, 9665, 9667, + 9669, 9671, 9673, 9675, 9677, 9679, 9681, 9683, 9685, 9687, 9689, 9691, + 9693, 9695, 9697, 9699, 9701, 9703, 9705, 9707, 9709, 9711, 9713, 9715, + 9717, 9719, 9721, 9723, 9725, 9727, 9729, 9731, 9733, 9735, 9737, 9739, + 9741, 9743, 9745, 9747, 9749, 9751, 9753, 9755, 9757, 9759, 9761, 9763, + 9765, 9767, 9769, 9771, 9773, 9775, 9777, 9779, 9781, 9783, 9785, 9787, + 9789, 9791, 9793, 9795, 9797, 9799, 9801, 9803, 9805, 9807, 9809, 9811, + 9813, 9815, 9817, 9819, 9821, 9823, 9825, 9827, 9829, 9831, 9833, 9835, + 9837, 9839, 9841, 9843, 9845, 9848, 9851, 9854, 9857, 9860, 9863, 9866, + 0, 0, 0, 0, 9869, 9871, 9873, 9875, 9877, 9879, 9881, 9883, 9885, 9887, + 9889, 9891, 9893, 9895, 9897, 9899, 9901, 9903, 9905, 9907, 9909, 9911, + 9913, 9915, 9917, 9919, 9921, 9923, 9925, 9927, 9929, 9931, 9933, 9935, + 9937, 9939, 9941, 9943, 9945, 9947, 9949, 9951, 9953, 9955, 9957, 9959, + 9961, 9963, 9965, 9967, 9969, 9971, 9973, 9975, 9977, 9979, 9981, 9983, + 9985, 9987, 9989, 9991, 9993, 9995, 9997, 9999, 10001, 10003, 10005, + 10007, 10009, 10011, 10013, 10015, 10017, 10019, 10021, 10023, 10025, + 10027, 10029, 10031, 10033, 10035, 10037, 10039, 10041, 10043, 10045, + 10047, 10049, 10051, 10053, 10055, 10057, 10059, 10061, 10063, 10065, + 10067, 10069, 10071, 10073, 10075, 10077, 10079, 10081, 10083, 10085, + 10087, 10089, 10091, 10093, 10095, 10097, 10099, 10101, 10103, 10105, + 10107, 10109, 10111, 10113, 10115, 10117, 10119, 10121, 10123, 10125, + 10127, 10129, 10131, 10133, 10135, 10137, 10139, 10141, 10143, 10145, + 10147, 10149, 10151, 10153, 10155, 10157, 10159, 10161, 10163, 10165, + 10167, 10169, 10171, 10173, 10175, 10177, 10179, 10181, 10183, 10185, + 10187, 10189, 10191, 10193, 10195, 10197, 10199, 10201, 10203, 10205, + 10207, 10209, 10211, 10213, 10215, 10217, 10219, 10221, 10223, 10225, + 10227, 10229, 10231, 10233, 10235, 10237, 10239, 10241, 10243, 10245, + 10247, 0, 0, 0, 10249, 10251, 10253, 10255, 10257, 10259, 0, 0, 10261, + 10263, 10265, 10267, 10269, 10271, 0, 0, 10273, 10275, 10277, 10279, + 10281, 10283, 0, 0, 10285, 10287, 10289, 0, 0, 0, 10291, 10293, 10295, + 10297, 10299, 10301, 10303, 0, 10305, 10307, 10309, 10311, 10313, 10315, + 10317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10319, + 10321, 10323, 10325, 10327, 0, 10329, 10331, 10333, 10335, 10337, 10339, + 10341, 10343, 10345, 10347, 10349, 10351, 10353, 10355, 10357, 10359, + 10361, 10363, 10365, 10367, 10369, 10371, 10373, 10375, 10377, 10379, + 10381, 10383, 10385, 10387, 10389, 10391, 10393, 10395, 10397, 10399, + 10401, 10403, 10405, 10407, 10409, 10411, 0, 10413, 10415, 10417, 10419, + 10421, 10423, 10425, 10427, 10429, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10431, 0, 10434, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10440, 10443, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10446, 10449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10452, 10455, 0, 10458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10461, 10464, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10467, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10470, 10473, + 10476, 10479, 10482, 10485, 10488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10491, 10494, 10497, 10500, 10503, 10506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10509, 3253, 3192, 3289, 3257, 3259, 10511, 3212, 3218, + 10513, 10515, 3220, 3261, 3224, 10517, 3229, 3231, 3233, 10519, 10521, + 10523, 10525, 10527, 10529, 10531, 3245, 10533, 10535, 10537, 3291, 3255, + 10539, 3210, 3214, 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, + 10549, 10551, 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, + 10509, 3253, 3192, 3289, 3257, 3259, 10511, 3212, 3218, 10513, 10515, + 3220, 3261, 3224, 10517, 3229, 3231, 3233, 10519, 10521, 10523, 10525, + 10527, 10529, 10531, 3245, 10533, 10535, 10537, 3291, 3255, 10539, 3210, + 0, 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, 10549, 10551, + 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, 10509, 3253, + 3192, 3289, 3257, 3259, 10511, 3212, 3218, 10513, 10515, 3220, 3261, + 3224, 10517, 3229, 3231, 3233, 10519, 10521, 10523, 10525, 10527, 10529, + 10531, 3245, 10533, 10535, 10537, 3291, 3255, 10539, 3210, 3214, 3273, + 3293, 10541, 3222, 10543, 10545, 3263, 10547, 10549, 10551, 10553, 10555, + 10557, 10559, 10561, 10563, 10565, 10567, 10509, 0, 3192, 3289, 0, 0, + 10511, 0, 0, 10513, 10515, 0, 0, 3224, 10517, 3229, 3231, 0, 10519, + 10521, 10523, 10525, 10527, 10529, 10531, 3245, 10533, 10535, 10537, + 3291, 0, 10539, 0, 3214, 3273, 3293, 10541, 3222, 10543, 10545, 0, 10547, + 10549, 10551, 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, + 10509, 3253, 3192, 3289, 3257, 3259, 10511, 3212, 3218, 10513, 10515, + 3220, 3261, 3224, 10517, 3229, 3231, 3233, 10519, 10521, 10523, 10525, + 10527, 10529, 10531, 3245, 10533, 10535, 10537, 3291, 3255, 10539, 3210, + 3214, 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, 10549, 10551, + 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, 10509, 3253, 0, + 3289, 3257, 3259, 10511, 0, 0, 10513, 10515, 3220, 3261, 3224, 10517, + 3229, 3231, 0, 10519, 10521, 10523, 10525, 10527, 10529, 10531, 0, 10533, + 10535, 10537, 3291, 3255, 10539, 3210, 3214, 3273, 3293, 10541, 3222, + 10543, 10545, 3263, 10547, 10549, 10551, 10553, 10555, 10557, 10559, + 10561, 10563, 10565, 10567, 10509, 3253, 0, 3289, 3257, 3259, 10511, 0, + 3218, 10513, 10515, 3220, 3261, 0, 10517, 0, 0, 0, 10519, 10521, 10523, + 10525, 10527, 10529, 10531, 0, 10533, 10535, 10537, 3291, 3255, 10539, + 3210, 3214, 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, 10549, + 10551, 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, 10509, + 3253, 3192, 3289, 3257, 3259, 10511, 3212, 3218, 10513, 10515, 3220, + 3261, 3224, 10517, 3229, 3231, 3233, 10519, 10521, 10523, 10525, 10527, + 10529, 10531, 3245, 10533, 10535, 10537, 3291, 3255, 10539, 3210, 3214, + 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, 10549, 10551, 10553, + 10555, 10557, 10559, 10561, 10563, 10565, 10567, 10509, 3253, 3192, 3289, + 3257, 3259, 10511, 3212, 3218, 10513, 10515, 3220, 3261, 3224, 10517, + 3229, 3231, 3233, 10519, 10521, 10523, 10525, 10527, 10529, 10531, 3245, + 10533, 10535, 10537, 3291, 3255, 10539, 3210, 3214, 3273, 3293, 10541, + 3222, 10543, 10545, 3263, 10547, 10549, 10551, 10553, 10555, 10557, + 10559, 10561, 10563, 10565, 10567, 10509, 3253, 3192, 3289, 3257, 3259, + 10511, 3212, 3218, 10513, 10515, 3220, 3261, 3224, 10517, 3229, 3231, + 3233, 10519, 10521, 10523, 10525, 10527, 10529, 10531, 3245, 10533, + 10535, 10537, 3291, 3255, 10539, 3210, 3214, 3273, 3293, 10541, 3222, + 10543, 10545, 3263, 10547, 10549, 10551, 10553, 10555, 10557, 10559, + 10561, 10563, 10565, 10567, 10509, 3253, 3192, 3289, 3257, 3259, 10511, + 3212, 3218, 10513, 10515, 3220, 3261, 3224, 10517, 3229, 3231, 3233, + 10519, 10521, 10523, 10525, 10527, 10529, 10531, 3245, 10533, 10535, + 10537, 3291, 3255, 10539, 3210, 3214, 3273, 3293, 10541, 3222, 10543, + 10545, 3263, 10547, 10549, 10551, 10553, 10555, 10557, 10559, 10561, + 10563, 10565, 10567, 10509, 3253, 3192, 3289, 3257, 3259, 10511, 3212, + 3218, 10513, 10515, 3220, 3261, 3224, 10517, 3229, 3231, 3233, 10519, + 10521, 10523, 10525, 10527, 10529, 10531, 3245, 10533, 10535, 10537, + 3291, 3255, 10539, 3210, 3214, 3273, 3293, 10541, 3222, 10543, 10545, + 3263, 10547, 10549, 10551, 10553, 10555, 10557, 10559, 10561, 10563, + 10565, 10567, 10509, 3253, 3192, 3289, 3257, 3259, 10511, 3212, 3218, + 10513, 10515, 3220, 3261, 3224, 10517, 3229, 3231, 3233, 10519, 10521, + 10523, 10525, 10527, 10529, 10531, 3245, 10533, 10535, 10537, 3291, 3255, + 10539, 3210, 3214, 3273, 3293, 10541, 3222, 10543, 10545, 3263, 10547, + 10549, 10551, 10553, 10555, 10557, 10559, 10561, 10563, 10565, 10567, + 10569, 10571, 0, 0, 10573, 10575, 3283, 10577, 10579, 10581, 10583, + 10585, 10587, 10589, 10591, 10593, 10595, 10597, 10599, 3285, 10601, + 10603, 10605, 10607, 10609, 10611, 10613, 10615, 10617, 10619, 10621, + 10623, 3281, 10625, 10627, 10629, 10631, 10633, 10635, 10637, 10639, + 10641, 10643, 10645, 10647, 3279, 10649, 10651, 10653, 10655, 10657, + 10659, 10661, 10663, 10665, 10667, 10669, 10671, 10673, 10675, 10677, + 10679, 10573, 10575, 3283, 10577, 10579, 10581, 10583, 10585, 10587, + 10589, 10591, 10593, 10595, 10597, 10599, 3285, 10601, 10603, 10605, + 10607, 10609, 10611, 10613, 10615, 10617, 10619, 10621, 10623, 3281, + 10625, 10627, 10629, 10631, 10633, 10635, 10637, 10639, 10641, 10643, + 10645, 10647, 3279, 10649, 10651, 10653, 10655, 10657, 10659, 10661, + 10663, 10665, 10667, 10669, 10671, 10673, 10675, 10677, 10679, 10573, + 10575, 3283, 10577, 10579, 10581, 10583, 10585, 10587, 10589, 10591, + 10593, 10595, 10597, 10599, 3285, 10601, 10603, 10605, 10607, 10609, + 10611, 10613, 10615, 10617, 10619, 10621, 10623, 3281, 10625, 10627, + 10629, 10631, 10633, 10635, 10637, 10639, 10641, 10643, 10645, 10647, + 3279, 10649, 10651, 10653, 10655, 10657, 10659, 10661, 10663, 10665, + 10667, 10669, 10671, 10673, 10675, 10677, 10679, 10573, 10575, 3283, + 10577, 10579, 10581, 10583, 10585, 10587, 10589, 10591, 10593, 10595, + 10597, 10599, 3285, 10601, 10603, 10605, 10607, 10609, 10611, 10613, + 10615, 10617, 10619, 10621, 10623, 3281, 10625, 10627, 10629, 10631, + 10633, 10635, 10637, 10639, 10641, 10643, 10645, 10647, 3279, 10649, + 10651, 10653, 10655, 10657, 10659, 10661, 10663, 10665, 10667, 10669, + 10671, 10673, 10675, 10677, 10679, 10573, 10575, 3283, 10577, 10579, + 10581, 10583, 10585, 10587, 10589, 10591, 10593, 10595, 10597, 10599, + 3285, 10601, 10603, 10605, 10607, 10609, 10611, 10613, 10615, 10617, + 10619, 10621, 10623, 3281, 10625, 10627, 10629, 10631, 10633, 10635, + 10637, 10639, 10641, 10643, 10645, 10647, 3279, 10649, 10651, 10653, + 10655, 10657, 10659, 10661, 10663, 10665, 10667, 10669, 10671, 10673, + 10675, 10677, 10679, 10681, 10683, 0, 0, 10685, 10687, 10689, 10691, + 10693, 10695, 10697, 10699, 10701, 10703, 10685, 10687, 10689, 10691, + 10693, 10695, 10697, 10699, 10701, 10703, 10685, 10687, 10689, 10691, + 10693, 10695, 10697, 10699, 10701, 10703, 10685, 10687, 10689, 10691, + 10693, 10695, 10697, 10699, 10701, 10703, 10685, 10687, 10689, 10691, + 10693, 10695, 10697, 10699, 10701, 10703, 10705, 10707, 10709, 10711, 0, + 10713, 10715, 10717, 10719, 10721, 10723, 10725, 10727, 10729, 10731, + 10733, 10735, 10737, 10739, 10741, 10743, 10745, 10747, 10749, 10751, + 10753, 10755, 10757, 10759, 10761, 10763, 10765, 0, 10707, 10709, 0, + 10767, 0, 0, 10717, 0, 10721, 10723, 10725, 10727, 10729, 10731, 10733, + 10735, 10737, 10739, 0, 10743, 10745, 10747, 10749, 0, 10753, 0, 10757, + 0, 0, 0, 0, 0, 0, 10709, 0, 0, 0, 0, 10717, 0, 10721, 0, 10725, 0, 10729, + 10731, 10733, 0, 10737, 10739, 0, 10743, 0, 0, 10749, 0, 10753, 0, 10757, + 0, 10761, 0, 10765, 0, 10707, 10709, 0, 10767, 0, 0, 10717, 10719, 10721, + 10723, 0, 10727, 10729, 10731, 10733, 10735, 10737, 10739, 0, 10743, + 10745, 10747, 10749, 0, 10753, 10755, 10757, 10759, 0, 10763, 0, 10705, + 10707, 10709, 10711, 10767, 10713, 10715, 10717, 10719, 10721, 0, 10725, + 10727, 10729, 10731, 10733, 10735, 10737, 10739, 10741, 10743, 10745, + 10747, 10749, 10751, 10753, 10755, 10757, 0, 0, 0, 0, 0, 10707, 10709, + 10711, 0, 10713, 10715, 10717, 10719, 10721, 0, 10725, 10727, 10729, + 10731, 10733, 10735, 10737, 10739, 10741, 10743, 10745, 10747, 10749, + 10751, 10753, 10755, 10757, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10769, 10772, 10775, 10778, 10781, 10784, 10787, 10790, + 10793, 10796, 10799, 0, 0, 0, 0, 0, 10802, 10806, 10810, 10814, 10818, + 10822, 10826, 10830, 10834, 10838, 10842, 10846, 10850, 10854, 10858, + 10862, 10866, 10870, 10874, 10878, 10882, 10886, 10890, 10894, 10898, + 10902, 10906, 3926, 3956, 10910, 10913, 0, 10916, 10918, 10920, 10922, + 10924, 10926, 10928, 10930, 10932, 10934, 10936, 10938, 10940, 10942, + 10944, 10946, 10948, 10950, 10952, 10954, 10956, 10958, 10960, 10962, + 10964, 10966, 10968, 6348, 10971, 10974, 10977, 10981, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10984, 10987, + 10990, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10993, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10996, 10999, 11002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11004, 11006, 11008, 11010, 11012, 11014, 11016, 11018, 11020, + 11022, 11024, 11026, 11028, 11030, 11032, 11034, 11036, 11038, 11040, + 11042, 11044, 11046, 11048, 11050, 11052, 11054, 11056, 11058, 11060, + 11062, 11064, 11066, 11068, 11070, 11072, 11074, 11076, 11078, 11080, + 11082, 11084, 11086, 11088, 11090, 0, 0, 0, 0, 11092, 11096, 11100, + 11104, 11108, 11112, 11116, 11120, 11124, 0, 0, 0, 0, 0, 0, 0, 11128, + 11130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10685, 10687, 10689, + 10691, 10693, 10695, 10697, 10699, 10701, 10703, 0, 0, 0, 0, 0, 0, 11132, + 11134, 11136, 11138, 11140, 7195, 11142, 11144, 11146, 11148, 7197, + 11150, 11152, 11154, 7199, 11156, 11158, 11160, 11162, 11164, 11166, + 11168, 11170, 11172, 11174, 11176, 11178, 7315, 11180, 11182, 11184, + 11186, 11188, 11190, 11192, 11194, 11196, 7325, 7201, 7203, 7327, 11198, + 11200, 6817, 11202, 7205, 11204, 11206, 11208, 11210, 11210, 11210, + 11212, 11214, 11216, 11218, 11220, 11222, 11224, 11226, 11228, 11230, + 11232, 11234, 11236, 11238, 11240, 11242, 11244, 11246, 11246, 7331, + 11248, 11250, 11252, 11254, 7209, 11256, 11258, 11260, 7123, 11262, + 11264, 11266, 11268, 11270, 11272, 11274, 11276, 11278, 11280, 11282, + 11284, 11286, 11288, 11290, 11292, 11294, 11296, 11298, 11300, 11302, + 11304, 11306, 11308, 11310, 11312, 11312, 11314, 11316, 11318, 6809, + 11320, 11322, 11324, 11326, 11328, 11330, 11332, 11334, 7219, 11336, + 11338, 11340, 11342, 11344, 11346, 11348, 11350, 11352, 11354, 11356, + 11358, 11360, 11362, 11364, 11366, 11368, 11370, 11372, 11374, 11376, + 6701, 11378, 11380, 11382, 11382, 11384, 11386, 11386, 11388, 11390, + 11392, 11394, 11396, 11398, 11400, 11402, 11404, 11406, 11408, 11410, + 11412, 7221, 11414, 11416, 11418, 11420, 7355, 11420, 11422, 7225, 11424, + 11426, 11428, 11430, 7227, 6647, 11432, 11434, 11436, 11438, 11440, + 11442, 11444, 11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, + 11462, 11464, 11466, 11468, 11470, 11472, 11474, 7229, 11476, 11478, + 11480, 11482, 11484, 11486, 7233, 11488, 11490, 11492, 11494, 11496, + 11498, 11500, 11502, 6703, 7371, 11504, 11506, 11508, 11510, 11512, + 11514, 11516, 11518, 7235, 11520, 11522, 11524, 11526, 7457, 11528, + 11530, 11532, 11534, 11536, 11538, 11540, 11542, 11544, 11546, 11548, + 11550, 11552, 6843, 11554, 11556, 11558, 11560, 11562, 11564, 11566, + 11568, 11570, 11572, 11574, 7237, 7017, 11576, 11578, 11580, 11582, + 11584, 11586, 11588, 11590, 7379, 11592, 11594, 11596, 11598, 11600, + 11602, 11604, 11606, 7381, 11608, 11610, 11612, 11614, 11616, 11618, + 11620, 11622, 11624, 11626, 11628, 11630, 7385, 11632, 11634, 11636, + 11638, 11640, 11642, 11644, 11646, 11648, 11650, 11652, 11652, 11654, + 11656, 7389, 11658, 11660, 11662, 11664, 11666, 11668, 11670, 6815, + 11672, 11674, 11676, 11678, 11680, 11682, 11684, 7401, 11686, 11688, + 11690, 11692, 11694, 11696, 11696, 7403, 7461, 11698, 11700, 11702, + 11704, 11706, 6739, 7407, 11708, 11710, 7259, 11712, 11714, 7167, 11716, + 11718, 7267, 11720, 11722, 11724, 11726, 11726, 11728, 11730, 11732, + 11734, 11736, 11738, 11740, 11742, 11744, 11746, 11748, 11750, 11752, + 11754, 11756, 11758, 11760, 11762, 11764, 11766, 11768, 11770, 11772, + 11774, 11776, 11778, 11780, 7279, 11782, 11784, 11786, 11788, 11790, + 11792, 11794, 11796, 11798, 11800, 11802, 11804, 11806, 11808, 11810, + 11812, 11384, 11814, 11816, 11818, 11820, 11822, 11824, 11826, 11828, + 11830, 11832, 11834, 11836, 6851, 11838, 11840, 11842, 11844, 11846, + 11848, 7285, 11850, 11852, 11854, 11856, 11858, 11860, 11862, 11864, + 11866, 11868, 11870, 11872, 11874, 11876, 11878, 11880, 11882, 11884, + 11886, 11888, 6729, 11890, 11892, 11894, 11896, 11898, 11900, 7421, + 11902, 11904, 11906, 11908, 11910, 11912, 11914, 11916, 11918, 11920, + 11922, 11924, 11926, 11928, 11930, 11932, 11934, 11936, 11938, 11940, + 7431, 7433, 11942, 11944, 11946, 11948, 11950, 11952, 11954, 11956, + 11958, 11960, 11962, 11964, 11966, 7435, 11968, 11970, 11972, 11974, + 11976, 11978, 11980, 11982, 11984, 11986, 11988, 11990, 11992, 11994, + 11996, 11998, 12000, 12002, 12004, 12006, 12008, 12010, 12012, 12014, + 12016, 12018, 12020, 12022, 12024, 12026, 7447, 7447, 12028, 12030, + 12032, 12034, 12036, 12038, 12040, 12042, 12044, 12046, 7449, 12048, + 12050, 12052, 12054, 12056, 12058, 12060, 12062, 12064, 12066, 12068, + 12070, 12072, 12074, 12076, 12078, 12080, 12082, 12084, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10586, 10589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10592, 10595, 0, - 10598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10601, 10604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10610, 10613, 10616, 10619, 10622, - 10625, 10628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10631, 10634, - 10637, 10640, 10643, 10646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10649, 10651, 10653, 10655, 10657, 10659, 10661, 10663, 10665, 10667, - 10669, 10671, 10673, 10675, 10677, 10679, 10681, 10683, 10685, 10687, - 10689, 10691, 10693, 10695, 10697, 10699, 10701, 10703, 10705, 10707, - 10709, 10711, 10713, 10715, 10717, 10719, 10721, 10723, 10725, 10727, - 10729, 10731, 10733, 10735, 10737, 10739, 10741, 10743, 10745, 10747, - 10749, 10751, 10753, 10755, 10757, 10759, 10761, 10763, 10765, 10767, - 10769, 10771, 10773, 10775, 10777, 10779, 10781, 10783, 10785, 10787, - 10789, 10791, 10793, 10795, 10797, 10799, 10801, 10803, 10805, 10807, - 10809, 10811, 10813, 10815, 10817, 0, 10819, 10821, 10823, 10825, 10827, - 10829, 10831, 10833, 10835, 10837, 10839, 10841, 10843, 10845, 10847, - 10849, 10851, 10853, 10855, 10857, 10859, 10861, 10863, 10865, 10867, - 10869, 10871, 10873, 10875, 10877, 10879, 10881, 10883, 10885, 10887, - 10889, 10891, 10893, 10895, 10897, 10899, 10901, 10903, 10905, 10907, - 10909, 10911, 10913, 10915, 10917, 10919, 10921, 10923, 10925, 10927, - 10929, 10931, 10933, 10935, 10937, 10939, 10941, 10943, 10945, 10947, - 10949, 10951, 10953, 10955, 10957, 10959, 0, 10961, 10963, 0, 0, 10965, - 0, 0, 10967, 10969, 0, 0, 10971, 10973, 10975, 10977, 0, 10979, 10981, - 10983, 10985, 10987, 10989, 10991, 10993, 10995, 10997, 10999, 11001, 0, - 11003, 0, 11005, 11007, 11009, 11011, 11013, 11015, 11017, 0, 11019, - 11021, 11023, 11025, 11027, 11029, 11031, 11033, 11035, 11037, 11039, - 11041, 11043, 11045, 11047, 11049, 11051, 11053, 11055, 11057, 11059, - 11061, 11063, 11065, 11067, 11069, 11071, 11073, 11075, 11077, 11079, - 11081, 11083, 11085, 11087, 11089, 11091, 11093, 11095, 11097, 11099, - 11101, 11103, 11105, 11107, 11109, 11111, 11113, 11115, 11117, 11119, - 11121, 11123, 11125, 11127, 11129, 11131, 11133, 11135, 11137, 11139, - 11141, 11143, 11145, 11147, 0, 11149, 11151, 11153, 11155, 0, 0, 11157, - 11159, 11161, 11163, 11165, 11167, 11169, 11171, 0, 11173, 11175, 11177, - 11179, 11181, 11183, 11185, 0, 11187, 11189, 11191, 11193, 11195, 11197, - 11199, 11201, 11203, 11205, 11207, 11209, 11211, 11213, 11215, 11217, - 11219, 11221, 11223, 11225, 11227, 11229, 11231, 11233, 11235, 11237, - 11239, 11241, 0, 11243, 11245, 11247, 11249, 0, 11251, 11253, 11255, - 11257, 11259, 0, 11261, 0, 0, 0, 11263, 11265, 11267, 11269, 11271, - 11273, 11275, 0, 11277, 11279, 11281, 11283, 11285, 11287, 11289, 11291, - 11293, 11295, 11297, 11299, 11301, 11303, 11305, 11307, 11309, 11311, - 11313, 11315, 11317, 11319, 11321, 11323, 11325, 11327, 11329, 11331, - 11333, 11335, 11337, 11339, 11341, 11343, 11345, 11347, 11349, 11351, - 11353, 11355, 11357, 11359, 11361, 11363, 11365, 11367, 11369, 11371, - 11373, 11375, 11377, 11379, 11381, 11383, 11385, 11387, 11389, 11391, - 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409, 11411, - 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, - 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, - 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, - 11473, 11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, - 11493, 11495, 11497, 11499, 11501, 11503, 11505, 11507, 11509, 11511, - 11513, 11515, 11517, 11519, 11521, 11523, 11525, 11527, 11529, 11531, - 11533, 11535, 11537, 11539, 11541, 11543, 11545, 11547, 11549, 11551, - 11553, 11555, 11557, 11559, 11561, 11563, 11565, 11567, 11569, 11571, - 11573, 11575, 11577, 11579, 11581, 11583, 11585, 11587, 11589, 11591, - 11593, 11595, 11597, 11599, 11601, 11603, 11605, 11607, 11609, 11611, - 11613, 11615, 11617, 11619, 11621, 11623, 11625, 11627, 11629, 11631, - 11633, 11635, 11637, 11639, 11641, 11643, 11645, 11647, 11649, 11651, - 11653, 11655, 11657, 11659, 11661, 11663, 11665, 11667, 11669, 11671, - 11673, 11675, 11677, 11679, 11681, 11683, 11685, 11687, 11689, 11691, - 11693, 11695, 11697, 11699, 11701, 11703, 11705, 11707, 11709, 11711, - 11713, 11715, 11717, 11719, 11721, 11723, 11725, 11727, 11729, 11731, - 11733, 11735, 11737, 11739, 11741, 11743, 11745, 11747, 11749, 11751, - 11753, 11755, 11757, 11759, 11761, 11763, 11765, 11767, 11769, 11771, - 11773, 11775, 11777, 11779, 11781, 11783, 11785, 11787, 11789, 11791, - 11793, 11795, 11797, 11799, 11801, 11803, 11805, 11807, 11809, 11811, - 11813, 11815, 11817, 11819, 11821, 11823, 11825, 11827, 11829, 11831, - 11833, 11835, 11837, 11839, 11841, 11843, 11845, 11847, 11849, 11851, - 11853, 11855, 11857, 11859, 11861, 11863, 11865, 11867, 11869, 11871, - 11873, 11875, 11877, 11879, 11881, 11883, 11885, 11887, 11889, 11891, - 11893, 11895, 11897, 11899, 11901, 11903, 11905, 11907, 11909, 11911, - 11913, 11915, 11917, 11919, 11921, 11923, 11925, 11927, 11929, 11931, - 11933, 11935, 11937, 11939, 11941, 11943, 11945, 11947, 11949, 11951, - 11953, 11955, 0, 0, 11957, 11959, 11961, 11963, 11965, 11967, 11969, - 11971, 11973, 11975, 11977, 11979, 11981, 11983, 11985, 11987, 11989, - 11991, 11993, 11995, 11997, 11999, 12001, 12003, 12005, 12007, 12009, - 12011, 12013, 12015, 12017, 12019, 12021, 12023, 12025, 12027, 12029, - 12031, 12033, 12035, 12037, 12039, 12041, 12043, 12045, 12047, 12049, - 12051, 12053, 12055, 12057, 12059, 12061, 12063, 12065, 12067, 12069, - 12071, 12073, 12075, 12077, 12079, 12081, 12083, 12085, 12087, 12089, - 12091, 12093, 12095, 12097, 12099, 12101, 12103, 12105, 12107, 12109, - 12111, 12113, 12115, 12117, 12119, 12121, 12123, 12125, 12127, 12129, - 12131, 12133, 12135, 12137, 12139, 12141, 12143, 12145, 12147, 12149, - 12151, 12153, 12155, 12157, 12159, 12161, 12163, 12165, 12167, 12169, - 12171, 12173, 12175, 12177, 12179, 12181, 12183, 12185, 12187, 12189, - 12191, 12193, 12195, 12197, 12199, 12201, 12203, 12205, 12207, 12209, - 12211, 12213, 12215, 12217, 12219, 12221, 12223, 12225, 12227, 12229, - 12231, 12233, 12235, 12237, 12239, 12241, 12243, 12245, 12247, 12249, - 12251, 12253, 12255, 12257, 12259, 12261, 12263, 12265, 12267, 12269, - 12271, 12273, 12275, 12277, 12279, 12281, 12283, 12285, 12287, 12289, - 12291, 12293, 12295, 12297, 12299, 12301, 12303, 12305, 12307, 12309, - 12311, 12313, 12315, 12317, 12319, 12321, 12323, 12325, 12327, 12329, - 12331, 12333, 12335, 12337, 12339, 12341, 12343, 12345, 12347, 12349, - 12351, 12353, 12355, 12357, 12359, 12361, 12363, 12365, 12367, 12369, - 12371, 12373, 12375, 12377, 12379, 12381, 12383, 12385, 12387, 12389, - 12391, 12393, 12395, 12397, 12399, 12401, 12403, 12405, 12407, 12409, - 12411, 12413, 12415, 12417, 12419, 12421, 12423, 12425, 12427, 12429, - 12431, 12433, 12435, 12437, 12439, 12441, 12443, 12445, 12447, 12449, - 12451, 12453, 12455, 12457, 12459, 12461, 12463, 12465, 12467, 12469, - 12471, 12473, 12475, 12477, 12479, 12481, 12483, 12485, 12487, 12489, - 12491, 12493, 12495, 12497, 12499, 12501, 12503, 12505, 12507, 12509, - 12511, 12513, 12515, 12517, 12519, 12521, 12523, 12525, 12527, 12529, - 12531, 12533, 12535, 12537, 12539, 0, 0, 12541, 12543, 12545, 12547, - 12549, 12551, 12553, 12555, 12557, 12559, 12561, 12563, 12565, 12567, - 12569, 12571, 12573, 12575, 12577, 12579, 12581, 12583, 12585, 12587, - 12589, 12591, 12593, 12595, 12597, 12599, 12601, 12603, 12605, 12607, - 12609, 12611, 12613, 12615, 12617, 12619, 12621, 12623, 12625, 12627, - 12629, 12631, 12633, 12635, 12637, 12639, 12641, 12643, 12645, 12647, 0, - 12649, 12651, 12653, 12655, 12657, 12659, 12661, 12663, 12665, 12667, - 12669, 12671, 12673, 12675, 12677, 12679, 12681, 12683, 12685, 12687, - 12689, 12691, 12693, 12695, 12697, 12699, 12701, 0, 12703, 12705, 0, - 12707, 0, 0, 12709, 0, 12711, 12713, 12715, 12717, 12719, 12721, 12723, - 12725, 12727, 12729, 0, 12731, 12733, 12735, 12737, 0, 12739, 0, 12741, - 0, 0, 0, 0, 0, 0, 12743, 0, 0, 0, 0, 12745, 0, 12747, 0, 12749, 0, 12751, - 12753, 12755, 0, 12757, 12759, 0, 12761, 0, 0, 12763, 0, 12765, 0, 12767, - 0, 12769, 0, 12771, 0, 12773, 12775, 0, 12777, 0, 0, 12779, 12781, 12783, - 12785, 0, 12787, 12789, 12791, 12793, 12795, 12797, 12799, 0, 12801, - 12803, 12805, 12807, 0, 12809, 12811, 12813, 12815, 0, 12817, 0, 12819, - 12821, 12823, 12825, 12827, 12829, 12831, 12833, 12835, 12837, 0, 12839, - 12841, 12843, 12845, 12847, 12849, 12851, 12853, 12855, 12857, 12859, - 12861, 12863, 12865, 12867, 12869, 12871, 0, 0, 0, 0, 0, 12873, 12875, - 12877, 0, 12879, 12881, 12883, 12885, 12887, 0, 12889, 12891, 12893, - 12895, 12897, 12899, 12901, 12903, 12905, 12907, 12909, 12911, 12913, - 12915, 12917, 12919, 12921, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 12923, 12926, 12929, 12932, 12935, 12938, 12941, 12944, - 12947, 12950, 12953, 0, 0, 0, 0, 0, 12956, 12960, 12964, 12968, 12972, - 12976, 12980, 12984, 12988, 12992, 12996, 13000, 13004, 13008, 13012, - 13016, 13020, 13024, 13028, 13032, 13036, 13040, 13044, 13048, 13052, - 13056, 13060, 13064, 13066, 13068, 13071, 0, 13074, 13076, 13078, 13080, - 13082, 13084, 13086, 13088, 13090, 13092, 13094, 13096, 13098, 13100, - 13102, 13104, 13106, 13108, 13110, 13112, 13114, 13116, 13118, 13120, - 13122, 13124, 13126, 13129, 13132, 13135, 13138, 13142, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13145, 13148, - 13151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13154, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 13157, 13160, 13163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 13165, 13167, 13169, 13171, 13173, 13175, 13177, 13179, 13181, - 13183, 13185, 13187, 13189, 13191, 13193, 13195, 13197, 13199, 13201, - 13203, 13205, 13207, 13209, 13211, 13213, 13215, 13217, 13219, 13221, - 13223, 13225, 13227, 13229, 13231, 13233, 13235, 13237, 13239, 13241, - 13243, 13245, 13247, 13249, 13251, 0, 0, 0, 0, 13253, 13257, 13261, - 13265, 13269, 13273, 13277, 13281, 13285, 0, 0, 0, 0, 0, 0, 0, 13289, - 13291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13293, 13295, 13297, - 13299, 13301, 13303, 13305, 13307, 13309, 13311, 0, 0, 0, 0, 0, 0, 13313, - 13315, 13317, 13319, 13321, 13323, 13325, 13327, 13329, 13331, 13333, - 13335, 13337, 13339, 13341, 13343, 13345, 13347, 13349, 13351, 13353, - 13355, 13357, 13359, 13361, 13363, 13365, 13367, 13369, 13371, 13373, - 13375, 13377, 13379, 13381, 13383, 13385, 13387, 13389, 13391, 13393, - 13395, 13397, 13399, 13401, 13403, 13405, 13407, 13409, 13411, 13413, - 13415, 13417, 13419, 13421, 13423, 13425, 13427, 13429, 13431, 13433, - 13435, 13437, 13439, 13441, 13443, 13445, 13447, 13449, 13451, 13453, - 13455, 13457, 13459, 13461, 13463, 13465, 13467, 13469, 13471, 13473, - 13475, 13477, 13479, 13481, 13483, 13485, 13487, 13489, 13491, 13493, - 13495, 13497, 13499, 13501, 13503, 13505, 13507, 13509, 13511, 13513, - 13515, 13517, 13519, 13521, 13523, 13525, 13527, 13529, 13531, 13533, - 13535, 13537, 13539, 13541, 13543, 13545, 13547, 13549, 13551, 13553, - 13555, 13557, 13559, 13561, 13563, 13565, 13567, 13569, 13571, 13573, - 13575, 13577, 13579, 13581, 13583, 13585, 13587, 13589, 13591, 13593, - 13595, 13597, 13599, 13601, 13603, 13605, 13607, 13609, 13611, 13613, - 13615, 13617, 13619, 13621, 13623, 13625, 13627, 13629, 13631, 13633, - 13635, 13637, 13639, 13641, 13643, 13645, 13647, 13649, 13651, 13653, - 13655, 13657, 13659, 13661, 13663, 13665, 13667, 13669, 13671, 13673, - 13675, 13677, 13679, 13681, 13683, 13685, 13687, 13689, 13691, 13693, - 13695, 13697, 13699, 13701, 13703, 13705, 13707, 13709, 13711, 13713, - 13715, 13717, 13719, 13721, 13723, 13725, 13727, 13729, 13731, 13733, - 13735, 13737, 13739, 13741, 13743, 13745, 13747, 13749, 13751, 13753, - 13755, 13757, 13759, 13761, 13763, 13765, 13767, 13769, 13771, 13773, - 13775, 13777, 13779, 13781, 13783, 13785, 13787, 13789, 13791, 13793, - 13795, 13797, 13799, 13801, 13803, 13805, 13807, 13809, 13811, 13813, - 13815, 13817, 13819, 13821, 13823, 13825, 13827, 13829, 13831, 13833, - 13835, 13837, 13839, 13841, 13843, 13845, 13847, 13849, 13851, 13853, - 13855, 13857, 13859, 13861, 13863, 13865, 13867, 13869, 13871, 13873, - 13875, 13877, 13879, 13881, 13883, 13885, 13887, 13889, 13891, 13893, - 13895, 13897, 13899, 13901, 13903, 13905, 13907, 13909, 13911, 13913, - 13915, 13917, 13919, 13921, 13923, 13925, 13927, 13929, 13931, 13933, - 13935, 13937, 13939, 13941, 13943, 13945, 13947, 13949, 13951, 13953, - 13955, 13957, 13959, 13961, 13963, 13965, 13967, 13969, 13971, 13973, - 13975, 13977, 13979, 13981, 13983, 13985, 13987, 13989, 13991, 13993, - 13995, 13997, 13999, 14001, 14003, 14005, 14007, 14009, 14011, 14013, - 14015, 14017, 14019, 14021, 14023, 14025, 14027, 14029, 14031, 14033, - 14035, 14037, 14039, 14041, 14043, 14045, 14047, 14049, 14051, 14053, - 14055, 14057, 14059, 14061, 14063, 14065, 14067, 14069, 14071, 14073, - 14075, 14077, 14079, 14081, 14083, 14085, 14087, 14089, 14091, 14093, - 14095, 14097, 14099, 14101, 14103, 14105, 14107, 14109, 14111, 14113, - 14115, 14117, 14119, 14121, 14123, 14125, 14127, 14129, 14131, 14133, - 14135, 14137, 14139, 14141, 14143, 14145, 14147, 14149, 14151, 14153, - 14155, 14157, 14159, 14161, 14163, 14165, 14167, 14169, 14171, 14173, - 14175, 14177, 14179, 14181, 14183, 14185, 14187, 14189, 14191, 14193, - 14195, 14197, 14199, 14201, 14203, 14205, 14207, 14209, 14211, 14213, - 14215, 14217, 14219, 14221, 14223, 14225, 14227, 14229, 14231, 14233, - 14235, 14237, 14239, 14241, 14243, 14245, 14247, 14249, 14251, 14253, - 14255, 14257, 14259, 14261, 14263, 14265, 14267, 14269, 14271, 14273, - 14275, 14277, 14279, 14281, 14283, 14285, 14287, 14289, 14291, 14293, - 14295, 14297, 14299, 14301, 14303, 14305, 14307, 14309, 14311, 14313, - 14315, 14317, 14319, 14321, 14323, 14325, 14327, 14329, 14331, 14333, - 14335, 14337, 14339, 14341, 14343, 14345, 14347, 14349, 14351, 14353, - 14355, 14357, 14359, 14361, 14363, 14365, 14367, 14369, 14371, 14373, - 14375, 14377, 14379, 14381, 14383, 14385, 14387, 14389, 14391, 14393, - 14395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /* NFC pairs */ @@ -6107,7 +5966,7 @@ static const change_record change_records_3_2_0[] = { { 19, 30, 255, 255, 255, 0 }, { 255, 8, 255, 255, 255, 0 }, { 255, 27, 255, 255, 255, 0 }, - { 255, 255, 255, 255, 5, 0 }, + { 255, 255, 255, 255, 0, 0 }, { 255, 22, 255, 255, 255, 0 }, { 255, 23, 255, 255, 255, 0 }, { 9, 255, 255, 255, 255, 0 }, diff --git a/Objects/asm_trampoline.S b/Objects/asm_trampoline.S new file mode 100644 index 000000000000000..460707717df0032 --- /dev/null +++ b/Objects/asm_trampoline.S @@ -0,0 +1,28 @@ + .text + .globl _Py_trampoline_func_start +# The following assembly is equivalent to: +# PyObject * +# trampoline(PyThreadState *ts, _PyInterpreterFrame *f, +# int throwflag, py_evaluator evaluator) +# { +# return evaluator(ts, f, throwflag); +# } +_Py_trampoline_func_start: +#ifdef __x86_64__ + sub $8, %rsp + call *%rcx + add $8, %rsp + ret +#endif // __x86_64__ +#if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) + // ARM64 little endian, 64bit ABI + // generate with aarch64-linux-gnu-gcc 12.1 + stp x29, x30, [sp, -16]! + mov x29, sp + blr x3 + ldp x29, x30, [sp], 16 + ret +#endif + .globl _Py_trampoline_func_end +_Py_trampoline_func_end: + .section .note.GNU-stack,"",@progbits diff --git a/Objects/codeobject.c b/Objects/codeobject.c index aeb6a8c0804e54f..72712f40e42c7c3 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -1339,7 +1339,7 @@ _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) PyCodeObject *o = (PyCodeObject*) code; _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra; - if (co_extra == NULL || co_extra->ce_size <= index) { + if (co_extra == NULL || index < 0 || co_extra->ce_size <= index) { *extra = NULL; return 0; } diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d8203486d76d2f7..0cb95d52360ef19 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1686,50 +1686,12 @@ PyDict_GetItem(PyObject *op, PyObject *key) } Py_ssize_t -_PyDict_GetItemHint(PyDictObject *mp, PyObject *key, - Py_ssize_t hint, PyObject **value) +_PyDict_LookupIndex(PyDictObject *mp, PyObject *key) { - assert(*value == NULL); + PyObject *value; assert(PyDict_CheckExact((PyObject*)mp)); assert(PyUnicode_CheckExact(key)); - if (hint >= 0 && hint < mp->ma_keys->dk_nentries) { - PyObject *res = NULL; - - if (DK_IS_UNICODE(mp->ma_keys)) { - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys) + (size_t)hint; - if (ep->me_key == key) { - if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) { - assert(mp->ma_values != NULL); - res = mp->ma_values->values[(size_t)hint]; - } - else { - res = ep->me_value; - } - if (res != NULL) { - *value = res; - return hint; - } - } - } - else { - PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint; - if (ep->me_key == key) { - if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) { - assert(mp->ma_values != NULL); - res = mp->ma_values->values[(size_t)hint]; - } - else { - res = ep->me_value; - } - if (res != NULL) { - *value = res; - return hint; - } - } - } - } - Py_hash_t hash = unicode_get_hash(key); if (hash == -1) { hash = PyObject_Hash(key); @@ -1738,7 +1700,7 @@ _PyDict_GetItemHint(PyDictObject *mp, PyObject *key, } } - return _Py_dict_lookup(mp, key, hash, value); + return _Py_dict_lookup(mp, key, hash, &value); } /* Same as PyDict_GetItemWithError() but with hash supplied by caller. diff --git a/Objects/exception_handling_notes.txt b/Objects/exception_handling_notes.txt index a136358f90c888e..7de01fdbf5ff486 100644 --- a/Objects/exception_handling_notes.txt +++ b/Objects/exception_handling_notes.txt @@ -43,33 +43,36 @@ SETUP_FINALLY and POP_BLOCK. In 3.11, the SETUP_FINALLY and POP_BLOCK are eliminated, replaced with a table to determine where to jump to when an exception is raised. - 2 0 NOP - - 3 2 LOAD_GLOBAL 0 (g) - 4 LOAD_CONST 1 (0) - 6 CALL_NO_KW 1 - 8 POP_TOP - 10 LOAD_CONST 0 (None) - 12 RETURN_VALUE - >> 14 PUSH_EXC_INFO - - 4 16 POP_TOP - 18 POP_TOP - 20 POP_TOP - - 5 22 POP_EXCEPT - 24 LOAD_CONST 2 ('fail') - 26 RETURN_VALUE - >> 28 POP_EXCEPT_AND_RERAISE + 1 0 RESUME 0 + + 2 2 NOP + + 3 4 LOAD_GLOBAL 1 (NULL + g) + 16 LOAD_CONST 1 (0) + 18 PRECALL 1 + 22 CALL 1 + 32 POP_TOP + 34 LOAD_CONST 0 (None) + 36 RETURN_VALUE + >> 38 PUSH_EXC_INFO + + 4 40 POP_TOP + + 5 42 POP_EXCEPT + 44 LOAD_CONST 2 ('fail') + 46 RETURN_VALUE + >> 48 COPY 3 + 50 POP_EXCEPT + 52 RERAISE 1 ExceptionTable: - 2 to 8 -> 14 [0] - 14 to 20 -> 28 [3] lasti + 4 to 32 -> 38 [0] + 38 to 40 -> 48 [1] lasti -(Note this code is from an early 3.11 alpha, the NOP may well have be removed before release). +(Note this code is from 3.11, later versions may have slightly different bytecode.) If an instruction raises an exception then its offset is used to find the target to jump to. -For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8. -So, if g() raises an exception, then control jumps to offset 14. +For example, the CALL at offset 22, falls into the range 4 to 32. +So, if g() raises an exception, then control jumps to offset 38. Unwinding @@ -84,9 +87,9 @@ This information is stored in the exception table, described below. If there is no relevant entry, the exception bubbles up to the caller. If there is an entry, then: - 1. pop values from the stack until it matches the stack depth for the handler, + 1. pop values from the stack until it matches the stack depth for the handler. 2. if 'lasti' is true, then push the offset that the exception was raised at. - 3. push the exception to the stack as three values: traceback, value, type, + 3. push the exception to the stack. 4. jump to the target offset and resume execution. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 26b38bae780c70e..2e3777943126126 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -311,25 +311,12 @@ mark_stacks(PyCodeObject *code_obj, int len) switch (opcode) { case JUMP_IF_FALSE_OR_POP: case JUMP_IF_TRUE_OR_POP: - case POP_JUMP_FORWARD_IF_FALSE: - case POP_JUMP_BACKWARD_IF_FALSE: - case POP_JUMP_FORWARD_IF_TRUE: - case POP_JUMP_BACKWARD_IF_TRUE: + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: { int64_t target_stack; int j = get_arg(code, i); - if (opcode == POP_JUMP_FORWARD_IF_FALSE || - opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == JUMP_IF_FALSE_OR_POP || - opcode == JUMP_IF_TRUE_OR_POP) - { - j += i + 1; - } - else { - assert(opcode == POP_JUMP_BACKWARD_IF_FALSE || - opcode == POP_JUMP_BACKWARD_IF_TRUE); - j = i + 1 - j; - } + j += i + 1; assert(j < len); if (stacks[j] == UNINITIALIZED && j < i) { todo = 1; @@ -910,7 +897,7 @@ frame_dealloc(PyFrameObject *f) /* Don't clear code object until the end */ co = frame->f_code; frame->f_code = NULL; - Py_CLEAR(frame->f_func); + Py_CLEAR(frame->f_funcobj); Py_CLEAR(frame->f_locals); PyObject **locals = _PyFrame_GetLocalsArray(frame); for (int i = 0; i < frame->stacktop; i++) { @@ -1154,10 +1141,12 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) { // COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt // here: int lasti = _PyInterpreterFrame_LASTI(frame); - if (lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS) { + if (lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS + && PyFunction_Check(frame->f_funcobj)) + { /* Free vars have not been initialized -- Do that */ PyCodeObject *co = frame->f_code; - PyObject *closure = frame->f_func->func_closure; + PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; int offset = co->co_nlocals + co->co_nplaincellvars; for (int i = 0; i < co->co_nfreevars; ++i) { PyObject *o = PyTuple_GET_ITEM(closure, i); diff --git a/Objects/genobject.c b/Objects/genobject.c index 2b45e28cbf16dfe..da4afecc69c8c1f 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -485,26 +485,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, } Py_DECREF(yf); if (!ret) { - PyObject *val; - /* Pop subiterator from stack */ - assert(gen->gi_frame_state < FRAME_CLEARED); - ret = _PyFrame_StackPop((_PyInterpreterFrame *)gen->gi_iframe); - assert(ret == yf); - Py_DECREF(ret); - // XXX: Performing this jump ourselves is awkward and problematic. - // See https://github.com/python/cpython/pull/31968. - /* Termination repetition of SEND loop */ - assert(_PyInterpreterFrame_LASTI(frame) >= 0); - /* Backup to SEND */ - assert(_Py_OPCODE(frame->prev_instr[-1]) == SEND); - int jump = _Py_OPARG(frame->prev_instr[-1]); - frame->prev_instr += jump - 1; - if (_PyGen_FetchStopIterationValue(&val) == 0) { - ret = gen_send(gen, val); - Py_DECREF(val); - } else { - ret = gen_send_ex(gen, Py_None, 1, 0); - } + ret = gen_send_ex(gen, Py_None, 1, 0); } return ret; } diff --git a/Objects/longobject.c b/Objects/longobject.c index 90ed02b8c27a198..cb52f82687af286 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -36,6 +36,9 @@ medium_value(PyLongObject *x) #define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) #define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) +#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits" +#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion" + static inline void _Py_DECREF_INT(PyLongObject *op) { @@ -1756,6 +1759,23 @@ long_to_decimal_string_internal(PyObject *aa, size_a = Py_ABS(Py_SIZE(a)); negative = Py_SIZE(a) < 0; + /* quick and dirty pre-check for overflowing the decimal digit limit, + based on the inequality 10/3 >= log2(10) + + explanation in https://github.com/python/cpython/pull/96537 + */ + if (size_a >= 10 * _PY_LONG_MAX_STR_DIGITS_THRESHOLD + / (3 * PyLong_SHIFT) + 2) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + int max_str_digits = interp->int_max_str_digits; + if ((max_str_digits > 0) && + (max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10)) { + PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR, + max_str_digits); + return -1; + } + } + /* quick and dirty upper bound for the number of digits required to express a in base _PyLong_DECIMAL_BASE: @@ -1815,6 +1835,17 @@ long_to_decimal_string_internal(PyObject *aa, tenpow *= 10; strlen++; } + if (strlen > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + int max_str_digits = interp->int_max_str_digits; + Py_ssize_t strlen_nosign = strlen - negative; + if ((max_str_digits > 0) && (strlen_nosign > max_str_digits)) { + Py_DECREF(scratch); + PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR, + max_str_digits); + return -1; + } + } if (writer) { if (_PyUnicodeWriter_Prepare(writer, strlen, '9') == -1) { Py_DECREF(scratch); @@ -2328,6 +2359,7 @@ PyLong_FromString(const char *str, char **pend, int base) start = str; if ((base & (base - 1)) == 0) { + /* binary bases are not limited by int_max_str_digits */ int res = long_from_binary_base(&str, base, &z); if (res < 0) { /* Syntax error. */ @@ -2479,6 +2511,17 @@ digit beyond the first. goto onError; } + /* Limit the size to avoid excessive computation attacks. */ + if (digits > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + int max_str_digits = interp->int_max_str_digits; + if ((max_str_digits > 0) && (digits > max_str_digits)) { + PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_INT, + max_str_digits, digits); + return NULL; + } + } + /* Create an int object that can contain the largest possible * integer with this base and length. Note that there's no * need to initialize z->ob_digit -- no slot is read up before @@ -5355,6 +5398,7 @@ long_new_impl(PyTypeObject *type, PyObject *x, PyObject *obase) } return PyLong_FromLong(0L); } + /* default base and limit, forward to standard implementation */ if (obase == NULL) return PyNumber_Long(x); @@ -6090,6 +6134,8 @@ internal representation of integers. The attributes are read only."); static PyStructSequence_Field int_info_fields[] = { {"bits_per_digit", "size of a digit in bits"}, {"sizeof_digit", "size in bytes of the C type used to represent a digit"}, + {"default_max_str_digits", "maximum string conversion digits limitation"}, + {"str_digits_check_threshold", "minimum positive value for int_max_str_digits"}, {NULL, NULL} }; @@ -6097,7 +6143,7 @@ static PyStructSequence_Desc int_info_desc = { "sys.int_info", /* name */ int_info__doc__, /* doc */ int_info_fields, /* fields */ - 2 /* number of fields */ + 4 /* number of fields */ }; PyObject * @@ -6112,6 +6158,17 @@ PyLong_GetInfo(void) PyLong_FromLong(PyLong_SHIFT)); PyStructSequence_SET_ITEM(int_info, field++, PyLong_FromLong(sizeof(digit))); + /* + * The following two fields were added after investigating uses of + * sys.int_info in the wild: Exceedingly rarely used. The ONLY use found was + * numba using sys.int_info.bits_per_digit as attribute access rather than + * sequence unpacking. Cython and sympy also refer to sys.int_info but only + * as info for debugging. No concern about adding these in a backport. + */ + PyStructSequence_SET_ITEM(int_info, field++, + PyLong_FromLong(_PY_LONG_DEFAULT_MAX_STR_DIGITS)); + PyStructSequence_SET_ITEM(int_info, field++, + PyLong_FromLong(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)); if (PyErr_Occurred()) { Py_CLEAR(int_info); return NULL; @@ -6139,6 +6196,10 @@ _PyLong_InitTypes(PyInterpreterState *interp) return _PyStatus_ERR("can't init int info type"); } } + interp->int_max_str_digits = _Py_global_config_int_max_str_digits; + if (interp->int_max_str_digits == -1) { + interp->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS; + } return _PyStatus_OK(); } diff --git a/Objects/object_layout.md b/Objects/object_layout.md new file mode 100644 index 000000000000000..9380b57938c8e31 --- /dev/null +++ b/Objects/object_layout.md @@ -0,0 +1,82 @@ +# Object layout + +## Common header + +Each Python object starts with two fields: + +* ob_refcnt +* ob_type + +which the form the header common to all Python objects, for all versions, +and hold the reference count and class of the object, respectively. + +## Pre-header + +Since the introduction of the cycle GC, there has also been a pre-header. +Before 3.11, this pre-header was two words in size. +It should be considered opaque to all code except the cycle GC. + +## 3.11 pre-header + +In 3.11 the pre-header was extended to include pointers to the VM managed ``__dict__``. +The reason for moving the ``__dict__`` to the pre-header is that it allows +faster access, as it is at a fixed offset, and it also allows object's +dictionaries to be lazily created when the ``__dict__`` attribute is +specifically asked for. + +In the 3.11 the non-GC part of the pre-header consists of two pointers: + +* dict +* values + +The values pointer refers to the ``PyDictValues`` array which holds the +values of the objects's attributes. +Should the dictionary be needed, then ``values`` is set to ``NULL`` +and the ``dict`` field points to the dictionary. + +## 3.12 pre-header + +In 3.12 the the pointer to the list of weak references is added to the +pre-header. In order to make space for it, the ``dict`` and ``values`` +pointers are combined into a single tagged pointer: + +* weakreflist +* dict_or_values + +If the object has no physical dictionary, then the ``dict_or_values`` +has its low bit set to one, and points to the values array. +If the object has a physical dictioanry, then the ``dict_or_values`` +has its low bit set to zero, and points to the dictionary. + +The untagged form is chosen for the dictionary pointer, rather than +the values pointer, to enable the (legacy) C-API function +`_PyObject_GetDictPtr(PyObject *obj)` to work. + + +## Layout of a "normal" Python object in 3.12: + +* weakreflist +* dict_or_values +* GC 1 +* GC 2 +* ob_refcnt +* ob_type + +For a "normal" Python object, that is one that doesn't inherit from a builtin +class or have slots, the header and pre-header form the entire object. + +![Layout of "normal" object in 3.12](./object_layout_312.png) + +There are several advantages to this layout: + +* It allows lazy `__dict__`s, as described above. +* The regular layout allows us to create tailored traversal and deallocation + functions based on layout, rather than inheritance. +* Multiple inheritance works properly, + as the weakrefs and dict are always at the same offset. + +The full layout object, with an opaque part defined by a C extension, +and `__slots__` looks like this: + +![Layout of "full" object in 3.12](./object_layout_full_312.png) + diff --git a/Objects/object_layout_312.gv b/Objects/object_layout_312.gv new file mode 100644 index 000000000000000..c0068d785685242 --- /dev/null +++ b/Objects/object_layout_312.gv @@ -0,0 +1,50 @@ +digraph ideal { + + rankdir = "LR" + + + object [ + shape = none + label = < + + + + + + + +
    object
    weakrefs
    dict or values
    GC info 0
    GC info 1
    refcount
    __class__
    > + ] + + values [ + shape = none + label = < + + + + +
    values
    values[0]
    values[1]
    ...
    > + + ] + + class [ + shape = none + label = < + + + + + +
    class
    ...
    dict_offset
    ...
    cached_keys
    > + ] + + keys [label = "dictionary keys"; fillcolor="lightgreen"; style="filled"] + NULL [ label = " NULL"; shape="plain"] + object:w -> NULL + object:h -> class:head + object:dv -> values:0 + class:k -> keys + + oop [ label = "pointer"; shape="plain"] + oop -> object:r +} diff --git a/Objects/object_layout_312.png b/Objects/object_layout_312.png new file mode 100644 index 000000000000000..396dab183b3e9b2 Binary files /dev/null and b/Objects/object_layout_312.png differ diff --git a/Objects/object_layout_full_312.gv b/Objects/object_layout_full_312.gv new file mode 100644 index 000000000000000..522fa32b0665047 --- /dev/null +++ b/Objects/object_layout_full_312.gv @@ -0,0 +1,25 @@ +digraph ideal { + + rankdir = "LR" + + + object [ + shape = none + label = < + + + + + + + + + + + +
    object
    weakrefs
    dict or values
    GC info 0
    GC info 1
    refcount
    __class__
    opaque (extension) data
    ...
    __slot__ 0
    ...
    > + ] + + oop [ label = "pointer"; shape="plain"] + oop -> object:r +} diff --git a/Objects/object_layout_full_312.png b/Objects/object_layout_full_312.png new file mode 100644 index 000000000000000..4f46ca86091d452 Binary files /dev/null and b/Objects/object_layout_full_312.png differ diff --git a/Objects/perf_trampoline.c b/Objects/perf_trampoline.c new file mode 100644 index 000000000000000..2cbe3741f26fbc7 --- /dev/null +++ b/Objects/perf_trampoline.c @@ -0,0 +1,512 @@ +/* + +Perf trampoline instrumentation +=============================== + +This file contains instrumentation to allow to associate +calls to the CPython eval loop back to the names of the Python +functions and filename being executed. + +Many native performance profilers like the Linux perf tools are +only available to 'see' the C stack when sampling from the profiled +process. This means that if we have the following python code: + + import time + def foo(n): + # Some CPU intensive code + + def bar(n): + foo(n) + + def baz(n): + bar(n) + + baz(10000000) + +A performance profiler that is only able to see native frames will +produce the following backtrace when sampling from foo(): + + _PyEval_EvalFrameDefault -----> Evaluation frame of foo() + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + _PyEval_EvalFrameDefault ------> Evaluation frame of bar() + _PyEval_EvalFrame + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + _PyEval_EvalFrameDefault -------> Evaluation frame of baz() + _PyEval_EvalFrame + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + ... + + Py_RunMain + +Because the profiler is only able to see the native frames and the native +function that runs the evaluation loop is the same (_PyEval_EvalFrameDefault) +then the profiler and any reporter generated by it will not be able to +associate the names of the Python functions and the filenames associated with +those calls, rendering the results useless in the Python world. + +To fix this problem, we introduce the concept of a trampoline frame. A +trampoline frame is a piece of code that is unique per Python code object that +is executed before entering the CPython eval loop. This piece of code just +calls the original Python evaluation function (_PyEval_EvalFrameDefault) and +forwards all the arguments received. In this way, when a profiler samples +frames from the previous example it will see; + + _PyEval_EvalFrameDefault -----> Evaluation frame of foo() + [Jit compiled code 3] + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + _PyEval_EvalFrameDefault ------> Evaluation frame of bar() + [Jit compiled code 2] + _PyEval_EvalFrame + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + _PyEval_EvalFrameDefault -------> Evaluation frame of baz() + [Jit compiled code 1] + _PyEval_EvalFrame + _PyEval_Vector + _PyFunction_Vectorcall + PyObject_Vectorcall + call_function + + ... + + Py_RunMain + +When we generate every unique copy of the trampoline (what here we called "[Jit +compiled code N]") we write the relationship between the compiled code and the +Python function that is associated with it. Every profiler requires this +information in a different format. For example, the Linux "perf" profiler +requires a file in "/tmp/perf-PID.map" (name and location not configurable) +with the following format: + + + +If this file is available when "perf" generates reports, it will automatically +associate every trampoline with the Python function that it is associated with +allowing it to generate reports that include Python information. These reports +then can also be filtered in a way that *only* Python information appears. + +Notice that for this to work, there must be a unique copied of the trampoline +per Python code object even if the code in the trampoline is the same. To +achieve this we have a assembly template in Objects/asm_trampiline.S that is +compiled into the Python executable/shared library. This template generates a +symbol that maps the start of the assembly code and another that marks the end +of the assembly code for the trampoline. Then, every time we need a unique +trampoline for a Python code object, we copy the assembly code into a mmaped +area that has executable permissions and we return the start of that area as +our trampoline function. + +Asking for a mmap-ed memory area for trampoline is very wasteful so we +allocate big arenas of memory in a single mmap call, we populate the entire +arena with copies of the trampoline (this allows us to now have to invalidate +the icache for the instructions in the page) and then we return the next +available chunk every time someone asks for a new trampoline. We keep a linked +list of arenas in case the current memory arena is exhausted and another one is +needed. + +For the best results, Python should be compiled with +CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" as this allows +profilers to unwind using only the frame pointer and not on DWARF debug +information (note that as trampilines are dynamically generated there won't be +any DWARF information available for them). +*/ + +#include "Python.h" +#include "pycore_ceval.h" +#include "pycore_frame.h" +#include "pycore_interp.h" + +typedef enum { + PERF_STATUS_FAILED = -1, // Perf trampoline is in an invalid state + PERF_STATUS_NO_INIT = 0, // Perf trampoline is not initialized + PERF_STATUS_OK = 1, // Perf trampoline is ready to be executed +} perf_status_t; + +#ifdef PY_HAVE_PERF_TRAMPOLINE + +#include +#include +#include +#include +#include +#include + +/* The function pointer is passed as last argument. The other three arguments + * are passed in the same order as the function requires. This results in + * shorter, more efficient ASM code for trampoline. + */ +typedef PyObject *(*py_evaluator)(PyThreadState *, _PyInterpreterFrame *, + int throwflag); +typedef PyObject *(*py_trampoline)(PyThreadState *, _PyInterpreterFrame *, int, + py_evaluator); + +extern void *_Py_trampoline_func_start; // Start of the template of the + // assembly trampoline +extern void * + _Py_trampoline_func_end; // End of the template of the assembly trampoline + +struct code_arena_st { + char *start_addr; // Start of the memory arena + char *current_addr; // Address of the current trampoline within the arena + size_t size; // Size of the memory arena + size_t size_left; // Remaining size of the memory arena + size_t code_size; // Size of the code of every trampoline in the arena + struct code_arena_st + *prev; // Pointer to the arena or NULL if this is the first arena. +}; + +typedef struct code_arena_st code_arena_t; + +struct trampoline_api_st { + void* (*init_state)(void); + void (*write_state)(void* state, const void *code_addr, + unsigned int code_size, PyCodeObject* code); + int (*free_state)(void* state); + void *state; +}; + +typedef struct trampoline_api_st trampoline_api_t; + +static perf_status_t perf_status = PERF_STATUS_NO_INIT; +static Py_ssize_t extra_code_index = -1; +static code_arena_t *code_arena; +static trampoline_api_t trampoline_api; + +static FILE *perf_map_file; + +static void * +perf_map_get_file(void) +{ + if (perf_map_file) { + return perf_map_file; + } + char filename[100]; + pid_t pid = getpid(); + // Location and file name of perf map is hard-coded in perf tool. + // Use exclusive create flag wit nofollow to prevent symlink attacks. + int flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC; + snprintf(filename, sizeof(filename) - 1, "/tmp/perf-%jd.map", + (intmax_t)pid); + int fd = open(filename, flags, 0600); + if (fd == -1) { + perf_status = PERF_STATUS_FAILED; + PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); + return NULL; + } + perf_map_file = fdopen(fd, "w"); + if (!perf_map_file) { + perf_status = PERF_STATUS_FAILED; + PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); + close(fd); + return NULL; + } + return perf_map_file; +} + +static int +perf_map_close(void *state) +{ + FILE *fp = (FILE *)state; + int ret = 0; + if (fp) { + ret = fclose(fp); + } + perf_map_file = NULL; + perf_status = PERF_STATUS_NO_INIT; + return ret; +} + +static void +perf_map_write_entry(void *state, const void *code_addr, + unsigned int code_size, PyCodeObject *co) +{ + assert(state != NULL); + FILE *method_file = (FILE *)state; + const char *entry = PyUnicode_AsUTF8(co->co_qualname); + if (entry == NULL) { + _PyErr_WriteUnraisableMsg("Failed to get qualname from code object", + NULL); + return; + } + const char *filename = PyUnicode_AsUTF8(co->co_filename); + if (filename == NULL) { + _PyErr_WriteUnraisableMsg("Failed to get filename from code object", + NULL); + return; + } + fprintf(method_file, "%p %x py::%s:%s\n", code_addr, code_size, entry, + filename); + fflush(method_file); +} + +_PyPerf_Callbacks _Py_perfmap_callbacks = { + &perf_map_get_file, + &perf_map_write_entry, + &perf_map_close +}; + +static int +new_code_arena(void) +{ + // non-trivial programs typically need 64 to 256 kiB. + size_t mem_size = 4096 * 16; + assert(mem_size % sysconf(_SC_PAGESIZE) == 0); + char *memory = + mmap(NULL, // address + mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, // fd (not used here) + 0); // offset (not used here) + if (!memory) { + PyErr_SetFromErrno(PyExc_OSError); + _PyErr_WriteUnraisableMsg( + "Failed to create new mmap for perf trampoline", NULL); + perf_status = PERF_STATUS_FAILED; + return -1; + } + void *start = &_Py_trampoline_func_start; + void *end = &_Py_trampoline_func_end; + size_t code_size = end - start; + // TODO: Check the effect of alignment of the code chunks. Initial investigation + // showed that this has no effect on performance in x86-64 or aarch64 and the current + // version has the advantage that the unwinder in GDB can unwind across JIT-ed code. + // + // We should check the values in the future and see if there is a + // measurable performance improvement by rounding trampolines up to 32-bit + // or 64-bit alignment. + + size_t n_copies = mem_size / code_size; + for (size_t i = 0; i < n_copies; i++) { + memcpy(memory + i * code_size, start, code_size * sizeof(char)); + } + // Some systems may prevent us from creating executable code on the fly. + // TODO: Call icache invalidation intrinsics if available: + // __builtin___clear_cache/__clear_cache (depending if clang/gcc). This is + // technically not necessary but we could be missing something so better be + // safe. + int res = mprotect(memory, mem_size, PROT_READ | PROT_EXEC); + if (res == -1) { + PyErr_SetFromErrno(PyExc_OSError); + munmap(memory, mem_size); + _PyErr_WriteUnraisableMsg( + "Failed to set mmap for perf trampoline to PROT_READ | PROT_EXEC", + NULL); + return -1; + } + + code_arena_t *new_arena = PyMem_RawCalloc(1, sizeof(code_arena_t)); + if (new_arena == NULL) { + PyErr_NoMemory(); + munmap(memory, mem_size); + _PyErr_WriteUnraisableMsg("Failed to allocate new code arena struct", + NULL); + return -1; + } + + new_arena->start_addr = memory; + new_arena->current_addr = memory; + new_arena->size = mem_size; + new_arena->size_left = mem_size; + new_arena->code_size = code_size; + new_arena->prev = code_arena; + code_arena = new_arena; + return 0; +} + +static void +free_code_arenas(void) +{ + code_arena_t *cur = code_arena; + code_arena_t *prev; + code_arena = NULL; // invalid static pointer + while (cur) { + munmap(cur->start_addr, cur->size); + prev = cur->prev; + PyMem_RawFree(cur); + cur = prev; + } +} + +static inline py_trampoline +code_arena_new_code(code_arena_t *code_arena) +{ + py_trampoline trampoline = (py_trampoline)code_arena->current_addr; + code_arena->size_left -= code_arena->code_size; + code_arena->current_addr += code_arena->code_size; + return trampoline; +} + +static inline py_trampoline +compile_trampoline(void) +{ + if ((code_arena == NULL) || + (code_arena->size_left <= code_arena->code_size)) { + if (new_code_arena() < 0) { + return NULL; + } + } + assert(code_arena->size_left <= code_arena->size); + return code_arena_new_code(code_arena); +} + +static PyObject * +py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame, + int throw) +{ + if (perf_status == PERF_STATUS_FAILED || + perf_status == PERF_STATUS_NO_INIT) { + goto default_eval; + } + PyCodeObject *co = frame->f_code; + py_trampoline f = NULL; + assert(extra_code_index != -1); + int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f); + if (ret != 0 || f == NULL) { + // This is the first time we see this code object so we need + // to compile a trampoline for it. + py_trampoline new_trampoline = compile_trampoline(); + if (new_trampoline == NULL) { + goto default_eval; + } + trampoline_api.write_state(trampoline_api.state, new_trampoline, + code_arena->code_size, co); + _PyCode_SetExtra((PyObject *)co, extra_code_index, + (void *)new_trampoline); + f = new_trampoline; + } + assert(f != NULL); + return f(ts, frame, throw, _PyEval_EvalFrameDefault); +default_eval: + // Something failed, fall back to the default evaluator. + return _PyEval_EvalFrameDefault(ts, frame, throw); +} +#endif // PY_HAVE_PERF_TRAMPOLINE + +int +_PyIsPerfTrampolineActive(void) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + PyThreadState *tstate = _PyThreadState_GET(); + return tstate->interp->eval_frame == py_trampoline_evaluator; +#endif + return 0; +} + +void +_PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *callbacks) +{ + if (callbacks == NULL) { + return; + } +#ifdef PY_HAVE_PERF_TRAMPOLINE + callbacks->init_state = trampoline_api.init_state; + callbacks->write_state = trampoline_api.write_state; + callbacks->free_state = trampoline_api.free_state; +#endif + return; +} + +int +_PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks) +{ + if (callbacks == NULL) { + return -1; + } +#ifdef PY_HAVE_PERF_TRAMPOLINE + if (trampoline_api.state) { + _PyPerfTrampoline_Fini(); + } + trampoline_api.init_state = callbacks->init_state; + trampoline_api.write_state = callbacks->write_state; + trampoline_api.free_state = callbacks->free_state; + trampoline_api.state = NULL; + perf_status = PERF_STATUS_OK; +#endif + return 0; +} + +int +_PyPerfTrampoline_Init(int activate) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + PyThreadState *tstate = _PyThreadState_GET(); + if (tstate->interp->eval_frame && + tstate->interp->eval_frame != py_trampoline_evaluator) { + PyErr_SetString(PyExc_RuntimeError, + "Trampoline cannot be initialized as a custom eval " + "frame is already present"); + return -1; + } + if (!activate) { + tstate->interp->eval_frame = NULL; + } + else { + tstate->interp->eval_frame = py_trampoline_evaluator; + if (new_code_arena() < 0) { + return -1; + } + if (trampoline_api.state == NULL) { + void *state = trampoline_api.init_state(); + if (state == NULL) { + return -1; + } + trampoline_api.state = state; + } + extra_code_index = _PyEval_RequestCodeExtraIndex(NULL); + if (extra_code_index == -1) { + return -1; + } + perf_status = PERF_STATUS_OK; + } +#endif + return 0; +} + +int +_PyPerfTrampoline_Fini(void) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + PyThreadState *tstate = _PyThreadState_GET(); + if (tstate->interp->eval_frame == py_trampoline_evaluator) { + tstate->interp->eval_frame = NULL; + } + free_code_arenas(); + if (trampoline_api.state != NULL) { + trampoline_api.free_state(trampoline_api.state); + trampoline_api.state = NULL; + } + extra_code_index = -1; +#endif + return 0; +} + +PyStatus +_PyPerfTrampoline_AfterFork_Child(void) +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + // Restart trampoline in file in child. + int was_active = _PyIsPerfTrampolineActive(); + _PyPerfTrampoline_Fini(); + if (was_active) { + _PyPerfTrampoline_Init(1); + } +#endif + return PyStatus_Ok(); +} diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c881aeb63d7565c..40d42947dbcfd4c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -70,11 +70,13 @@ static inline PyTypeObject * subclass_from_ref(PyObject *ref); /* helpers for for static builtin types */ +#ifndef NDEBUG static inline int static_builtin_index_is_set(PyTypeObject *self) { return self->tp_subclasses != NULL; } +#endif static inline size_t static_builtin_index_get(PyTypeObject *self) @@ -2330,36 +2332,13 @@ best_base(PyObject *bases) return base; } -#define ADDED_FIELD_AT_OFFSET(name, offset) \ - (type->tp_ ## name && (base->tp_ ##name == 0) && \ - type->tp_ ## name + sizeof(PyObject *) == (offset) && \ - type->tp_flags & Py_TPFLAGS_HEAPTYPE) - static int -extra_ivars(PyTypeObject *type, PyTypeObject *base) +shape_differs(PyTypeObject *t1, PyTypeObject *t2) { - size_t t_size = type->tp_basicsize; - size_t b_size = base->tp_basicsize; - - assert(t_size >= b_size); /* Else type smaller than base! */ - if (type->tp_itemsize || base->tp_itemsize) { - /* If itemsize is involved, stricter rules */ - return t_size != b_size || - type->tp_itemsize != base->tp_itemsize; - } - /* Check for __dict__ and __weakrefs__ slots in either order */ - if (ADDED_FIELD_AT_OFFSET(weaklistoffset, t_size)) { - t_size -= sizeof(PyObject *); - } - if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0 && - ADDED_FIELD_AT_OFFSET(dictoffset, t_size)) { - t_size -= sizeof(PyObject *); - } - /* Check __weakrefs__ again, in case it precedes __dict__ */ - if (ADDED_FIELD_AT_OFFSET(weaklistoffset, t_size)) { - t_size -= sizeof(PyObject *); - } - return t_size != b_size; + return ( + t1->tp_basicsize != t2->tp_basicsize || + t1->tp_itemsize != t2->tp_itemsize + ); } static PyTypeObject * @@ -2367,14 +2346,18 @@ solid_base(PyTypeObject *type) { PyTypeObject *base; - if (type->tp_base) + if (type->tp_base) { base = solid_base(type->tp_base); - else + } + else { base = &PyBaseObject_Type; - if (extra_ivars(type, base)) + } + if (shape_differs(type, base)) { return type; - else + } + else { return base; + } } static void object_dealloc(PyObject *); @@ -3304,11 +3287,6 @@ type_new_impl(type_new_ctx *ctx) // Put the proper slots in place fixup_slot_dispatchers(type); - if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { - PyHeapTypeObject *et = (PyHeapTypeObject*)type; - et->ht_cached_keys = _PyDict_NewKeysForClass(); - } - if (type_new_set_names(type) < 0) { goto error; } @@ -3853,10 +3831,6 @@ PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module, goto finally; } - if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { - res->ht_cached_keys = _PyDict_NewKeysForClass(); - } - if (type->tp_doc) { PyObject *__doc__ = PyUnicode_FromString(_PyType_DocWithoutSignature(type->tp_name, type->tp_doc)); if (!__doc__) { @@ -6791,6 +6765,29 @@ type_ready_set_new(PyTypeObject *type) return 0; } +static int +type_ready_managed_dict(PyTypeObject *type) +{ + if (!(type->tp_flags & Py_TPFLAGS_MANAGED_DICT)) { + return 0; + } + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + PyErr_Format(PyExc_SystemError, + "type %s has the Py_TPFLAGS_MANAGED_DICT flag " + "but not Py_TPFLAGS_HEAPTYPE flag", + type->tp_name); + return -1; + } + PyHeapTypeObject* et = (PyHeapTypeObject*)type; + if (et->ht_cached_keys == NULL) { + et->ht_cached_keys = _PyDict_NewKeysForClass(); + if (et->ht_cached_keys == NULL) { + PyErr_NoMemory(); + return -1; + } + } + return 0; +} static int type_ready_post_checks(PyTypeObject *type) @@ -6869,6 +6866,9 @@ type_ready(PyTypeObject *type) if (type_ready_add_subclasses(type) < 0) { return -1; } + if (type_ready_managed_dict(type) < 0) { + return -1; + } if (type_ready_post_checks(type) < 0) { return -1; } @@ -8102,17 +8102,17 @@ slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) /* There are two slot dispatch functions for tp_getattro. - - slot_tp_getattro() is used when __getattribute__ is overridden + - _Py_slot_tp_getattro() is used when __getattribute__ is overridden but no __getattr__ hook is present; - - slot_tp_getattr_hook() is used when a __getattr__ hook is present. + - _Py_slot_tp_getattr_hook() is used when a __getattr__ hook is present. - The code in update_one_slot() always installs slot_tp_getattr_hook(); this - detects the absence of __getattr__ and then installs the simpler slot if - necessary. */ + The code in update_one_slot() always installs _Py_slot_tp_getattr_hook(); + this detects the absence of __getattr__ and then installs the simpler + slot if necessary. */ -static PyObject * -slot_tp_getattro(PyObject *self, PyObject *name) +PyObject * +_Py_slot_tp_getattro(PyObject *self, PyObject *name) { PyObject *stack[2] = {self, name}; return vectorcall_method(&_Py_ID(__getattribute__), stack, 2); @@ -8143,8 +8143,8 @@ call_attribute(PyObject *self, PyObject *attr, PyObject *name) return res; } -static PyObject * -slot_tp_getattr_hook(PyObject *self, PyObject *name) +PyObject * +_Py_slot_tp_getattr_hook(PyObject *self, PyObject *name) { PyTypeObject *tp = Py_TYPE(self); PyObject *getattr, *getattribute, *res; @@ -8157,8 +8157,8 @@ slot_tp_getattr_hook(PyObject *self, PyObject *name) getattr = _PyType_Lookup(tp, &_Py_ID(__getattr__)); if (getattr == NULL) { /* No __getattr__ hook: use a simpler dispatcher */ - tp->tp_getattro = slot_tp_getattro; - return slot_tp_getattro(self, name); + tp->tp_getattro = _Py_slot_tp_getattro; + return _Py_slot_tp_getattro(self, name); } Py_INCREF(getattr); /* speed hack: we could use lookup_maybe, but that would resolve the @@ -8519,10 +8519,10 @@ static slotdef slotdefs[] = { PyWrapperFlag_KEYWORDS), TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, "__str__($self, /)\n--\n\nReturn str(self)."), - TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, + TPSLOT("__getattribute__", tp_getattro, _Py_slot_tp_getattr_hook, wrap_binaryfunc, "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, name)."), - TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), + TPSLOT("__getattr__", tp_getattro, _Py_slot_tp_getattr_hook, NULL, ""), TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, name, value)."), TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr, diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index b1d14a32f70f3e3..bd169ed714212dd 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -191,16 +191,6 @@ extern "C" { # define OVERALLOCATE_FACTOR 4 #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) -*/ -static PyObject *interned = NULL; - /* Forward declaration */ static inline int _PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch); @@ -235,6 +225,23 @@ static inline PyObject* unicode_new_empty(void) return empty; } +/* 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) +*/ +static inline PyObject *get_interned_dict(void) +{ + return _PyRuntime.global_objects.interned; +} + +static inline void set_interned_dict(PyObject *dict) +{ + _PyRuntime.global_objects.interned = dict; +} + #define _Py_RETURN_UNICODE_EMPTY() \ do { \ return unicode_new_empty(); \ @@ -1523,7 +1530,7 @@ unicode_dealloc(PyObject *unicode) _Py_FatalRefcountError("deallocating an Unicode singleton"); } #endif - + PyObject *interned = get_interned_dict(); if (PyUnicode_CHECK_INTERNED(unicode)) { /* Revive the dead object temporarily. PyDict_DelItem() removes two references (key and value) which were ignored by @@ -14657,12 +14664,14 @@ PyUnicode_InternInPlace(PyObject **p) return; } + PyObject *interned = get_interned_dict(); if (interned == NULL) { interned = PyDict_New(); if (interned == NULL) { PyErr_Clear(); /* Don't leave an exception */ return; } + set_interned_dict(interned); } PyObject *t = PyDict_SetDefault(interned, s, s); @@ -14713,6 +14722,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) return; } + PyObject *interned = get_interned_dict(); if (interned == NULL) { return; } @@ -14748,7 +14758,8 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) #endif PyDict_Clear(interned); - Py_CLEAR(interned); + Py_DECREF(interned); + set_interned_dict(NULL); } @@ -15155,7 +15166,7 @@ _PyUnicode_EnableLegacyWindowsFSEncoding(void) static inline int unicode_is_finalizing(void) { - return (interned == NULL); + return (get_interned_dict() == NULL); } #endif @@ -15173,23 +15184,6 @@ _PyUnicode_FiniTypes(PyInterpreterState *interp) } -static void unicode_static_dealloc(PyObject *op) -{ - PyASCIIObject *ascii = _PyASCIIObject_CAST(op); - - assert(ascii->state.compact); - - if (!ascii->state.ascii) { - PyCompactUnicodeObject* compact = (PyCompactUnicodeObject*)op; - if (compact->utf8) { - PyObject_Free(compact->utf8); - compact->utf8 = NULL; - compact->utf8_length = 0; - } - } -} - - void _PyUnicode_Fini(PyInterpreterState *interp) { @@ -15197,7 +15191,7 @@ _PyUnicode_Fini(PyInterpreterState *interp) if (_Py_IsMainInterpreter(interp)) { // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() - assert(interned == NULL); + assert(get_interned_dict() == NULL); // bpo-47182: force a unicodedata CAPI capsule re-import on // subsequent initialization of main interpreter. ucnhash_capi = NULL; @@ -15206,24 +15200,8 @@ _PyUnicode_Fini(PyInterpreterState *interp) _PyUnicode_FiniEncodings(&state->fs_codec); unicode_clear_identifiers(state); - - // Clear the single character singletons - for (int i = 0; i < 128; i++) { - unicode_static_dealloc((PyObject*)&_Py_SINGLETON(strings).ascii[i]); - } - for (int i = 0; i < 128; i++) { - unicode_static_dealloc((PyObject*)&_Py_SINGLETON(strings).latin1[i]); - } -} - - -void -_PyStaticUnicode_Dealloc(PyObject *op) -{ - unicode_static_dealloc(op); } - /* A _string module, to export formatter_parser and formatter_field_name_split to the string.Formatter class implemented in Python. */ diff --git a/PC/_msi.c b/PC/_msi.c index 3f50f9b88459471..3686b9bb6f2a6de 100644 --- a/PC/_msi.c +++ b/PC/_msi.c @@ -360,7 +360,7 @@ msierror(int status) int code; char buf[2000]; char *res = buf; - DWORD size = sizeof(buf); + DWORD size = Py_ARRAY_LENGTH(buf); MSIHANDLE err = MsiGetLastErrorRecord(); if (err == 0) { @@ -484,7 +484,7 @@ _msi_Record_GetString_impl(msiobj *self, unsigned int field) unsigned int status; WCHAR buf[2000]; WCHAR *res = buf; - DWORD size = sizeof(buf); + DWORD size = Py_ARRAY_LENGTH(buf); PyObject* string; status = MsiRecordGetStringW(self->h, field, res, &size); diff --git a/PC/_wmimodule.cpp b/PC/_wmimodule.cpp new file mode 100644 index 000000000000000..a9f7836172ba2c8 --- /dev/null +++ b/PC/_wmimodule.cpp @@ -0,0 +1,307 @@ +// +// Helper library for querying WMI using its COM-based query API. +// +// Copyright (c) Microsoft Corporation +// Licensed to PSF under a contributor agreement +// + +// Version history +// 2022-08: Initial contribution (Steve Dower) + +#define _WIN32_DCOM +#include +#include +#include +#include + +#include +#include "clinic/_wmimodule.cpp.h" + + +/*[clinic input] +module _wmi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7ca95dad1453d10d]*/ + + + +struct _query_data { + LPCWSTR query; + HANDLE writePipe; + HANDLE readPipe; +}; + + +static DWORD WINAPI +_query_thread(LPVOID param) +{ + IWbemLocator *locator = NULL; + IWbemServices *services = NULL; + IEnumWbemClassObject* enumerator = NULL; + BSTR bstrQuery = NULL; + struct _query_data *data = (struct _query_data*)param; + + HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + CloseHandle(data->writePipe); + return (DWORD)hr; + } + + hr = CoInitializeSecurity( + NULL, -1, NULL, NULL, + RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE, NULL + ); + if (SUCCEEDED(hr)) { + hr = CoCreateInstance( + CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *)&locator + ); + } + if (SUCCEEDED(hr)) { + hr = locator->ConnectServer( + bstr_t(L"ROOT\\CIMV2"), + NULL, NULL, 0, NULL, 0, 0, &services + ); + } + if (SUCCEEDED(hr)) { + hr = CoSetProxyBlanket( + services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE + ); + } + if (SUCCEEDED(hr)) { + bstrQuery = SysAllocString(data->query); + if (!bstrQuery) { + hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); + } + } + if (SUCCEEDED(hr)) { + hr = services->ExecQuery( + bstr_t("WQL"), + bstrQuery, + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &enumerator + ); + } + + // Okay, after all that, at this stage we should have an enumerator + // to the query results and can start writing them to the pipe! + IWbemClassObject *value = NULL; + int startOfEnum = TRUE; + int endOfEnum = FALSE; + while (SUCCEEDED(hr) && !endOfEnum) { + ULONG got = 0; + DWORD written; + hr = enumerator->Next(WBEM_INFINITE, 1, &value, &got); + if (hr == WBEM_S_FALSE) { + // Could be at the end, but still got a result this time + endOfEnum = TRUE; + hr = 0; + break; + } + if (FAILED(hr) || got != 1 || !value) { + continue; + } + if (!startOfEnum && !WriteFile(data->writePipe, (LPVOID)L"\0", 2, &written, NULL)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + break; + } + startOfEnum = FALSE; + // Okay, now we have each resulting object it's time to + // enumerate its members + hr = value->BeginEnumeration(0); + if (FAILED(hr)) { + value->Release(); + break; + } + while (SUCCEEDED(hr)) { + BSTR propName; + VARIANT propValue; + long flavor; + hr = value->Next(0, &propName, &propValue, NULL, &flavor); + if (hr == WBEM_S_NO_MORE_DATA) { + hr = 0; + break; + } + if (SUCCEEDED(hr) && (flavor & WBEM_FLAVOR_MASK_ORIGIN) != WBEM_FLAVOR_ORIGIN_SYSTEM) { + WCHAR propStr[8192]; + hr = VariantToString(propValue, propStr, sizeof(propStr) / sizeof(propStr[0])); + if (SUCCEEDED(hr)) { + DWORD cbStr1, cbStr2; + cbStr1 = (DWORD)(wcslen(propName) * sizeof(propName[0])); + cbStr2 = (DWORD)(wcslen(propStr) * sizeof(propStr[0])); + if (!WriteFile(data->writePipe, propName, cbStr1, &written, NULL) || + !WriteFile(data->writePipe, (LPVOID)L"=", 2, &written, NULL) || + !WriteFile(data->writePipe, propStr, cbStr2, &written, NULL) || + !WriteFile(data->writePipe, (LPVOID)L"\0", 2, &written, NULL) + ) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + VariantClear(&propValue); + SysFreeString(propName); + } + } + value->EndEnumeration(); + value->Release(); + } + + if (bstrQuery) { + SysFreeString(bstrQuery); + } + if (enumerator) { + enumerator->Release(); + } + if (services) { + services->Release(); + } + if (locator) { + locator->Release(); + } + CoUninitialize(); + CloseHandle(data->writePipe); + return (DWORD)hr; +} + + +/*[clinic input] +_wmi.exec_query + + query: unicode + +Runs a WMI query against the local machine. + +This returns a single string with 'name=value' pairs in a flat array separated +by null characters. +[clinic start generated code]*/ + +static PyObject * +_wmi_exec_query_impl(PyObject *module, PyObject *query) +/*[clinic end generated code: output=a62303d5bb5e003f input=48d2d0a1e1a7e3c2]*/ + +/*[clinic end generated code]*/ +{ + PyObject *result = NULL; + HANDLE hThread = NULL; + int err = 0; + WCHAR buffer[8192]; + DWORD offset = 0; + DWORD bytesRead; + struct _query_data data = {0}; + + if (PySys_Audit("_wmi.exec_query", "O", query) < 0) { + return NULL; + } + + data.query = PyUnicode_AsWideCharString(query, NULL); + if (!data.query) { + return NULL; + } + + if (0 != _wcsnicmp(data.query, L"select ", 7)) { + PyMem_Free((void *)data.query); + PyErr_SetString(PyExc_ValueError, "only SELECT queries are supported"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + + if (!CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) { + err = GetLastError(); + } else { + hThread = CreateThread(NULL, 0, _query_thread, (LPVOID*)&data, 0, NULL); + if (!hThread) { + err = GetLastError(); + // Normally the thread proc closes this handle, but since we never started + // we need to close it here. + CloseHandle(data.writePipe); + } + } + + while (!err) { + if (ReadFile( + data.readPipe, + (LPVOID)&buffer[offset / sizeof(buffer[0])], + sizeof(buffer) - offset, + &bytesRead, + NULL + )) { + offset += bytesRead; + if (offset >= sizeof(buffer)) { + err = ERROR_MORE_DATA; + } + } else { + err = GetLastError(); + } + } + + if (data.readPipe) { + CloseHandle(data.readPipe); + } + + // Allow the thread some time to clean up + switch (WaitForSingleObject(hThread, 1000)) { + case WAIT_OBJECT_0: + // Thread ended cleanly + if (!GetExitCodeThread(hThread, (LPDWORD)&err)) { + err = GetLastError(); + } + break; + case WAIT_TIMEOUT: + // Probably stuck - there's not much we can do, unfortunately + if (err == 0 || err == ERROR_BROKEN_PIPE) { + err = WAIT_TIMEOUT; + } + break; + default: + if (err == 0 || err == ERROR_BROKEN_PIPE) { + err = GetLastError(); + } + break; + } + + CloseHandle(hThread); + hThread = NULL; + + Py_END_ALLOW_THREADS + + PyMem_Free((void *)data.query); + + if (err == ERROR_MORE_DATA) { + PyErr_Format(PyExc_OSError, "Query returns more than %zd characters", Py_ARRAY_LENGTH(buffer)); + return NULL; + } else if (err) { + PyErr_SetFromWindowsErr(err); + return NULL; + } + + if (!offset) { + return PyUnicode_FromStringAndSize(NULL, 0); + } + return PyUnicode_FromWideChar(buffer, offset / sizeof(buffer[0]) - 1); +} + + +static PyMethodDef wmi_functions[] = { + _WMI_EXEC_QUERY_METHODDEF + { NULL, NULL, 0, NULL } +}; + +static PyModuleDef wmi_def = { + PyModuleDef_HEAD_INIT, + "_wmi", + NULL, // doc + 0, // m_size + wmi_functions +}; + +extern "C" { + PyMODINIT_FUNC PyInit__wmi(void) + { + return PyModuleDef_Init(&wmi_def); + } +} diff --git a/PC/clinic/_wmimodule.cpp.h b/PC/clinic/_wmimodule.cpp.h new file mode 100644 index 000000000000000..e2b947f339da60d --- /dev/null +++ b/PC/clinic/_wmimodule.cpp.h @@ -0,0 +1,75 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(_wmi_exec_query__doc__, +"exec_query($module, /, query)\n" +"--\n" +"\n" +"Runs a WMI query against the local machine.\n" +"\n" +"This returns a single string with \'name=value\' pairs in a flat array separated\n" +"by null characters."); + +#define _WMI_EXEC_QUERY_METHODDEF \ + {"exec_query", _PyCFunction_CAST(_wmi_exec_query), METH_FASTCALL|METH_KEYWORDS, _wmi_exec_query__doc__}, + +static PyObject * +_wmi_exec_query_impl(PyObject *module, PyObject *query); + +static PyObject * +_wmi_exec_query(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(query), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"query", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "exec_query", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *query; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("exec_query", "argument 'query'", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + query = args[0]; + return_value = _wmi_exec_query_impl(module, query); + +exit: + return return_value; +} +/*[clinic end generated code: output=7fdf0c0579ddb566 input=a9049054013a1b77]*/ diff --git a/PC/launcher2.c b/PC/launcher2.c index a5dfd25f7d52f0b..23eaa19dde38e86 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -393,12 +393,6 @@ typedef struct { // only currently possible high priority environment is an active virtual // environment bool lowPriorityTag; - // if true, we had an old-style tag with '-64' suffix, and so do not - // want to match tags like '3.x-32' - bool exclude32Bit; - // if true, we had an old-style tag with '-32' suffix, and so *only* - // want to match tags like '3.x-32' - bool only32Bit; // if true, allow PEP 514 lookup to override 'executable' bool allowExecutableOverride; // if true, allow a nearby pyvenv.cfg to locate the executable @@ -483,8 +477,6 @@ dumpSearchInfo(SearchInfo *search) DEBUG_2(tag, tagLength); DEBUG_BOOL(oldStyleTag); DEBUG_BOOL(lowPriorityTag); - DEBUG_BOOL(exclude32Bit); - DEBUG_BOOL(only32Bit); DEBUG_BOOL(allowDefaults); DEBUG_BOOL(allowExecutableOverride); DEBUG_BOOL(windowed); @@ -649,17 +641,6 @@ parseCommandLine(SearchInfo *search) search->tagLength = argLen; search->oldStyleTag = true; search->restOfCmdLine = tail; - // If the tag ends with -64, we want to exclude 32-bit runtimes - // (If the tag ends with -32, it will be filtered later) - if (argLen > 3) { - if (0 == _compareArgument(&arg[argLen - 3], 3, L"-64", 3)) { - search->tagLength -= 3; - search->exclude32Bit = true; - } else if (0 == _compareArgument(&arg[argLen - 3], 3, L"-32", 3)) { - search->tagLength -= 3; - search->only32Bit = true; - } - } } else if (STARTSWITH(L"V:") || STARTSWITH(L"-version:")) { // Arguments starting with 'V:' specify company and/or tag const wchar_t *argStart = wcschr(arg, L':') + 1; @@ -1087,6 +1068,7 @@ checkDefaults(SearchInfo *search) if (!slash) { search->tag = tag; search->tagLength = n; + search->oldStyleTag = true; } else { search->company = tag; search->companyLength = (int)(slash - tag); @@ -1966,10 +1948,25 @@ _selectEnvironment(const SearchInfo *search, EnvironmentInfo *env, EnvironmentIn } } else if (0 == _compare(env->company, -1, L"PythonCore", -1)) { // Old-style tags can only match PythonCore entries - if (_startsWith(env->tag, -1, search->tag, search->tagLength)) { - if (search->exclude32Bit && _is32Bit(env)) { + + // If the tag ends with -64, we want to exclude 32-bit runtimes + // (If the tag ends with -32, it will be filtered later) + int tagLength = search->tagLength; + bool exclude32Bit = false, only32Bit = false; + if (tagLength > 3) { + if (0 == _compareArgument(&search->tag[tagLength - 3], 3, L"-64", 3)) { + tagLength -= 3; + exclude32Bit = true; + } else if (0 == _compareArgument(&search->tag[tagLength - 3], 3, L"-32", 3)) { + tagLength -= 3; + only32Bit = true; + } + } + + if (_startsWith(env->tag, -1, search->tag, tagLength)) { + if (exclude32Bit && _is32Bit(env)) { debug(L"# Excluding %s/%s because it looks like 32bit\n", env->company, env->tag); - } else if (search->only32Bit && !_is32Bit(env)) { + } else if (only32Bit && !_is32Bit(env)) { debug(L"# Excluding %s/%s because it doesn't look 32bit\n", env->company, env->tag); } else { *best = env; diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 5821c3d9e4d8600..39939a7ba983450 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -129,6 +129,7 @@ + @@ -199,6 +200,7 @@ + @@ -423,6 +425,10 @@ + + + + diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index b657f56e28f248b..96ab2f2a4aac7d2 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -85,6 +85,9 @@ Source Files + + Source Files + Source Files @@ -184,6 +187,9 @@ Source Files + + Source Files + Source Files diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 23bb5ec85274aef..b7d40c8cdc30eb3 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -107,6 +107,10 @@ {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} false + + {885d4898-d08d-4091-9c40-c700cfe3fc5a} + false + diff --git a/PCbuild/_wmi.vcxproj b/PCbuild/_wmi.vcxproj new file mode 100644 index 000000000000000..c1914a3fa5a1bff --- /dev/null +++ b/PCbuild/_wmi.vcxproj @@ -0,0 +1,119 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + PGInstrument + ARM + + + PGInstrument + ARM64 + + + PGInstrument + Win32 + + + PGInstrument + x64 + + + PGUpdate + ARM + + + PGUpdate + ARM64 + + + PGUpdate + Win32 + + + PGUpdate + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {54B1431F-B86B-4ACB-B28C-88BCF93191D8} + _wmi + Win32Proj + false + + + + + DynamicLibrary + NotSet + + + + .pyd + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + + + + /std:c++20 %(AdditionalOptions) + + + wbemuuid.lib;propsys.lib;%(AdditionalDependencies) + ole32.dll + + + + + + + + + + + {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} + false + + + + + + \ No newline at end of file diff --git a/PCbuild/_wmi.vcxproj.filters b/PCbuild/_wmi.vcxproj.filters new file mode 100644 index 000000000000000..fa8046237a0b715 --- /dev/null +++ b/PCbuild/_wmi.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {4fa4dbfa-e069-4ab4-86a6-ad389b2ec407} + + + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index d29344517988583..cd211f13e355e5c 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -53,7 +53,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.2 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1n +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1q set libraries=%libraries% sqlite-3.38.4.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.1 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.1 @@ -77,7 +77,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.2 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1n +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1q if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.1 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 2ba0627b8336952..d9e4d981aa2189b 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -64,7 +64,7 @@ - + @@ -125,6 +125,12 @@ StopOnFirstFailure="false" Condition="%(CleanTarget) != ''" Targets="%(CleanTarget)" /> + @@ -140,6 +146,12 @@ StopOnFirstFailure="false" Condition="%(CleanAllTarget) != ''" Targets="%(CleanAllTarget)" /> + diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index 3629a8508a3a609..9f374abd152b175 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -108,6 +108,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw_uwp", "pythonw_uwp. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_uuid", "_uuid.vcxproj", "{CB435430-EBB1-478B-8F4E-C256F6838F55}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_wmi", "_wmi.vcxproj", "{54B1431F-B86B-4ACB-B28C-88BCF93191D8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -1503,6 +1505,38 @@ Global {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|Win32.Build.0 = Release|Win32 {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.ActiveCfg = Release|x64 {CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.Build.0 = Release|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|ARM.ActiveCfg = Debug|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|ARM.Build.0 = Debug|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|ARM64.Build.0 = Debug|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|Win32.Build.0 = Debug|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|x64.ActiveCfg = Debug|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Debug|x64.Build.0 = Debug|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|ARM.Build.0 = PGInstrument|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGInstrument|x64.Build.0 = PGInstrument|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|ARM.Build.0 = PGUpdate|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.PGUpdate|x64.Build.0 = PGUpdate|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|ARM.ActiveCfg = Release|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|ARM.Build.0 = Release|ARM + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|ARM64.ActiveCfg = Release|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|ARM64.Build.0 = Release|ARM64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|Win32.ActiveCfg = Release|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|Win32.Build.0 = Release|Win32 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|x64.ActiveCfg = Release|x64 + {54B1431F-B86B-4ACB-B28C-88BCF93191D8}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PCbuild/python.props b/PCbuild/python.props index 7f10e7c45ef7b70..efcb480976b6a2d 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -67,8 +67,8 @@ $(ExternalsDir)libffi-3.4.2\ $(ExternalsDir)libffi-3.4.2\$(ArchName)\ $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1n\ - $(ExternalsDir)openssl-bin-1.1.1n\$(ArchName)\ + $(ExternalsDir)openssl-1.1.1q\ + $(ExternalsDir)openssl-bin-1.1.1q\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.2.12\ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 3ff4be518724852..ff17304032cdedd 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -327,7 +327,6 @@ - @@ -430,6 +429,7 @@ + @@ -502,6 +502,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 64d248dfafd81ee..7d7fe7267c8ff05 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -312,9 +312,6 @@ Python - - Python - Include @@ -926,6 +923,9 @@ Objects + + Objects + Objects @@ -1097,6 +1097,9 @@ Python + + Python + Modules diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index e4cad75189c9722..c536fac94cc6806 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -168,7 +168,7 @@ _lzma Homepage: https://tukaani.org/xz/ _ssl - Python wrapper for version 1.1.1k of the OpenSSL secure sockets + Python wrapper for version 1.1.1q of the OpenSSL secure sockets library, which is downloaded from our binaries repository at https://github.com/python/cpython-bin-deps. diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets index 9073bb6ab2bd69d..3938b66678eee05 100644 --- a/PCbuild/regen.targets +++ b/PCbuild/regen.targets @@ -82,9 +82,16 @@ WorkingDirectory="$(PySourcePath)" /> + + + + + + DependsOnTargets="_TouchRegenSources;_RegenPegen;_RegenAST_H;_RegenOpcodes;_RegenTokens;_RegenKeywords;_RegenGlobalObjects"> diff --git a/Parser/parser.c b/Parser/parser.c index c9366d59923b825..bec51fe4a90362e 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -6970,7 +6970,7 @@ try_stmt_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_TryStar ( b , ex , el , f , EXTRA ); + _res = CHECK_VERSION ( stmt_ty , 11 , "Exception groups are" , _PyAST_TryStar ( b , ex , el , f , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; diff --git a/Parser/pegen.c b/Parser/pegen.c index 31e3ec05a105304..a5d123da51296c1 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -1,5 +1,6 @@ #include #include "pycore_ast.h" // _PyAST_Validate(), +#include "pycore_pystate.h" // _PyThreadState_GET() #include #include "tokenizer.h" @@ -645,6 +646,28 @@ _PyPegen_number_token(Parser *p) if (c == NULL) { p->error_indicator = 1; + PyThreadState *tstate = _PyThreadState_GET(); + // The only way a ValueError should happen in _this_ code is via + // PyLong_FromString hitting a length limit. + if (tstate->curexc_type == PyExc_ValueError && + tstate->curexc_value != NULL) { + PyObject *type, *value, *tb; + // This acts as PyErr_Clear() as we're replacing curexc. + PyErr_Fetch(&type, &value, &tb); + Py_XDECREF(tb); + Py_DECREF(type); + /* Intentionally omitting columns to avoid a wall of 1000s of '^'s + * on the error message. Nobody is going to overlook their huge + * numeric literal once given the line. */ + RAISE_ERROR_KNOWN_LOCATION( + p, PyExc_SyntaxError, + t->lineno, -1 /* col_offset */, + t->end_lineno, -1 /* end_col_offset */, + "%S - Consider hexadecimal for huge integer literals " + "to avoid decimal conversion limits.", + value); + Py_DECREF(value); + } return NULL; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index f2606f17d14630e..d16af89df555171 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -489,25 +489,59 @@ static void fp_ungetc(int c, struct tok_state *tok) { /* Check whether the characters at s start a valid UTF-8 sequence. Return the number of characters forming - the sequence if yes, 0 if not. */ -static int valid_utf8(const unsigned char* s) + the sequence if yes, 0 if not. The special cases match + those in stringlib/codecs.h:utf8_decode. +*/ +static int +valid_utf8(const unsigned char* s) { int expected = 0; int length; - if (*s < 0x80) + if (*s < 0x80) { /* single-byte code */ return 1; - if (*s < 0xc0) - /* following byte */ - return 0; - if (*s < 0xE0) + } + else if (*s < 0xE0) { + /* \xC2\x80-\xDF\xBF -- 0080-07FF */ + if (*s < 0xC2) { + /* invalid sequence + \x80-\xBF -- continuation byte + \xC0-\xC1 -- fake 0000-007F */ + return 0; + } expected = 1; - else if (*s < 0xF0) + } + else if (*s < 0xF0) { + /* \xE0\xA0\x80-\xEF\xBF\xBF -- 0800-FFFF */ + if (*s == 0xE0 && *(s + 1) < 0xA0) { + /* invalid sequence + \xE0\x80\x80-\xE0\x9F\xBF -- fake 0000-0800 */ + return 0; + } + else if (*s == 0xED && *(s + 1) >= 0xA0) { + /* Decoding UTF-8 sequences in range \xED\xA0\x80-\xED\xBF\xBF + will result in surrogates in range D800-DFFF. Surrogates are + not valid UTF-8 so they are rejected. + See https://www.unicode.org/versions/Unicode5.2.0/ch03.pdf + (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */ + return 0; + } expected = 2; - else if (*s < 0xF8) + } + else if (*s < 0xF5) { + /* \xF0\x90\x80\x80-\xF4\x8F\xBF\xBF -- 10000-10FFFF */ + if (*(s + 1) < 0x90 ? *s == 0xF0 : *s == 0xF4) { + /* invalid sequence -- one of: + \xF0\x80\x80\x80-\xF0\x8F\xBF\xBF -- fake 0000-FFFF + \xF4\x90\x80\x80- -- 110000- overflow */ + return 0; + } expected = 3; - else + } + else { + /* invalid start byte */ return 0; + } length = expected + 1; for (; expected; expected--) if (s[expected] < 0x80 || s[expected] >= 0xC0) @@ -528,14 +562,12 @@ ensure_utf8(char *line, struct tok_state *tok) } } if (badchar) { - /* Need to add 1 to the line number, since this line - has not been counted, yet. */ PyErr_Format(PyExc_SyntaxError, "Non-UTF-8 code starting with '\\x%.2x' " "in file %U on line %i, " "but no encoding declared; " "see https://peps.python.org/pep-0263/ for details", - badchar, tok->filename, tok->lineno + 1); + badchar, tok->filename, tok->lineno); return 0; } return 1; @@ -1936,6 +1968,8 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end) /* Get rest of string */ while (end_quote_size != quote_size) { c = tok_nextc(tok); + if (tok->done == E_DECODE) + break; if (c == EOF || (quote_size == 1 && c == '\n')) { assert(tok->multi_line_start != NULL); // shift the tok_state's location into diff --git a/Python/ceval.c b/Python/ceval.c index d34d6bfeec0963b..af47e091bc7f0b0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -13,13 +13,11 @@ #include "pycore_ceval.h" // _PyEval_SignalAsyncExc() #include "pycore_code.h" #include "pycore_function.h" -#include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_moduleobject.h" // PyModuleObject #include "pycore_opcode.h" // EXTRA_CASES #include "pycore_pyerrors.h" // _PyErr_Fetch() -#include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_range.h" // _PyRangeIterObject @@ -48,7 +46,7 @@ # error "ceval.c must be build with Py_BUILD_CORE define for best performance" #endif -#ifndef Py_DEBUG +#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) // GH-89279: The MSVC compiler does not inline these static inline functions // in PGO build in _PyEval_EvalFrameDefault(), because this function is over // the limit of PGO, and that limit cannot be configured. @@ -98,6 +96,10 @@ #define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL) #endif +#define HEAD_LOCK(runtime) \ + PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) +#define HEAD_UNLOCK(runtime) \ + PyThread_release_lock((runtime)->interpreters.mutex) /* Forward declarations */ static PyObject *trace_call_function( @@ -152,11 +154,12 @@ lltrace_instruction(_PyInterpreterFrame *frame, static void lltrace_resume_frame(_PyInterpreterFrame *frame) { - PyFunctionObject *f = frame->f_func; - if (f == NULL) { + PyObject *fobj = frame->f_funcobj; + if (fobj == NULL || !PyFunction_Check(fobj)) { printf("\nResuming frame."); return; } + PyFunctionObject *f = (PyFunctionObject *)fobj; PyObject *type, *value, *traceback; PyErr_Fetch(&type, &value, &traceback); PyObject *name = f->func_qualname; @@ -237,582 +240,9 @@ is_tstate_valid(PyThreadState *tstate) #endif -/* This can set eval_breaker to 0 even though gil_drop_request became - 1. We believe this is all right because the eval loop will release - the GIL eventually anyway. */ -static inline void -COMPUTE_EVAL_BREAKER(PyInterpreterState *interp, - struct _ceval_runtime_state *ceval, - struct _ceval_state *ceval2) -{ - _Py_atomic_store_relaxed(&ceval2->eval_breaker, - _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request) - | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending) - && _Py_ThreadCanHandleSignals(interp)) - | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do) - && _Py_ThreadCanHandlePendingCalls()) - | ceval2->pending.async_exc); -} - - -static inline void -SET_GIL_DROP_REQUEST(PyInterpreterState *interp) -{ - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 1); - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); -} - - -static inline void -RESET_GIL_DROP_REQUEST(PyInterpreterState *interp) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); -} - - -static inline void -SIGNAL_PENDING_CALLS(PyInterpreterState *interp) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); -} - - -static inline void -UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); -} - - -static inline void -SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval->signals_pending, 1); - if (force) { - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); - } - else { - /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */ - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); - } -} - - -static inline void -UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - _Py_atomic_store_relaxed(&ceval->signals_pending, 0); - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); -} - - -static inline void -SIGNAL_ASYNC_EXC(PyInterpreterState *interp) -{ - struct _ceval_state *ceval2 = &interp->ceval; - ceval2->pending.async_exc = 1; - _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); -} - - -static inline void -UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp) -{ - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - ceval2->pending.async_exc = 0; - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); -} - - #ifdef HAVE_ERRNO_H #include #endif -#include "ceval_gil.h" - -void _Py_NO_RETURN -_Py_FatalError_TstateNULL(const char *func) -{ - _Py_FatalErrorFunc(func, - "the function must be called with the GIL held, " - "after Python initialization and before Python finalization, " - "but the GIL is released (the current Python thread state is NULL)"); -} - -int -_PyEval_ThreadsInitialized(_PyRuntimeState *runtime) -{ - return gil_created(&runtime->ceval.gil); -} - -int -PyEval_ThreadsInitialized(void) -{ - _PyRuntimeState *runtime = &_PyRuntime; - return _PyEval_ThreadsInitialized(runtime); -} - -PyStatus -_PyEval_InitGIL(PyThreadState *tstate) -{ - if (!_Py_IsMainInterpreter(tstate->interp)) { - /* Currently, the GIL is shared by all interpreters, - and only the main interpreter is responsible to create - and destroy it. */ - return _PyStatus_OK(); - } - - struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil; - assert(!gil_created(gil)); - - PyThread_init_thread(); - create_gil(gil); - - take_gil(tstate); - - assert(gil_created(gil)); - return _PyStatus_OK(); -} - -void -_PyEval_FiniGIL(PyInterpreterState *interp) -{ - if (!_Py_IsMainInterpreter(interp)) { - /* Currently, the GIL is shared by all interpreters, - and only the main interpreter is responsible to create - and destroy it. */ - return; - } - - struct _gil_runtime_state *gil = &interp->runtime->ceval.gil; - if (!gil_created(gil)) { - /* First Py_InitializeFromConfig() call: the GIL doesn't exist - yet: do nothing. */ - return; - } - - destroy_gil(gil); - assert(!gil_created(gil)); -} - -void -PyEval_InitThreads(void) -{ - /* Do nothing: kept for backward compatibility */ -} - -void -_PyEval_Fini(void) -{ -#ifdef Py_STATS - _Py_PrintSpecializationStats(1); -#endif -} - -void -PyEval_AcquireLock(void) -{ - _PyRuntimeState *runtime = &_PyRuntime; - PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); - _Py_EnsureTstateNotNULL(tstate); - - take_gil(tstate); -} - -void -PyEval_ReleaseLock(void) -{ - _PyRuntimeState *runtime = &_PyRuntime; - PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); - /* This function must succeed when the current thread state is NULL. - We therefore avoid PyThreadState_Get() which dumps a fatal error - in debug mode. */ - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); -} - -void -_PyEval_ReleaseLock(PyThreadState *tstate) -{ - struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); -} - -void -PyEval_AcquireThread(PyThreadState *tstate) -{ - _Py_EnsureTstateNotNULL(tstate); - - take_gil(tstate); - - struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; - if (_PyThreadState_Swap(gilstate, tstate) != NULL) { - Py_FatalError("non-NULL old thread state"); - } -} - -void -PyEval_ReleaseThread(PyThreadState *tstate) -{ - assert(is_tstate_valid(tstate)); - - _PyRuntimeState *runtime = tstate->interp->runtime; - PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); - if (new_tstate != tstate) { - Py_FatalError("wrong thread state"); - } - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - drop_gil(ceval, ceval2, tstate); -} - -#ifdef HAVE_FORK -/* This function is called from PyOS_AfterFork_Child to destroy all threads - which are not running in the child process, and clear internal locks - which might be held by those threads. */ -PyStatus -_PyEval_ReInitThreads(PyThreadState *tstate) -{ - _PyRuntimeState *runtime = tstate->interp->runtime; - - struct _gil_runtime_state *gil = &runtime->ceval.gil; - if (!gil_created(gil)) { - return _PyStatus_OK(); - } - recreate_gil(gil); - - take_gil(tstate); - - struct _pending_calls *pending = &tstate->interp->ceval.pending; - if (_PyThread_at_fork_reinit(&pending->lock) < 0) { - return _PyStatus_ERR("Can't reinitialize pending calls lock"); - } - - /* Destroy all threads except the current one */ - _PyThreadState_DeleteExcept(runtime, tstate); - return _PyStatus_OK(); -} -#endif - -/* This function is used to signal that async exceptions are waiting to be - raised. */ - -void -_PyEval_SignalAsyncExc(PyInterpreterState *interp) -{ - SIGNAL_ASYNC_EXC(interp); -} - -PyThreadState * -PyEval_SaveThread(void) -{ - _PyRuntimeState *runtime = &_PyRuntime; - PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); - _Py_EnsureTstateNotNULL(tstate); - - struct _ceval_runtime_state *ceval = &runtime->ceval; - struct _ceval_state *ceval2 = &tstate->interp->ceval; - assert(gil_created(&ceval->gil)); - drop_gil(ceval, ceval2, tstate); - return tstate; -} - -void -PyEval_RestoreThread(PyThreadState *tstate) -{ - _Py_EnsureTstateNotNULL(tstate); - - take_gil(tstate); - - struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; - _PyThreadState_Swap(gilstate, tstate); -} - - -/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX - signal handlers or Mac I/O completion routines) can schedule calls - to a function to be called synchronously. - The synchronous function is called with one void* argument. - It should return 0 for success or -1 for failure -- failure should - be accompanied by an exception. - - If registry succeeds, the registry function returns 0; if it fails - (e.g. due to too many pending calls) it returns -1 (without setting - an exception condition). - - Note that because registry may occur from within signal handlers, - or other asynchronous events, calling malloc() is unsafe! - - Any thread can schedule pending calls, but only the main thread - will execute them. - There is no facility to schedule calls to a particular thread, but - that should be easy to change, should that ever be required. In - that case, the static variables here should go into the python - threadstate. -*/ - -void -_PyEval_SignalReceived(PyInterpreterState *interp) -{ -#ifdef MS_WINDOWS - // bpo-42296: On Windows, _PyEval_SignalReceived() is called from a signal - // handler which can run in a thread different than the Python thread, in - // which case _Py_ThreadCanHandleSignals() is wrong. Ignore - // _Py_ThreadCanHandleSignals() and always set eval_breaker to 1. - // - // The next eval_frame_handle_pending() call will call - // _Py_ThreadCanHandleSignals() to recompute eval_breaker. - int force = 1; -#else - int force = 0; -#endif - /* bpo-30703: Function called when the C signal handler of Python gets a - signal. We cannot queue a callback using _PyEval_AddPendingCall() since - that function is not async-signal-safe. */ - SIGNAL_PENDING_SIGNALS(interp, force); -} - -/* Push one item onto the queue while holding the lock. */ -static int -_push_pending_call(struct _pending_calls *pending, - int (*func)(void *), void *arg) -{ - int i = pending->last; - int j = (i + 1) % NPENDINGCALLS; - if (j == pending->first) { - return -1; /* Queue full */ - } - pending->calls[i].func = func; - pending->calls[i].arg = arg; - pending->last = j; - return 0; -} - -/* Pop one item off the queue while holding the lock. */ -static void -_pop_pending_call(struct _pending_calls *pending, - int (**func)(void *), void **arg) -{ - int i = pending->first; - if (i == pending->last) { - return; /* Queue empty */ - } - - *func = pending->calls[i].func; - *arg = pending->calls[i].arg; - pending->first = (i + 1) % NPENDINGCALLS; -} - -/* This implementation is thread-safe. It allows - scheduling to be made from any thread, and even from an executing - callback. - */ - -int -_PyEval_AddPendingCall(PyInterpreterState *interp, - int (*func)(void *), void *arg) -{ - struct _pending_calls *pending = &interp->ceval.pending; - - /* Ensure that _PyEval_InitState() was called - and that _PyEval_FiniState() is not called yet. */ - assert(pending->lock != NULL); - - PyThread_acquire_lock(pending->lock, WAIT_LOCK); - int result = _push_pending_call(pending, func, arg); - PyThread_release_lock(pending->lock); - - /* signal main loop */ - SIGNAL_PENDING_CALLS(interp); - return result; -} - -int -Py_AddPendingCall(int (*func)(void *), void *arg) -{ - /* Best-effort to support subinterpreters and calls with the GIL released. - - First attempt _PyThreadState_GET() since it supports subinterpreters. - - If the GIL is released, _PyThreadState_GET() returns NULL . In this - case, use PyGILState_GetThisThreadState() which works even if the GIL - is released. - - Sadly, PyGILState_GetThisThreadState() doesn't support subinterpreters: - see bpo-10915 and bpo-15751. - - Py_AddPendingCall() doesn't require the caller to hold the GIL. */ - PyThreadState *tstate = _PyThreadState_GET(); - if (tstate == NULL) { - tstate = PyGILState_GetThisThreadState(); - } - - PyInterpreterState *interp; - if (tstate != NULL) { - interp = tstate->interp; - } - else { - /* Last resort: use the main interpreter */ - interp = _PyInterpreterState_Main(); - } - return _PyEval_AddPendingCall(interp, func, arg); -} - -static int -handle_signals(PyThreadState *tstate) -{ - assert(is_tstate_valid(tstate)); - if (!_Py_ThreadCanHandleSignals(tstate->interp)) { - return 0; - } - - UNSIGNAL_PENDING_SIGNALS(tstate->interp); - if (_PyErr_CheckSignalsTstate(tstate) < 0) { - /* On failure, re-schedule a call to handle_signals(). */ - SIGNAL_PENDING_SIGNALS(tstate->interp, 0); - return -1; - } - return 0; -} - -static int -make_pending_calls(PyInterpreterState *interp) -{ - /* only execute pending calls on main thread */ - if (!_Py_ThreadCanHandlePendingCalls()) { - return 0; - } - - /* don't perform recursive pending calls */ - static int busy = 0; - if (busy) { - return 0; - } - busy = 1; - - /* unsignal before starting to call callbacks, so that any callback - added in-between re-signals */ - UNSIGNAL_PENDING_CALLS(interp); - int res = 0; - - /* perform a bounded number of calls, in case of recursion */ - struct _pending_calls *pending = &interp->ceval.pending; - for (int i=0; ilock, WAIT_LOCK); - _pop_pending_call(pending, &func, &arg); - PyThread_release_lock(pending->lock); - - /* having released the lock, perform the callback */ - if (func == NULL) { - break; - } - res = func(arg); - if (res) { - goto error; - } - } - - busy = 0; - return res; - -error: - busy = 0; - SIGNAL_PENDING_CALLS(interp); - return res; -} - -void -_Py_FinishPendingCalls(PyThreadState *tstate) -{ - assert(PyGILState_Check()); - assert(is_tstate_valid(tstate)); - - struct _pending_calls *pending = &tstate->interp->ceval.pending; - - if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) { - return; - } - - if (make_pending_calls(tstate->interp) < 0) { - PyObject *exc, *val, *tb; - _PyErr_Fetch(tstate, &exc, &val, &tb); - PyErr_BadInternalCall(); - _PyErr_ChainExceptions(exc, val, tb); - _PyErr_Print(tstate); - } -} - -/* Py_MakePendingCalls() is a simple wrapper for the sake - of backward-compatibility. */ -int -Py_MakePendingCalls(void) -{ - assert(PyGILState_Check()); - - PyThreadState *tstate = _PyThreadState_GET(); - assert(is_tstate_valid(tstate)); - - /* Python signal handler doesn't really queue a callback: it only signals - that a signal was received, see _PyEval_SignalReceived(). */ - int res = handle_signals(tstate); - if (res != 0) { - return res; - } - - res = make_pending_calls(tstate->interp); - if (res != 0) { - return res; - } - - return 0; -} - -/* The interpreter's recursion limit */ - -void -_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) -{ - _gil_initialize(&ceval->gil); -} - -void -_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock) -{ - struct _pending_calls *pending = &ceval->pending; - assert(pending->lock == NULL); - - pending->lock = pending_lock; -} - -void -_PyEval_FiniState(struct _ceval_state *ceval) -{ - struct _pending_calls *pending = &ceval->pending; - if (pending->lock != NULL) { - PyThread_free_lock(pending->lock); - pending->lock = NULL; - } -} int Py_GetRecursionLimit(void) @@ -1182,71 +612,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } -/* Handle signals, pending calls, GIL drop request - and asynchronous exception */ -static int -eval_frame_handle_pending(PyThreadState *tstate) -{ - _PyRuntimeState * const runtime = &_PyRuntime; - struct _ceval_runtime_state *ceval = &runtime->ceval; - - /* Pending signals */ - if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) { - if (handle_signals(tstate) != 0) { - return -1; - } - } - - /* Pending calls */ - struct _ceval_state *ceval2 = &tstate->interp->ceval; - if (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)) { - if (make_pending_calls(tstate->interp) != 0) { - return -1; - } - } - - /* GIL drop request */ - if (_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)) { - /* Give another thread a chance */ - if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { - Py_FatalError("tstate mix-up"); - } - drop_gil(ceval, ceval2, tstate); - - /* Other threads may run now */ - - take_gil(tstate); - - if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { - Py_FatalError("orphan tstate"); - } - } - - /* Check for asynchronous exception. */ - if (tstate->async_exc != NULL) { - PyObject *exc = tstate->async_exc; - tstate->async_exc = NULL; - UNSIGNAL_ASYNC_EXC(tstate->interp); - _PyErr_SetNone(tstate, exc); - Py_DECREF(exc); - return -1; - } - -#ifdef MS_WINDOWS - // bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a - // different thread than the Python thread, in which case - // _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the - // current Python thread with the correct _Py_ThreadCanHandleSignals() - // value. It prevents to interrupt the eval loop at every instruction if - // the current Python thread cannot handle signals (if - // _Py_ThreadCanHandleSignals() is false). - COMPUTE_EVAL_BREAKER(tstate->interp, ceval, ceval2); -#endif - - return 0; -} - - /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" using gcc's labels-as-values extension @@ -1368,9 +733,15 @@ eval_frame_handle_pending(PyThreadState *tstate) /* Tuple access macros */ #ifndef Py_DEBUG -#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i)) +#define GETITEM(v, i) PyTuple_GET_ITEM((v), (i)) #else -#define GETITEM(v, i) PyTuple_GetItem((v), (i)) +static inline PyObject * +GETITEM(PyObject *v, Py_ssize_t i) { + assert(PyTuple_Check(v)); + assert(i >= 0); + assert(i < PyTuple_GET_SIZE(v)); + return PyTuple_GET_ITEM(v, i); +} #endif /* Code access macros */ @@ -1750,7 +1121,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int * All loops should include a check of the eval breaker. * We also check on return from any builtin function. */ - if (eval_frame_handle_pending(tstate) != 0) { + if (_Py_HandlePending(tstate) != 0) { goto error; } DISPATCH(); @@ -2256,7 +1627,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *sub = TOP(); PyObject *res = PyDict_GetItemWithError(dict, sub); if (res == NULL) { - goto binary_subscr_dict_error; + if (!_PyErr_Occurred(tstate)) { + _PyErr_SetKeyError(sub); + } + goto error; } Py_INCREF(res); STACK_SHRINK(1); @@ -2668,6 +2042,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(YIELD_VALUE) { + // NOTE: It's important that YIELD_VALUE never raises an exception! + // The compiler treats any exception raised here as a failed close() + // or throw() call. assert(oparg == STACK_LEVEL()); assert(frame->is_entry); PyObject *retval = POP(); @@ -2746,6 +2123,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } } + TARGET(CLEANUP_THROW) { + assert(throwflag); + PyObject *exc_value = TOP(); + assert(exc_value && PyExceptionInstance_Check(exc_value)); + if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { + PyObject *value = ((PyStopIterationObject *)exc_value)->value; + Py_INCREF(value); + Py_DECREF(POP()); // The StopIteration. + Py_DECREF(POP()); // The last sent value. + Py_DECREF(POP()); // The delegated sub-iterator. + PUSH(value); + DISPATCH(); + } + Py_INCREF(exc_value); + PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value)); + PyObject *exc_traceback = PyException_GetTraceback(exc_value); + _PyErr_Restore(tstate, exc_type, exc_value, exc_traceback); + goto exception_unwind; + } + TARGET(LOAD_ASSERTION_ERROR) { PyObject *value = PyExc_AssertionError; Py_INCREF(value); @@ -3232,7 +2629,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(COPY_FREE_VARS) { /* Copy closure variables to free variables */ PyCodeObject *co = frame->f_code; - PyObject *closure = frame->f_func->func_closure; + assert(PyFunction_Check(frame->f_funcobj)); + PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure; int offset = co->co_nlocals + co->co_nplaincellvars; assert(oparg == co->co_nfreevars); for (int i = 0; i < oparg; ++i) { @@ -3698,6 +3096,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); PyObject *fget = read_obj(cache->descr); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); @@ -3709,8 +3108,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f); SET_TOP(NULL); - int push_null = !(oparg & 1); - STACK_SHRINK(push_null); + int shrink_stack = !(oparg & 1); + STACK_SHRINK(shrink_stack); new_frame->localsplus[0] = owner; for (int i = 1; i < code->co_nlocalsplus; i++) { new_frame->localsplus[i] = NULL; @@ -3724,6 +3123,44 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto start_frame; } + TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + assert(cframe.use_tracing == 0); + DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); + _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; + PyObject *owner = TOP(); + PyTypeObject *cls = Py_TYPE(owner); + uint32_t type_version = read_u32(cache->type_version); + DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); + assert(type_version != 0); + PyObject *getattribute = read_obj(cache->descr); + assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)getattribute; + PyCodeObject *code = (PyCodeObject *)f->func_code; + DEOPT_IF(((PyCodeObject *)f->func_code)->co_argcount != 2, LOAD_ATTR); + DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); + STAT_INC(LOAD_ATTR, hit); + + PyObject *name = GETITEM(names, oparg >> 1); + Py_INCREF(f); + _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f); + SET_TOP(NULL); + int shrink_stack = !(oparg & 1); + STACK_SHRINK(shrink_stack); + Py_INCREF(name); + new_frame->localsplus[0] = owner; + new_frame->localsplus[1] = name; + for (int i = 2; i < code->co_nlocalsplus; i++) { + new_frame->localsplus[i] = NULL; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + frame->prev_instr = next_instr - 1; + new_frame->previous = frame; + frame = cframe.current_frame = new_frame; + CALL_STAT_INC(inlined_py_calls); + goto start_frame; + } + TARGET(STORE_ATTR_ADAPTIVE) { assert(cframe.use_tracing == 0); _PyAttrCache *cache = (_PyAttrCache *)next_instr; @@ -3876,7 +3313,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(COMPARE_OP_FLOAT_JUMP) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (float ? float) + POP_JUMP_(direction)_IF_(true/false) + // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; int when_to_jump_mask = cache->mask; PyObject *right = TOP(); @@ -3894,23 +3331,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(2); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - assert(opcode == POP_JUMP_FORWARD_IF_FALSE || - opcode == POP_JUMP_BACKWARD_IF_FALSE || - opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_TRUE); - int jump = (9 << (sign + 1)) & when_to_jump_mask; + assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); + int jump = (1 << (sign + 1)) & when_to_jump_mask; if (!jump) { next_instr++; } - else if (jump >= 8) { - assert(opcode == POP_JUMP_BACKWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_FALSE); - JUMPBY(1 - oparg); - CHECK_EVAL_BREAKER(); - } else { - assert(opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_FORWARD_IF_FALSE); JUMPBY(1 + oparg); } NOTRACE_DISPATCH(); @@ -3918,7 +3344,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(COMPARE_OP_INT_JUMP) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (int ? int) + POP_JUMP_(direction)_IF_(true/false) + // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false) _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; int when_to_jump_mask = cache->mask; PyObject *right = TOP(); @@ -3937,23 +3363,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(2); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - assert(opcode == POP_JUMP_FORWARD_IF_FALSE || - opcode == POP_JUMP_BACKWARD_IF_FALSE || - opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_TRUE); - int jump = (9 << (sign + 1)) & when_to_jump_mask; + assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); + int jump = (1 << (sign + 1)) & when_to_jump_mask; if (!jump) { next_instr++; } - else if (jump >= 8) { - assert(opcode == POP_JUMP_BACKWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_FALSE); - JUMPBY(1 - oparg); - CHECK_EVAL_BREAKER(); - } else { - assert(opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_FORWARD_IF_FALSE); JUMPBY(1 + oparg); } NOTRACE_DISPATCH(); @@ -3961,9 +3376,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(COMPARE_OP_STR_JUMP) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_(direction)_IF_(true/false) + // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false) _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; - int when_to_jump_mask = cache->mask; + int invert = cache->mask; PyObject *right = TOP(); PyObject *left = SECOND(); DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); @@ -3976,28 +3391,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(oparg == Py_EQ || oparg == Py_NE); JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP); NEXTOPARG(); - assert(opcode == POP_JUMP_FORWARD_IF_FALSE || - opcode == POP_JUMP_BACKWARD_IF_FALSE || - opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_TRUE); + assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); STACK_SHRINK(2); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); assert(res == 0 || res == 1); - int sign = 1 - res; - int jump = (9 << (sign + 1)) & when_to_jump_mask; + assert(invert == 0 || invert == 1); + int jump = res ^ invert; if (!jump) { next_instr++; } - else if (jump >= 8) { - assert(opcode == POP_JUMP_BACKWARD_IF_TRUE || - opcode == POP_JUMP_BACKWARD_IF_FALSE); - JUMPBY(1 - oparg); - CHECK_EVAL_BREAKER(); - } else { - assert(opcode == POP_JUMP_FORWARD_IF_TRUE || - opcode == POP_JUMP_FORWARD_IF_FALSE); JUMPBY(1 + oparg); } NOTRACE_DISPATCH(); @@ -4144,34 +3548,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK); } - TARGET(POP_JUMP_BACKWARD_IF_FALSE) { - PREDICTED(POP_JUMP_BACKWARD_IF_FALSE); - PyObject *cond = POP(); - if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - DISPATCH(); - } - if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); - } - int err = PyObject_IsTrue(cond); - Py_DECREF(cond); - if (err > 0) - ; - else if (err == 0) { - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - } - else - goto error; - DISPATCH(); - } - - TARGET(POP_JUMP_FORWARD_IF_FALSE) { - PREDICTED(POP_JUMP_FORWARD_IF_FALSE); + TARGET(POP_JUMP_IF_FALSE) { + PREDICTED(POP_JUMP_IF_FALSE); PyObject *cond = POP(); if (Py_IsTrue(cond)) { _Py_DECREF_NO_DEALLOC(cond); @@ -4194,32 +3572,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(POP_JUMP_BACKWARD_IF_TRUE) { - PyObject *cond = POP(); - if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - DISPATCH(); - } - if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); - } - int err = PyObject_IsTrue(cond); - Py_DECREF(cond); - if (err > 0) { - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - } - else if (err == 0) - ; - else - goto error; - DISPATCH(); - } - - TARGET(POP_JUMP_FORWARD_IF_TRUE) { + TARGET(POP_JUMP_IF_TRUE) { PyObject *cond = POP(); if (Py_IsFalse(cond)) { _Py_DECREF_NO_DEALLOC(cond); @@ -4242,19 +3595,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(POP_JUMP_BACKWARD_IF_NOT_NONE) { - PyObject *value = POP(); - if (!Py_IsNone(value)) { - Py_DECREF(value); - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); - } - _Py_DECREF_NO_DEALLOC(value); - DISPATCH(); - } - - TARGET(POP_JUMP_FORWARD_IF_NOT_NONE) { + TARGET(POP_JUMP_IF_NOT_NONE) { PyObject *value = POP(); if (!Py_IsNone(value)) { JUMPBY(oparg); @@ -4263,20 +3604,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(POP_JUMP_BACKWARD_IF_NONE) { - PyObject *value = POP(); - if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - } - else { - Py_DECREF(value); - } - DISPATCH(); - } - - TARGET(POP_JUMP_FORWARD_IF_NONE) { + TARGET(POP_JUMP_IF_NONE) { PyObject *value = POP(); if (Py_IsNone(value)) { _Py_DECREF_NO_DEALLOC(value); @@ -4403,8 +3731,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *res = match ? Py_True : Py_False; Py_INCREF(res); PUSH(res); - PREDICT(POP_JUMP_FORWARD_IF_FALSE); - PREDICT(POP_JUMP_BACKWARD_IF_FALSE); + PREDICT(POP_JUMP_IF_FALSE); DISPATCH(); } @@ -4414,8 +3741,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *res = match ? Py_True : Py_False; Py_INCREF(res); PUSH(res); - PREDICT(POP_JUMP_FORWARD_IF_FALSE); - PREDICT(POP_JUMP_BACKWARD_IF_FALSE); + PREDICT(POP_JUMP_IF_FALSE); DISPATCH(); } @@ -4490,10 +3816,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } _PyErr_Clear(tstate); } - iterator_exhausted_no_error: /* iterator ended normally */ - assert(!_PyErr_Occurred(tstate)); - Py_DECREF(POP()); + STACK_SHRINK(1); + Py_DECREF(iter); JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); DISPATCH(); } @@ -4519,19 +3844,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DEOPT_IF(Py_TYPE(it) != &PyListIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); PyListObject *seq = it->it_seq; - if (seq == NULL) { - goto iterator_exhausted_no_error; - } - if (it->it_index < PyList_GET_SIZE(seq)) { - PyObject *next = PyList_GET_ITEM(seq, it->it_index++); - Py_INCREF(next); - PUSH(next); - JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); - NOTRACE_DISPATCH(); + if (seq) { + if (it->it_index < PyList_GET_SIZE(seq)) { + PyObject *next = PyList_GET_ITEM(seq, it->it_index++); + Py_INCREF(next); + PUSH(next); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER); + NOTRACE_DISPATCH(); + } + it->it_seq = NULL; + Py_DECREF(seq); } - it->it_seq = NULL; - Py_DECREF(seq); - goto iterator_exhausted_no_error; + STACK_SHRINK(1); + Py_DECREF(it); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); + NOTRACE_DISPATCH(); } TARGET(FOR_ITER_RANGE) { @@ -4542,7 +3869,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; assert(_PyOpcode_Deopt[_Py_OPCODE(next)] == STORE_FAST); if (r->index >= r->len) { - goto iterator_exhausted_no_error; + STACK_SHRINK(1); + Py_DECREF(r); + JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg); + NOTRACE_DISPATCH(); } long value = (long)(r->start + (unsigned long)(r->index++) * r->step); @@ -5471,7 +4801,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(RETURN_GENERATOR) { - PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(frame->f_func); + assert(PyFunction_Check(frame->f_funcobj)); + PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; + PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); if (gen == NULL) { goto error; } @@ -5493,7 +4825,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int /* Make sure that frame is in a valid state */ frame->stacktop = 0; frame->f_locals = NULL; - Py_INCREF(frame->f_func); + Py_INCREF(frame->f_funcobj); Py_INCREF(frame->f_code); /* Restore previous cframe and return. */ tstate->cframe = cframe.previous; @@ -5763,16 +5095,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH_GOTO(); } -binary_subscr_dict_error: - { - PyObject *sub = POP(); - if (!_PyErr_Occurred(tstate)) { - _PyErr_SetKeyError(sub); - } - Py_DECREF(sub); - goto error; - } - unbound_local_error: { format_exc_check_arg(tstate, PyExc_UnboundLocalError, @@ -7033,6 +6355,27 @@ PyEval_SetProfile(Py_tracefunc func, PyObject *arg) } } +void +PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *arg) +{ + PyThreadState *this_tstate = _PyThreadState_GET(); + PyInterpreterState* interp = this_tstate->interp; + + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); + PyThreadState* ts = PyInterpreterState_ThreadHead(interp); + HEAD_UNLOCK(runtime); + + while (ts) { + if (_PyEval_SetProfile(ts, func, arg) < 0) { + _PyErr_WriteUnraisableMsg("in PyEval_SetProfileAllThreads", NULL); + } + HEAD_LOCK(runtime); + ts = PyThreadState_Next(ts); + HEAD_UNLOCK(runtime); + } +} + int _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) { @@ -7086,6 +6429,26 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg) } } +void +PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *arg) +{ + PyThreadState *this_tstate = _PyThreadState_GET(); + PyInterpreterState* interp = this_tstate->interp; + + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); + PyThreadState* ts = PyInterpreterState_ThreadHead(interp); + HEAD_UNLOCK(runtime); + + while (ts) { + if (_PyEval_SetTrace(ts, func, arg) < 0) { + _PyErr_WriteUnraisableMsg("in PyEval_SetTraceAllThreads", NULL); + } + HEAD_LOCK(runtime); + ts = PyThreadState_Next(ts); + HEAD_UNLOCK(runtime); + } +} int _PyEval_SetCoroutineOriginTrackingDepth(int depth) diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c new file mode 100644 index 000000000000000..a67908667667954 --- /dev/null +++ b/Python/ceval_gil.c @@ -0,0 +1,986 @@ + +#include "Python.h" +#include "pycore_atomic.h" // _Py_atomic_int +#include "pycore_ceval.h" // _PyEval_SignalReceived() +#include "pycore_pyerrors.h" // _PyErr_Fetch() +#include "pycore_pylifecycle.h" // _PyErr_Print() +#include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_pymem.h" // _PyMem_IsPtrFreed() + +/* + Notes about the implementation: + + - The GIL is just a boolean variable (locked) whose access is protected + by a mutex (gil_mutex), and whose changes are signalled by a condition + variable (gil_cond). gil_mutex is taken for short periods of time, + and therefore mostly uncontended. + + - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be + able to release the GIL on demand by another thread. A volatile boolean + variable (gil_drop_request) is used for that purpose, which is checked + at every turn of the eval loop. That variable is set after a wait of + `interval` microseconds on `gil_cond` has timed out. + + [Actually, another volatile boolean variable (eval_breaker) is used + which ORs several conditions into one. Volatile booleans are + sufficient as inter-thread signalling means since Python is run + on cache-coherent architectures only.] + + - A thread wanting to take the GIL will first let pass a given amount of + time (`interval` microseconds) before setting gil_drop_request. This + encourages a defined switching period, but doesn't enforce it since + opcodes can take an arbitrary time to execute. + + The `interval` value is available for the user to read and modify + using the Python API `sys.{get,set}switchinterval()`. + + - When a thread releases the GIL and gil_drop_request is set, that thread + ensures that another GIL-awaiting thread gets scheduled. + It does so by waiting on a condition variable (switch_cond) until + the value of last_holder is changed to something else than its + own thread state pointer, indicating that another thread was able to + take the GIL. + + This is meant to prohibit the latency-adverse behaviour on multi-core + machines where one thread would speculatively release the GIL, but still + run and end up being the first to re-acquire it, making the "timeslices" + much longer than expected. + (Note: this mechanism is enabled with FORCE_SWITCHING above) +*/ + +// GH-89279: Force inlining by using a macro. +#if defined(_MSC_VER) && SIZEOF_INT == 4 +#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value))) +#else +#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL) +#endif + +/* This can set eval_breaker to 0 even though gil_drop_request became + 1. We believe this is all right because the eval loop will release + the GIL eventually anyway. */ +static inline void +COMPUTE_EVAL_BREAKER(PyInterpreterState *interp, + struct _ceval_runtime_state *ceval, + struct _ceval_state *ceval2) +{ + _Py_atomic_store_relaxed(&ceval2->eval_breaker, + _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request) + | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending) + && _Py_ThreadCanHandleSignals(interp)) + | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do) + && _Py_ThreadCanHandlePendingCalls()) + | ceval2->pending.async_exc); +} + + +static inline void +SET_GIL_DROP_REQUEST(PyInterpreterState *interp) +{ + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 1); + _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); +} + + +static inline void +RESET_GIL_DROP_REQUEST(PyInterpreterState *interp) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 0); + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); +} + + +static inline void +SIGNAL_PENDING_CALLS(PyInterpreterState *interp) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1); + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); +} + + +static inline void +UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0); + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); +} + + +static inline void +SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->signals_pending, 1); + if (force) { + _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); + } + else { + /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */ + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + } +} + + +static inline void +UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + _Py_atomic_store_relaxed(&ceval->signals_pending, 0); + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); +} + + +static inline void +SIGNAL_ASYNC_EXC(PyInterpreterState *interp) +{ + struct _ceval_state *ceval2 = &interp->ceval; + ceval2->pending.async_exc = 1; + _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1); +} + + +static inline void +UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp) +{ + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + ceval2->pending.async_exc = 0; + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); +} + +#ifndef NDEBUG +/* Ensure that tstate is valid */ +static int +is_tstate_valid(PyThreadState *tstate) +{ + assert(!_PyMem_IsPtrFreed(tstate)); + assert(!_PyMem_IsPtrFreed(tstate->interp)); + return 1; +} +#endif + +/* + * Implementation of the Global Interpreter Lock (GIL). + */ + +#include +#include + +#include "pycore_atomic.h" + + +#include "condvar.h" + +#define MUTEX_INIT(mut) \ + if (PyMUTEX_INIT(&(mut))) { \ + Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); }; +#define MUTEX_FINI(mut) \ + if (PyMUTEX_FINI(&(mut))) { \ + Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); }; +#define MUTEX_LOCK(mut) \ + if (PyMUTEX_LOCK(&(mut))) { \ + Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); }; +#define MUTEX_UNLOCK(mut) \ + if (PyMUTEX_UNLOCK(&(mut))) { \ + Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); }; + +#define COND_INIT(cond) \ + if (PyCOND_INIT(&(cond))) { \ + Py_FatalError("PyCOND_INIT(" #cond ") failed"); }; +#define COND_FINI(cond) \ + if (PyCOND_FINI(&(cond))) { \ + Py_FatalError("PyCOND_FINI(" #cond ") failed"); }; +#define COND_SIGNAL(cond) \ + if (PyCOND_SIGNAL(&(cond))) { \ + Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); }; +#define COND_WAIT(cond, mut) \ + if (PyCOND_WAIT(&(cond), &(mut))) { \ + Py_FatalError("PyCOND_WAIT(" #cond ") failed"); }; +#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ + { \ + int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \ + if (r < 0) \ + Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \ + if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \ + timeout_result = 1; \ + else \ + timeout_result = 0; \ + } \ + + +#define DEFAULT_INTERVAL 5000 + +static void _gil_initialize(struct _gil_runtime_state *gil) +{ + _Py_atomic_int uninitialized = {-1}; + gil->locked = uninitialized; + gil->interval = DEFAULT_INTERVAL; +} + +static int gil_created(struct _gil_runtime_state *gil) +{ + return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0); +} + +static void create_gil(struct _gil_runtime_state *gil) +{ + MUTEX_INIT(gil->mutex); +#ifdef FORCE_SWITCHING + MUTEX_INIT(gil->switch_mutex); +#endif + COND_INIT(gil->cond); +#ifdef FORCE_SWITCHING + COND_INIT(gil->switch_cond); +#endif + _Py_atomic_store_relaxed(&gil->last_holder, 0); + _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked); + _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release); +} + +static void destroy_gil(struct _gil_runtime_state *gil) +{ + /* some pthread-like implementations tie the mutex to the cond + * and must have the cond destroyed first. + */ + COND_FINI(gil->cond); + MUTEX_FINI(gil->mutex); +#ifdef FORCE_SWITCHING + COND_FINI(gil->switch_cond); + MUTEX_FINI(gil->switch_mutex); +#endif + _Py_atomic_store_explicit(&gil->locked, -1, + _Py_memory_order_release); + _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); +} + +#ifdef HAVE_FORK +static void recreate_gil(struct _gil_runtime_state *gil) +{ + _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); + /* XXX should we destroy the old OS resources here? */ + create_gil(gil); +} +#endif + +static void +drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, + PyThreadState *tstate) +{ + struct _gil_runtime_state *gil = &ceval->gil; + if (!_Py_atomic_load_relaxed(&gil->locked)) { + Py_FatalError("drop_gil: GIL is not locked"); + } + + /* tstate is allowed to be NULL (early interpreter init) */ + if (tstate != NULL) { + /* Sub-interpreter support: threads might have been switched + under our feet using PyThreadState_Swap(). Fix the GIL last + holder variable so that our heuristics work. */ + _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate); + } + + MUTEX_LOCK(gil->mutex); + _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1); + _Py_atomic_store_relaxed(&gil->locked, 0); + COND_SIGNAL(gil->cond); + MUTEX_UNLOCK(gil->mutex); + +#ifdef FORCE_SWITCHING + if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) { + MUTEX_LOCK(gil->switch_mutex); + /* Not switched yet => wait */ + if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate) + { + assert(is_tstate_valid(tstate)); + RESET_GIL_DROP_REQUEST(tstate->interp); + /* NOTE: if COND_WAIT does not atomically start waiting when + releasing the mutex, another thread can run through, take + the GIL and drop it again, and reset the condition + before we even had a chance to wait for it. */ + COND_WAIT(gil->switch_cond, gil->switch_mutex); + } + MUTEX_UNLOCK(gil->switch_mutex); + } +#endif +} + + +/* Check if a Python thread must exit immediately, rather than taking the GIL + if Py_Finalize() has been called. + + When this function is called by a daemon thread after Py_Finalize() has been + called, the GIL does no longer exist. + + tstate must be non-NULL. */ +static inline int +tstate_must_exit(PyThreadState *tstate) +{ + /* bpo-39877: Access _PyRuntime directly rather than using + tstate->interp->runtime to support calls from Python daemon threads. + After Py_Finalize() has been called, tstate can be a dangling pointer: + point to PyThreadState freed memory. */ + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + return (finalizing != NULL && finalizing != tstate); +} + + +/* Take the GIL. + + The function saves errno at entry and restores its value at exit. + + tstate must be non-NULL. */ +static void +take_gil(PyThreadState *tstate) +{ + int err = errno; + + assert(tstate != NULL); + + if (tstate_must_exit(tstate)) { + /* bpo-39877: If Py_Finalize() has been called and tstate is not the + thread which called Py_Finalize(), exit immediately the thread. + + This code path can be reached by a daemon thread after Py_Finalize() + completes. In this case, tstate is a dangling pointer: points to + PyThreadState freed memory. */ + PyThread_exit_thread(); + } + + assert(is_tstate_valid(tstate)); + PyInterpreterState *interp = tstate->interp; + struct _ceval_runtime_state *ceval = &interp->runtime->ceval; + struct _ceval_state *ceval2 = &interp->ceval; + struct _gil_runtime_state *gil = &ceval->gil; + + /* Check that _PyEval_InitThreads() was called to create the lock */ + assert(gil_created(gil)); + + MUTEX_LOCK(gil->mutex); + + if (!_Py_atomic_load_relaxed(&gil->locked)) { + goto _ready; + } + + while (_Py_atomic_load_relaxed(&gil->locked)) { + unsigned long saved_switchnum = gil->switch_number; + + unsigned long interval = (gil->interval >= 1 ? gil->interval : 1); + int timed_out = 0; + COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out); + + /* If we timed out and no switch occurred in the meantime, it is time + to ask the GIL-holding thread to drop it. */ + if (timed_out && + _Py_atomic_load_relaxed(&gil->locked) && + gil->switch_number == saved_switchnum) + { + if (tstate_must_exit(tstate)) { + MUTEX_UNLOCK(gil->mutex); + PyThread_exit_thread(); + } + assert(is_tstate_valid(tstate)); + + SET_GIL_DROP_REQUEST(interp); + } + } + +_ready: +#ifdef FORCE_SWITCHING + /* This mutex must be taken before modifying gil->last_holder: + see drop_gil(). */ + MUTEX_LOCK(gil->switch_mutex); +#endif + /* We now hold the GIL */ + _Py_atomic_store_relaxed(&gil->locked, 1); + _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1); + + if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) { + _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate); + ++gil->switch_number; + } + +#ifdef FORCE_SWITCHING + COND_SIGNAL(gil->switch_cond); + MUTEX_UNLOCK(gil->switch_mutex); +#endif + + if (tstate_must_exit(tstate)) { + /* bpo-36475: If Py_Finalize() has been called and tstate is not + the thread which called Py_Finalize(), exit immediately the + thread. + + This code path can be reached by a daemon thread which was waiting + in take_gil() while the main thread called + wait_for_thread_shutdown() from Py_Finalize(). */ + MUTEX_UNLOCK(gil->mutex); + drop_gil(ceval, ceval2, tstate); + PyThread_exit_thread(); + } + assert(is_tstate_valid(tstate)); + + if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) { + RESET_GIL_DROP_REQUEST(interp); + } + else { + /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there + is a pending signal: signal received by another thread which cannot + handle signals. + + Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ + COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); + } + + /* Don't access tstate if the thread must exit */ + if (tstate->async_exc != NULL) { + _PyEval_SignalAsyncExc(tstate->interp); + } + + MUTEX_UNLOCK(gil->mutex); + + errno = err; +} + +void _PyEval_SetSwitchInterval(unsigned long microseconds) +{ + struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; + gil->interval = microseconds; +} + +unsigned long _PyEval_GetSwitchInterval() +{ + struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; + return gil->interval; +} + + +int +_PyEval_ThreadsInitialized(_PyRuntimeState *runtime) +{ + return gil_created(&runtime->ceval.gil); +} + +int +PyEval_ThreadsInitialized(void) +{ + _PyRuntimeState *runtime = &_PyRuntime; + return _PyEval_ThreadsInitialized(runtime); +} + +PyStatus +_PyEval_InitGIL(PyThreadState *tstate) +{ + if (!_Py_IsMainInterpreter(tstate->interp)) { + /* Currently, the GIL is shared by all interpreters, + and only the main interpreter is responsible to create + and destroy it. */ + return _PyStatus_OK(); + } + + struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil; + assert(!gil_created(gil)); + + PyThread_init_thread(); + create_gil(gil); + + take_gil(tstate); + + assert(gil_created(gil)); + return _PyStatus_OK(); +} + +void +_PyEval_FiniGIL(PyInterpreterState *interp) +{ + if (!_Py_IsMainInterpreter(interp)) { + /* Currently, the GIL is shared by all interpreters, + and only the main interpreter is responsible to create + and destroy it. */ + return; + } + + struct _gil_runtime_state *gil = &interp->runtime->ceval.gil; + if (!gil_created(gil)) { + /* First Py_InitializeFromConfig() call: the GIL doesn't exist + yet: do nothing. */ + return; + } + + destroy_gil(gil); + assert(!gil_created(gil)); +} + +void +PyEval_InitThreads(void) +{ + /* Do nothing: kept for backward compatibility */ +} + +void +_PyEval_Fini(void) +{ +#ifdef Py_STATS + _Py_PrintSpecializationStats(1); +#endif +} +void +PyEval_AcquireLock(void) +{ + _PyRuntimeState *runtime = &_PyRuntime; + PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); + _Py_EnsureTstateNotNULL(tstate); + + take_gil(tstate); +} + +void +PyEval_ReleaseLock(void) +{ + _PyRuntimeState *runtime = &_PyRuntime; + PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); + /* This function must succeed when the current thread state is NULL. + We therefore avoid PyThreadState_Get() which dumps a fatal error + in debug mode. */ + struct _ceval_runtime_state *ceval = &runtime->ceval; + struct _ceval_state *ceval2 = &tstate->interp->ceval; + drop_gil(ceval, ceval2, tstate); +} + +void +_PyEval_ReleaseLock(PyThreadState *tstate) +{ + struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; + struct _ceval_state *ceval2 = &tstate->interp->ceval; + drop_gil(ceval, ceval2, tstate); +} + +void +PyEval_AcquireThread(PyThreadState *tstate) +{ + _Py_EnsureTstateNotNULL(tstate); + + take_gil(tstate); + + struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; + if (_PyThreadState_Swap(gilstate, tstate) != NULL) { + Py_FatalError("non-NULL old thread state"); + } +} + +void +PyEval_ReleaseThread(PyThreadState *tstate) +{ + assert(is_tstate_valid(tstate)); + + _PyRuntimeState *runtime = tstate->interp->runtime; + PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); + if (new_tstate != tstate) { + Py_FatalError("wrong thread state"); + } + struct _ceval_runtime_state *ceval = &runtime->ceval; + struct _ceval_state *ceval2 = &tstate->interp->ceval; + drop_gil(ceval, ceval2, tstate); +} + +#ifdef HAVE_FORK +/* This function is called from PyOS_AfterFork_Child to destroy all threads + which are not running in the child process, and clear internal locks + which might be held by those threads. */ +PyStatus +_PyEval_ReInitThreads(PyThreadState *tstate) +{ + _PyRuntimeState *runtime = tstate->interp->runtime; + + struct _gil_runtime_state *gil = &runtime->ceval.gil; + if (!gil_created(gil)) { + return _PyStatus_OK(); + } + recreate_gil(gil); + + take_gil(tstate); + + struct _pending_calls *pending = &tstate->interp->ceval.pending; + if (_PyThread_at_fork_reinit(&pending->lock) < 0) { + return _PyStatus_ERR("Can't reinitialize pending calls lock"); + } + + /* Destroy all threads except the current one */ + _PyThreadState_DeleteExcept(runtime, tstate); + return _PyStatus_OK(); +} +#endif + +/* This function is used to signal that async exceptions are waiting to be + raised. */ + +void +_PyEval_SignalAsyncExc(PyInterpreterState *interp) +{ + SIGNAL_ASYNC_EXC(interp); +} + +PyThreadState * +PyEval_SaveThread(void) +{ + _PyRuntimeState *runtime = &_PyRuntime; + PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); + _Py_EnsureTstateNotNULL(tstate); + + struct _ceval_runtime_state *ceval = &runtime->ceval; + struct _ceval_state *ceval2 = &tstate->interp->ceval; + assert(gil_created(&ceval->gil)); + drop_gil(ceval, ceval2, tstate); + return tstate; +} + +void +PyEval_RestoreThread(PyThreadState *tstate) +{ + _Py_EnsureTstateNotNULL(tstate); + + take_gil(tstate); + + struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; + _PyThreadState_Swap(gilstate, tstate); +} + + +/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX + signal handlers or Mac I/O completion routines) can schedule calls + to a function to be called synchronously. + The synchronous function is called with one void* argument. + It should return 0 for success or -1 for failure -- failure should + be accompanied by an exception. + + If registry succeeds, the registry function returns 0; if it fails + (e.g. due to too many pending calls) it returns -1 (without setting + an exception condition). + + Note that because registry may occur from within signal handlers, + or other asynchronous events, calling malloc() is unsafe! + + Any thread can schedule pending calls, but only the main thread + will execute them. + There is no facility to schedule calls to a particular thread, but + that should be easy to change, should that ever be required. In + that case, the static variables here should go into the python + threadstate. +*/ + +void +_PyEval_SignalReceived(PyInterpreterState *interp) +{ +#ifdef MS_WINDOWS + // bpo-42296: On Windows, _PyEval_SignalReceived() is called from a signal + // handler which can run in a thread different than the Python thread, in + // which case _Py_ThreadCanHandleSignals() is wrong. Ignore + // _Py_ThreadCanHandleSignals() and always set eval_breaker to 1. + // + // The next eval_frame_handle_pending() call will call + // _Py_ThreadCanHandleSignals() to recompute eval_breaker. + int force = 1; +#else + int force = 0; +#endif + /* bpo-30703: Function called when the C signal handler of Python gets a + signal. We cannot queue a callback using _PyEval_AddPendingCall() since + that function is not async-signal-safe. */ + SIGNAL_PENDING_SIGNALS(interp, force); +} + +/* Push one item onto the queue while holding the lock. */ +static int +_push_pending_call(struct _pending_calls *pending, + int (*func)(void *), void *arg) +{ + int i = pending->last; + int j = (i + 1) % NPENDINGCALLS; + if (j == pending->first) { + return -1; /* Queue full */ + } + pending->calls[i].func = func; + pending->calls[i].arg = arg; + pending->last = j; + return 0; +} + +/* Pop one item off the queue while holding the lock. */ +static void +_pop_pending_call(struct _pending_calls *pending, + int (**func)(void *), void **arg) +{ + int i = pending->first; + if (i == pending->last) { + return; /* Queue empty */ + } + + *func = pending->calls[i].func; + *arg = pending->calls[i].arg; + pending->first = (i + 1) % NPENDINGCALLS; +} + +/* This implementation is thread-safe. It allows + scheduling to be made from any thread, and even from an executing + callback. + */ + +int +_PyEval_AddPendingCall(PyInterpreterState *interp, + int (*func)(void *), void *arg) +{ + struct _pending_calls *pending = &interp->ceval.pending; + /* Ensure that _PyEval_InitState() was called + and that _PyEval_FiniState() is not called yet. */ + assert(pending->lock != NULL); + + PyThread_acquire_lock(pending->lock, WAIT_LOCK); + int result = _push_pending_call(pending, func, arg); + PyThread_release_lock(pending->lock); + + /* signal main loop */ + SIGNAL_PENDING_CALLS(interp); + return result; +} + +int +Py_AddPendingCall(int (*func)(void *), void *arg) +{ + /* Best-effort to support subinterpreters and calls with the GIL released. + + First attempt _PyThreadState_GET() since it supports subinterpreters. + + If the GIL is released, _PyThreadState_GET() returns NULL . In this + case, use PyGILState_GetThisThreadState() which works even if the GIL + is released. + + Sadly, PyGILState_GetThisThreadState() doesn't support subinterpreters: + see bpo-10915 and bpo-15751. + + Py_AddPendingCall() doesn't require the caller to hold the GIL. */ + PyThreadState *tstate = _PyThreadState_GET(); + if (tstate == NULL) { + tstate = PyGILState_GetThisThreadState(); + } + + PyInterpreterState *interp; + if (tstate != NULL) { + interp = tstate->interp; + } + else { + /* Last resort: use the main interpreter */ + interp = _PyInterpreterState_Main(); + } + return _PyEval_AddPendingCall(interp, func, arg); +} + +static int +handle_signals(PyThreadState *tstate) +{ + assert(is_tstate_valid(tstate)); + if (!_Py_ThreadCanHandleSignals(tstate->interp)) { + return 0; + } + + UNSIGNAL_PENDING_SIGNALS(tstate->interp); + if (_PyErr_CheckSignalsTstate(tstate) < 0) { + /* On failure, re-schedule a call to handle_signals(). */ + SIGNAL_PENDING_SIGNALS(tstate->interp, 0); + return -1; + } + return 0; +} + +static int +make_pending_calls(PyInterpreterState *interp) +{ + /* only execute pending calls on main thread */ + if (!_Py_ThreadCanHandlePendingCalls()) { + return 0; + } + + /* don't perform recursive pending calls */ + static int busy = 0; + if (busy) { + return 0; + } + busy = 1; + + /* unsignal before starting to call callbacks, so that any callback + added in-between re-signals */ + UNSIGNAL_PENDING_CALLS(interp); + int res = 0; + + /* perform a bounded number of calls, in case of recursion */ + struct _pending_calls *pending = &interp->ceval.pending; + for (int i=0; ilock, WAIT_LOCK); + _pop_pending_call(pending, &func, &arg); + PyThread_release_lock(pending->lock); + + /* having released the lock, perform the callback */ + if (func == NULL) { + break; + } + res = func(arg); + if (res) { + goto error; + } + } + + busy = 0; + return res; + +error: + busy = 0; + SIGNAL_PENDING_CALLS(interp); + return res; +} + +void +_Py_FinishPendingCalls(PyThreadState *tstate) +{ + assert(PyGILState_Check()); + assert(is_tstate_valid(tstate)); + + struct _pending_calls *pending = &tstate->interp->ceval.pending; + + if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) { + return; + } + + if (make_pending_calls(tstate->interp) < 0) { + PyObject *exc, *val, *tb; + _PyErr_Fetch(tstate, &exc, &val, &tb); + PyErr_BadInternalCall(); + _PyErr_ChainExceptions(exc, val, tb); + _PyErr_Print(tstate); + } +} + +/* Py_MakePendingCalls() is a simple wrapper for the sake + of backward-compatibility. */ +int +Py_MakePendingCalls(void) +{ + assert(PyGILState_Check()); + + PyThreadState *tstate = _PyThreadState_GET(); + assert(is_tstate_valid(tstate)); + + /* Python signal handler doesn't really queue a callback: it only signals + that a signal was received, see _PyEval_SignalReceived(). */ + int res = handle_signals(tstate); + if (res != 0) { + return res; + } + + res = make_pending_calls(tstate->interp); + if (res != 0) { + return res; + } + + return 0; +} + +/* The interpreter's recursion limit */ + +void +_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval) +{ + _gil_initialize(&ceval->gil); +} + +void +_PyEval_InitState(struct _ceval_state *ceval, PyThread_type_lock pending_lock) +{ + struct _pending_calls *pending = &ceval->pending; + assert(pending->lock == NULL); + + pending->lock = pending_lock; +} + +void +_PyEval_FiniState(struct _ceval_state *ceval) +{ + struct _pending_calls *pending = &ceval->pending; + if (pending->lock != NULL) { + PyThread_free_lock(pending->lock); + pending->lock = NULL; + } +} + +/* Handle signals, pending calls, GIL drop request + and asynchronous exception */ +int +_Py_HandlePending(PyThreadState *tstate) +{ + _PyRuntimeState * const runtime = &_PyRuntime; + struct _ceval_runtime_state *ceval = &runtime->ceval; + + /* Pending signals */ + if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) { + if (handle_signals(tstate) != 0) { + return -1; + } + } + + /* Pending calls */ + struct _ceval_state *ceval2 = &tstate->interp->ceval; + if (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)) { + if (make_pending_calls(tstate->interp) != 0) { + return -1; + } + } + + /* GIL drop request */ + if (_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)) { + /* Give another thread a chance */ + if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { + Py_FatalError("tstate mix-up"); + } + drop_gil(ceval, ceval2, tstate); + + /* Other threads may run now */ + + take_gil(tstate); + + if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { + Py_FatalError("orphan tstate"); + } + } + + /* Check for asynchronous exception. */ + if (tstate->async_exc != NULL) { + PyObject *exc = tstate->async_exc; + tstate->async_exc = NULL; + UNSIGNAL_ASYNC_EXC(tstate->interp); + _PyErr_SetNone(tstate, exc); + Py_DECREF(exc); + return -1; + } + +#ifdef MS_WINDOWS + // bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a + // different thread than the Python thread, in which case + // _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the + // current Python thread with the correct _Py_ThreadCanHandleSignals() + // value. It prevents to interrupt the eval loop at every instruction if + // the current Python thread cannot handle signals (if + // _Py_ThreadCanHandleSignals() is false). + COMPUTE_EVAL_BREAKER(tstate->interp, ceval, ceval2); +#endif + + return 0; +} + diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h deleted file mode 100644 index 1b2dc7f8e1dc311..000000000000000 --- a/Python/ceval_gil.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Implementation of the Global Interpreter Lock (GIL). - */ - -#include -#include - -#include "pycore_atomic.h" - - -/* - Notes about the implementation: - - - The GIL is just a boolean variable (locked) whose access is protected - by a mutex (gil_mutex), and whose changes are signalled by a condition - variable (gil_cond). gil_mutex is taken for short periods of time, - and therefore mostly uncontended. - - - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be - able to release the GIL on demand by another thread. A volatile boolean - variable (gil_drop_request) is used for that purpose, which is checked - at every turn of the eval loop. That variable is set after a wait of - `interval` microseconds on `gil_cond` has timed out. - - [Actually, another volatile boolean variable (eval_breaker) is used - which ORs several conditions into one. Volatile booleans are - sufficient as inter-thread signalling means since Python is run - on cache-coherent architectures only.] - - - A thread wanting to take the GIL will first let pass a given amount of - time (`interval` microseconds) before setting gil_drop_request. This - encourages a defined switching period, but doesn't enforce it since - opcodes can take an arbitrary time to execute. - - The `interval` value is available for the user to read and modify - using the Python API `sys.{get,set}switchinterval()`. - - - When a thread releases the GIL and gil_drop_request is set, that thread - ensures that another GIL-awaiting thread gets scheduled. - It does so by waiting on a condition variable (switch_cond) until - the value of last_holder is changed to something else than its - own thread state pointer, indicating that another thread was able to - take the GIL. - - This is meant to prohibit the latency-adverse behaviour on multi-core - machines where one thread would speculatively release the GIL, but still - run and end up being the first to re-acquire it, making the "timeslices" - much longer than expected. - (Note: this mechanism is enabled with FORCE_SWITCHING above) -*/ - -#include "condvar.h" - -#define MUTEX_INIT(mut) \ - if (PyMUTEX_INIT(&(mut))) { \ - Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); }; -#define MUTEX_FINI(mut) \ - if (PyMUTEX_FINI(&(mut))) { \ - Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); }; -#define MUTEX_LOCK(mut) \ - if (PyMUTEX_LOCK(&(mut))) { \ - Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); }; -#define MUTEX_UNLOCK(mut) \ - if (PyMUTEX_UNLOCK(&(mut))) { \ - Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); }; - -#define COND_INIT(cond) \ - if (PyCOND_INIT(&(cond))) { \ - Py_FatalError("PyCOND_INIT(" #cond ") failed"); }; -#define COND_FINI(cond) \ - if (PyCOND_FINI(&(cond))) { \ - Py_FatalError("PyCOND_FINI(" #cond ") failed"); }; -#define COND_SIGNAL(cond) \ - if (PyCOND_SIGNAL(&(cond))) { \ - Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); }; -#define COND_WAIT(cond, mut) \ - if (PyCOND_WAIT(&(cond), &(mut))) { \ - Py_FatalError("PyCOND_WAIT(" #cond ") failed"); }; -#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ - { \ - int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \ - if (r < 0) \ - Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \ - if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \ - timeout_result = 1; \ - else \ - timeout_result = 0; \ - } \ - - -#define DEFAULT_INTERVAL 5000 - -static void _gil_initialize(struct _gil_runtime_state *gil) -{ - _Py_atomic_int uninitialized = {-1}; - gil->locked = uninitialized; - gil->interval = DEFAULT_INTERVAL; -} - -static int gil_created(struct _gil_runtime_state *gil) -{ - return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0); -} - -static void create_gil(struct _gil_runtime_state *gil) -{ - MUTEX_INIT(gil->mutex); -#ifdef FORCE_SWITCHING - MUTEX_INIT(gil->switch_mutex); -#endif - COND_INIT(gil->cond); -#ifdef FORCE_SWITCHING - COND_INIT(gil->switch_cond); -#endif - _Py_atomic_store_relaxed(&gil->last_holder, 0); - _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked); - _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release); -} - -static void destroy_gil(struct _gil_runtime_state *gil) -{ - /* some pthread-like implementations tie the mutex to the cond - * and must have the cond destroyed first. - */ - COND_FINI(gil->cond); - MUTEX_FINI(gil->mutex); -#ifdef FORCE_SWITCHING - COND_FINI(gil->switch_cond); - MUTEX_FINI(gil->switch_mutex); -#endif - _Py_atomic_store_explicit(&gil->locked, -1, - _Py_memory_order_release); - _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); -} - -static void recreate_gil(struct _gil_runtime_state *gil) -{ - _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked); - /* XXX should we destroy the old OS resources here? */ - create_gil(gil); -} - -static void -drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2, - PyThreadState *tstate) -{ - struct _gil_runtime_state *gil = &ceval->gil; - if (!_Py_atomic_load_relaxed(&gil->locked)) { - Py_FatalError("drop_gil: GIL is not locked"); - } - - /* tstate is allowed to be NULL (early interpreter init) */ - if (tstate != NULL) { - /* Sub-interpreter support: threads might have been switched - under our feet using PyThreadState_Swap(). Fix the GIL last - holder variable so that our heuristics work. */ - _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate); - } - - MUTEX_LOCK(gil->mutex); - _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1); - _Py_atomic_store_relaxed(&gil->locked, 0); - COND_SIGNAL(gil->cond); - MUTEX_UNLOCK(gil->mutex); - -#ifdef FORCE_SWITCHING - if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) { - MUTEX_LOCK(gil->switch_mutex); - /* Not switched yet => wait */ - if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate) - { - assert(is_tstate_valid(tstate)); - RESET_GIL_DROP_REQUEST(tstate->interp); - /* NOTE: if COND_WAIT does not atomically start waiting when - releasing the mutex, another thread can run through, take - the GIL and drop it again, and reset the condition - before we even had a chance to wait for it. */ - COND_WAIT(gil->switch_cond, gil->switch_mutex); - } - MUTEX_UNLOCK(gil->switch_mutex); - } -#endif -} - - -/* Check if a Python thread must exit immediately, rather than taking the GIL - if Py_Finalize() has been called. - - When this function is called by a daemon thread after Py_Finalize() has been - called, the GIL does no longer exist. - - tstate must be non-NULL. */ -static inline int -tstate_must_exit(PyThreadState *tstate) -{ - /* bpo-39877: Access _PyRuntime directly rather than using - tstate->interp->runtime to support calls from Python daemon threads. - After Py_Finalize() has been called, tstate can be a dangling pointer: - point to PyThreadState freed memory. */ - PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); - return (finalizing != NULL && finalizing != tstate); -} - - -/* Take the GIL. - - The function saves errno at entry and restores its value at exit. - - tstate must be non-NULL. */ -static void -take_gil(PyThreadState *tstate) -{ - int err = errno; - - assert(tstate != NULL); - - if (tstate_must_exit(tstate)) { - /* bpo-39877: If Py_Finalize() has been called and tstate is not the - thread which called Py_Finalize(), exit immediately the thread. - - This code path can be reached by a daemon thread after Py_Finalize() - completes. In this case, tstate is a dangling pointer: points to - PyThreadState freed memory. */ - PyThread_exit_thread(); - } - - assert(is_tstate_valid(tstate)); - PyInterpreterState *interp = tstate->interp; - struct _ceval_runtime_state *ceval = &interp->runtime->ceval; - struct _ceval_state *ceval2 = &interp->ceval; - struct _gil_runtime_state *gil = &ceval->gil; - - /* Check that _PyEval_InitThreads() was called to create the lock */ - assert(gil_created(gil)); - - MUTEX_LOCK(gil->mutex); - - if (!_Py_atomic_load_relaxed(&gil->locked)) { - goto _ready; - } - - while (_Py_atomic_load_relaxed(&gil->locked)) { - unsigned long saved_switchnum = gil->switch_number; - - unsigned long interval = (gil->interval >= 1 ? gil->interval : 1); - int timed_out = 0; - COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out); - - /* If we timed out and no switch occurred in the meantime, it is time - to ask the GIL-holding thread to drop it. */ - if (timed_out && - _Py_atomic_load_relaxed(&gil->locked) && - gil->switch_number == saved_switchnum) - { - if (tstate_must_exit(tstate)) { - MUTEX_UNLOCK(gil->mutex); - PyThread_exit_thread(); - } - assert(is_tstate_valid(tstate)); - - SET_GIL_DROP_REQUEST(interp); - } - } - -_ready: -#ifdef FORCE_SWITCHING - /* This mutex must be taken before modifying gil->last_holder: - see drop_gil(). */ - MUTEX_LOCK(gil->switch_mutex); -#endif - /* We now hold the GIL */ - _Py_atomic_store_relaxed(&gil->locked, 1); - _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1); - - if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) { - _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate); - ++gil->switch_number; - } - -#ifdef FORCE_SWITCHING - COND_SIGNAL(gil->switch_cond); - MUTEX_UNLOCK(gil->switch_mutex); -#endif - - if (tstate_must_exit(tstate)) { - /* bpo-36475: If Py_Finalize() has been called and tstate is not - the thread which called Py_Finalize(), exit immediately the - thread. - - This code path can be reached by a daemon thread which was waiting - in take_gil() while the main thread called - wait_for_thread_shutdown() from Py_Finalize(). */ - MUTEX_UNLOCK(gil->mutex); - drop_gil(ceval, ceval2, tstate); - PyThread_exit_thread(); - } - assert(is_tstate_valid(tstate)); - - if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) { - RESET_GIL_DROP_REQUEST(interp); - } - else { - /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there - is a pending signal: signal received by another thread which cannot - handle signals. - - Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ - COMPUTE_EVAL_BREAKER(interp, ceval, ceval2); - } - - /* Don't access tstate if the thread must exit */ - if (tstate->async_exc != NULL) { - _PyEval_SignalAsyncExc(tstate->interp); - } - - MUTEX_UNLOCK(gil->mutex); - - errno = err; -} - -void _PyEval_SetSwitchInterval(unsigned long microseconds) -{ - struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; - gil->interval = microseconds; -} - -unsigned long _PyEval_GetSwitchInterval() -{ - struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil; - return gil->interval; -} diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index beaf21c85bcff21..6864b8b0e03b2f8 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -292,6 +292,18 @@ sys_intern(PyObject *module, PyObject *arg) return return_value; } +PyDoc_STRVAR(sys__settraceallthreads__doc__, +"_settraceallthreads($module, arg, /)\n" +"--\n" +"\n" +"Set the global debug tracing function in all running threads belonging to the current interpreter.\n" +"\n" +"It will be called on each function call. See the debugger chapter\n" +"in the library manual."); + +#define SYS__SETTRACEALLTHREADS_METHODDEF \ + {"_settraceallthreads", (PyCFunction)sys__settraceallthreads, METH_O, sys__settraceallthreads__doc__}, + PyDoc_STRVAR(sys_gettrace__doc__, "gettrace($module, /)\n" "--\n" @@ -312,6 +324,18 @@ sys_gettrace(PyObject *module, PyObject *Py_UNUSED(ignored)) return sys_gettrace_impl(module); } +PyDoc_STRVAR(sys__setprofileallthreads__doc__, +"_setprofileallthreads($module, arg, /)\n" +"--\n" +"\n" +"Set the profiling function in all running threads belonging to the current interpreter.\n" +"\n" +"It will be called on each function call and return. See the profiler chapter\n" +"in the library manual."); + +#define SYS__SETPROFILEALLTHREADS_METHODDEF \ + {"_setprofileallthreads", (PyCFunction)sys__setprofileallthreads, METH_O, sys__setprofileallthreads__doc__}, + PyDoc_STRVAR(sys_getprofile__doc__, "getprofile($module, /)\n" "--\n" @@ -721,6 +745,82 @@ sys_mdebug(PyObject *module, PyObject *arg) #endif /* defined(USE_MALLOPT) */ +PyDoc_STRVAR(sys_get_int_max_str_digits__doc__, +"get_int_max_str_digits($module, /)\n" +"--\n" +"\n" +"Set the maximum string digits limit for non-binary int<->str conversions."); + +#define SYS_GET_INT_MAX_STR_DIGITS_METHODDEF \ + {"get_int_max_str_digits", (PyCFunction)sys_get_int_max_str_digits, METH_NOARGS, sys_get_int_max_str_digits__doc__}, + +static PyObject * +sys_get_int_max_str_digits_impl(PyObject *module); + +static PyObject * +sys_get_int_max_str_digits(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return sys_get_int_max_str_digits_impl(module); +} + +PyDoc_STRVAR(sys_set_int_max_str_digits__doc__, +"set_int_max_str_digits($module, /, maxdigits)\n" +"--\n" +"\n" +"Set the maximum string digits limit for non-binary int<->str conversions."); + +#define SYS_SET_INT_MAX_STR_DIGITS_METHODDEF \ + {"set_int_max_str_digits", _PyCFunction_CAST(sys_set_int_max_str_digits), METH_FASTCALL|METH_KEYWORDS, sys_set_int_max_str_digits__doc__}, + +static PyObject * +sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits); + +static PyObject * +sys_set_int_max_str_digits(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(maxdigits), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"maxdigits", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_int_max_str_digits", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int maxdigits; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + maxdigits = _PyLong_AsInt(args[0]); + if (maxdigits == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = sys_set_int_max_str_digits_impl(module, maxdigits); + +exit: + return return_value; +} + PyDoc_STRVAR(sys_getrefcount__doc__, "getrefcount($module, object, /)\n" "--\n" @@ -1127,6 +1227,79 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #endif /* defined(ANDROID_API_LEVEL) */ +PyDoc_STRVAR(sys_activate_stack_trampoline__doc__, +"activate_stack_trampoline($module, backend, /)\n" +"--\n" +"\n" +"Activate the perf profiler trampoline."); + +#define SYS_ACTIVATE_STACK_TRAMPOLINE_METHODDEF \ + {"activate_stack_trampoline", (PyCFunction)sys_activate_stack_trampoline, METH_O, sys_activate_stack_trampoline__doc__}, + +static PyObject * +sys_activate_stack_trampoline_impl(PyObject *module, const char *backend); + +static PyObject * +sys_activate_stack_trampoline(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *backend; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("activate_stack_trampoline", "argument", "str", arg); + goto exit; + } + Py_ssize_t backend_length; + backend = PyUnicode_AsUTF8AndSize(arg, &backend_length); + if (backend == NULL) { + goto exit; + } + if (strlen(backend) != (size_t)backend_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = sys_activate_stack_trampoline_impl(module, backend); + +exit: + return return_value; +} + +PyDoc_STRVAR(sys_deactivate_stack_trampoline__doc__, +"deactivate_stack_trampoline($module, /)\n" +"--\n" +"\n" +"Dectivate the perf profiler trampoline."); + +#define SYS_DEACTIVATE_STACK_TRAMPOLINE_METHODDEF \ + {"deactivate_stack_trampoline", (PyCFunction)sys_deactivate_stack_trampoline, METH_NOARGS, sys_deactivate_stack_trampoline__doc__}, + +static PyObject * +sys_deactivate_stack_trampoline_impl(PyObject *module); + +static PyObject * +sys_deactivate_stack_trampoline(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return sys_deactivate_stack_trampoline_impl(module); +} + +PyDoc_STRVAR(sys_is_stack_trampoline_active__doc__, +"is_stack_trampoline_active($module, /)\n" +"--\n" +"\n" +"Returns *True* if the perf profiler trampoline is active."); + +#define SYS_IS_STACK_TRAMPOLINE_ACTIVE_METHODDEF \ + {"is_stack_trampoline_active", (PyCFunction)sys_is_stack_trampoline_active, METH_NOARGS, sys_is_stack_trampoline_active__doc__}, + +static PyObject * +sys_is_stack_trampoline_active_impl(PyObject *module); + +static PyObject * +sys_is_stack_trampoline_active(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return sys_is_stack_trampoline_active_impl(module); +} + #ifndef SYS_GETWINDOWSVERSION_METHODDEF #define SYS_GETWINDOWSVERSION_METHODDEF #endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */ @@ -1170,4 +1343,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=38446a4c76e2f3b6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=15318cdd96b62b06 input=a9049054013a1b77]*/ diff --git a/Python/compile.c b/Python/compile.c index 3dec7b5edfb5e9f..33a8679fd8888ae 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -96,23 +96,11 @@ #define IS_ASSEMBLER_OPCODE(opcode) \ ((opcode) == JUMP_FORWARD || \ (opcode) == JUMP_BACKWARD || \ - (opcode) == JUMP_BACKWARD_NO_INTERRUPT || \ - (opcode) == POP_JUMP_FORWARD_IF_NONE || \ - (opcode) == POP_JUMP_BACKWARD_IF_NONE || \ - (opcode) == POP_JUMP_FORWARD_IF_NOT_NONE || \ - (opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \ - (opcode) == POP_JUMP_FORWARD_IF_TRUE || \ - (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \ - (opcode) == POP_JUMP_FORWARD_IF_FALSE || \ - (opcode) == POP_JUMP_BACKWARD_IF_FALSE) + (opcode) == JUMP_BACKWARD_NO_INTERRUPT) #define IS_BACKWARDS_JUMP_OPCODE(opcode) \ ((opcode) == JUMP_BACKWARD || \ - (opcode) == JUMP_BACKWARD_NO_INTERRUPT || \ - (opcode) == POP_JUMP_BACKWARD_IF_NONE || \ - (opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \ - (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \ - (opcode) == POP_JUMP_BACKWARD_IF_FALSE) + (opcode) == JUMP_BACKWARD_NO_INTERRUPT) #define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \ ((opcode) == JUMP || \ @@ -291,7 +279,9 @@ typedef struct basicblock_ { static struct instr * basicblock_last_instr(const basicblock *b) { - if (b->b_iused) { + assert(b->b_iused >= 0); + if (b->b_iused > 0) { + assert(b->b_instr != NULL); return &b->b_instr[b->b_iused - 1]; } return NULL; @@ -457,6 +447,7 @@ typedef struct { static int basicblock_next_instr(basicblock *); +static basicblock *cfg_builder_new_block(cfg_builder *g); static int cfg_builder_maybe_start_new_block(cfg_builder *g); static int cfg_builder_addop_i(cfg_builder *g, int opcode, Py_ssize_t oparg, struct location loc); @@ -767,8 +758,20 @@ cfg_builder_check(cfg_builder *g) } } +static int +cfg_builder_init(cfg_builder *g) +{ + g->g_block_list = NULL; + basicblock *block = cfg_builder_new_block(g); + if (block == NULL) + return 0; + g->g_curblock = g->g_entryblock = block; + g->g_current_label = NO_LABEL; + return 1; +} + static void -cfg_builder_free(cfg_builder* g) +cfg_builder_fini(cfg_builder* g) { cfg_builder_check(g); basicblock *b = g->g_block_list; @@ -785,7 +788,7 @@ cfg_builder_free(cfg_builder* g) static void compiler_unit_free(struct compiler_unit *u) { - cfg_builder_free(&u->u_cfg_builder); + cfg_builder_fini(&u->u_cfg_builder); Py_CLEAR(u->u_ste); Py_CLEAR(u->u_name); Py_CLEAR(u->u_qualname); @@ -1131,17 +1134,9 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_IF_FALSE_OR_POP: return jump ? 0 : -1; - case POP_JUMP_BACKWARD_IF_NONE: - case POP_JUMP_FORWARD_IF_NONE: case POP_JUMP_IF_NONE: - case POP_JUMP_BACKWARD_IF_NOT_NONE: - case POP_JUMP_FORWARD_IF_NOT_NONE: case POP_JUMP_IF_NOT_NONE: - case POP_JUMP_FORWARD_IF_FALSE: - case POP_JUMP_BACKWARD_IF_FALSE: case POP_JUMP_IF_FALSE: - case POP_JUMP_FORWARD_IF_TRUE: - case POP_JUMP_BACKWARD_IF_TRUE: case POP_JUMP_IF_TRUE: return -1; @@ -1234,6 +1229,8 @@ stack_effect(int opcode, int oparg, int jump) return 0; case END_ASYNC_FOR: return -2; + case CLEANUP_THROW: + return -2; case FORMAT_VALUE: /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ @@ -1706,7 +1703,6 @@ compiler_enter_scope(struct compiler *c, identifier name, int scope_type, void *key, int lineno) { struct compiler_unit *u; - basicblock *block; u = (struct compiler_unit *)PyObject_Calloc(1, sizeof( struct compiler_unit)); @@ -1784,12 +1780,9 @@ compiler_enter_scope(struct compiler *c, identifier name, c->c_nestlevel++; cfg_builder *g = CFG_BUILDER(c); - g->g_block_list = NULL; - block = cfg_builder_new_block(g); - if (block == NULL) + if (!cfg_builder_init(g)) { return 0; - g->g_curblock = g->g_entryblock = block; - g->g_current_label = NO_LABEL; + } if (u->u_scope_type == COMPILER_SCOPE_MODULE) { c->u->u_loc.lineno = 0; @@ -1946,17 +1939,22 @@ compiler_call_exit_with_nones(struct compiler *c) { static int compiler_add_yield_from(struct compiler *c, int await) { - NEW_JUMP_TARGET_LABEL(c, start); - NEW_JUMP_TARGET_LABEL(c, resume); + NEW_JUMP_TARGET_LABEL(c, send); + NEW_JUMP_TARGET_LABEL(c, fail); NEW_JUMP_TARGET_LABEL(c, exit); - USE_LABEL(c, start); + USE_LABEL(c, send); ADDOP_JUMP(c, SEND, exit); - - USE_LABEL(c, resume); + // Set up a virtual try/except to handle when StopIteration is raised during + // a close or throw call. The only way YIELD_VALUE raises if they do! + ADDOP_JUMP(c, SETUP_FINALLY, fail); ADDOP_I(c, YIELD_VALUE, 0); + ADDOP_NOLINE(c, POP_BLOCK); ADDOP_I(c, RESUME, await ? 3 : 2); - ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); + ADDOP_JUMP(c, JUMP_NO_INTERRUPT, send); + + USE_LABEL(c, fail); + ADDOP(c, CLEANUP_THROW); USE_LABEL(c, exit); return 1; @@ -7077,6 +7075,7 @@ stackdepth(basicblock *entryblock, int code_flags) return -1; } int new_depth = depth + effect; + assert(new_depth >= 0); /* invalid code or bug in stackdepth() */ if (new_depth > maxdepth) { maxdepth = new_depth; } @@ -7152,10 +7151,8 @@ assemble_free(struct assembler *a) static int blocksize(basicblock *b) { - int i; int size = 0; - - for (i = 0; i < b->b_iused; i++) { + for (int i = 0; i < b->b_iused; i++) { size += instr_size(&b->b_instr[i]); } return size; @@ -7380,6 +7377,9 @@ mark_cold(basicblock *entryblock) { return 0; } +static int +remove_redundant_jumps(cfg_builder *g); + static int push_cold_blocks_to_end(cfg_builder *g, int code_flags) { basicblock *entryblock = g->g_entryblock; @@ -7449,6 +7449,12 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) { } assert(b != NULL && b->b_next == NULL); b->b_next = cold_blocks; + + if (cold_blocks != NULL) { + if (remove_redundant_jumps(g) < 0) { + return -1; + } + } return 0; } @@ -7722,63 +7728,91 @@ assemble_emit(struct assembler *a, struct instr *i) return 1; } -static void -normalize_jumps(basicblock *entryblock) +static int +normalize_jumps_in_block(cfg_builder *g, basicblock *b) { + struct instr *last = basicblock_last_instr(b); + if (last == NULL || !is_jump(last)) { + return 0; + } + assert(!IS_ASSEMBLER_OPCODE(last->i_opcode)); + bool is_forward = last->i_target->b_visited == 0; + switch(last->i_opcode) { + case JUMP: + last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD; + return 0; + case JUMP_NO_INTERRUPT: + last->i_opcode = is_forward ? + JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT; + return 0; + } + int reversed_opcode = 0; + switch(last->i_opcode) { + case POP_JUMP_IF_NOT_NONE: + reversed_opcode = POP_JUMP_IF_NONE; + break; + case POP_JUMP_IF_NONE: + reversed_opcode = POP_JUMP_IF_NOT_NONE; + break; + case POP_JUMP_IF_FALSE: + reversed_opcode = POP_JUMP_IF_TRUE; + break; + case POP_JUMP_IF_TRUE: + reversed_opcode = POP_JUMP_IF_FALSE; + break; + case JUMP_IF_TRUE_OR_POP: + case JUMP_IF_FALSE_OR_POP: + if (!is_forward) { + /* As far as we can tell, the compiler never emits + * these jumps with a backwards target. If/when this + * exception is raised, we have found a use case for + * a backwards version of this jump (or to replace + * it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP) + */ + PyErr_Format(PyExc_SystemError, + "unexpected %s jumping backwards", + last->i_opcode == JUMP_IF_TRUE_OR_POP ? + "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP"); + } + return 0; + } + if (is_forward) { + return 0; + } + + /* transform 'conditional jump T' to + * 'reversed_jump b_next' followed by 'jump_backwards T' + */ + + basicblock *target = last->i_target; + basicblock *backwards_jump = cfg_builder_new_block(g); + if (backwards_jump == NULL) { + return -1; + } + basicblock_addop(backwards_jump, JUMP, target->b_label, NO_LOCATION); + backwards_jump->b_instr[0].i_target = target; + last->i_opcode = reversed_opcode; + last->i_target = b->b_next; + + backwards_jump->b_cold = b->b_cold; + backwards_jump->b_next = b->b_next; + b->b_next = backwards_jump; + return 0; +} + +static int +normalize_jumps(cfg_builder *g) { + basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { b->b_visited = 0; } for (basicblock *b = entryblock; b != NULL; b = b->b_next) { b->b_visited = 1; - if (b->b_iused == 0) { - continue; - } - struct instr *last = &b->b_instr[b->b_iused-1]; - assert(!IS_ASSEMBLER_OPCODE(last->i_opcode)); - if (is_jump(last)) { - bool is_forward = last->i_target->b_visited == 0; - switch(last->i_opcode) { - case JUMP: - last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD; - break; - case JUMP_NO_INTERRUPT: - last->i_opcode = is_forward ? - JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT; - break; - case POP_JUMP_IF_NOT_NONE: - last->i_opcode = is_forward ? - POP_JUMP_FORWARD_IF_NOT_NONE : POP_JUMP_BACKWARD_IF_NOT_NONE; - break; - case POP_JUMP_IF_NONE: - last->i_opcode = is_forward ? - POP_JUMP_FORWARD_IF_NONE : POP_JUMP_BACKWARD_IF_NONE; - break; - case POP_JUMP_IF_FALSE: - last->i_opcode = is_forward ? - POP_JUMP_FORWARD_IF_FALSE : POP_JUMP_BACKWARD_IF_FALSE; - break; - case POP_JUMP_IF_TRUE: - last->i_opcode = is_forward ? - POP_JUMP_FORWARD_IF_TRUE : POP_JUMP_BACKWARD_IF_TRUE; - break; - case JUMP_IF_TRUE_OR_POP: - case JUMP_IF_FALSE_OR_POP: - if (!is_forward) { - /* As far as we can tell, the compiler never emits - * these jumps with a backwards target. If/when this - * exception is raised, we have found a use case for - * a backwards version of this jump (or to replace - * it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP) - */ - PyErr_Format(PyExc_SystemError, - "unexpected %s jumping backwards", - last->i_opcode == JUMP_IF_TRUE_OR_POP ? - "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP"); - } - break; - } + if (normalize_jumps_in_block(g, b) < 0) { + return -1; } } + return 0; } static void @@ -7899,8 +7933,8 @@ scan_block_for_local(int target, basicblock *b, bool unsafe_to_start, if (b->b_next && BB_HAS_FALLTHROUGH(b)) { MAYBE_PUSH(b->b_next); } - if (b->b_iused > 0) { - struct instr *last = &b->b_instr[b->b_iused-1]; + struct instr *last = basicblock_last_instr(b); + if (last != NULL) { if (is_jump(last)) { assert(last->i_target != NULL); MAYBE_PUSH(last->i_target); @@ -8213,7 +8247,7 @@ dump_instr(struct instr *i) sprintf(arg, "arg: %d ", i->i_oparg); } if (HAS_TARGET(i->i_opcode)) { - sprintf(arg, "target: %p ", i->i_target); + sprintf(arg, "target: %p [%d] ", i->i_target, i->i_oparg); } fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", i->i_loc.lineno, i->i_opcode, arg, jabs, jrel); @@ -8244,7 +8278,7 @@ static int calculate_jump_targets(basicblock *entryblock); static int -optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache); +optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache); static int trim_unused_consts(basicblock *entryblock, PyObject *consts); @@ -8253,9 +8287,6 @@ trim_unused_consts(basicblock *entryblock, PyObject *consts); static int duplicate_exits_without_lineno(cfg_builder *g); -static int -extend_block(basicblock *bb); - static int * build_cellfixedoffsets(struct compiler *c) { @@ -8389,10 +8420,10 @@ guarantee_lineno_for_exits(basicblock *entryblock, int firstlineno) { int lineno = firstlineno; assert(lineno > 0); for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_iused == 0) { + struct instr *last = basicblock_last_instr(b); + if (last == NULL) { continue; } - struct instr *last = &b->b_instr[b->b_iused-1]; if (last->i_loc.lineno < 0) { if (last->i_opcode == RETURN_VALUE) { for (int i = 0; i < b->b_iused; i++) { @@ -8458,37 +8489,52 @@ static void propagate_line_numbers(basicblock *entryblock); static void -eliminate_empty_basic_blocks(basicblock *entryblock); +eliminate_empty_basic_blocks(cfg_builder *g); +#ifndef NDEBUG +static bool +no_redundant_jumps(cfg_builder *g) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + struct instr *last = basicblock_last_instr(b); + if (last != NULL) { + if (last->i_opcode == JUMP || last->i_opcode == JUMP_NO_INTERRUPT) { + assert(last->i_target != b->b_next); + return false; + } + } + } + return true; +} +#endif static int -remove_redundant_jumps(basicblock *entryblock) { +remove_redundant_jumps(cfg_builder *g) { /* If a non-empty block ends with a jump instruction, check if the next * non-empty block reached through normal flow control is the target * of that jump. If it is, then the jump instruction is redundant and * can be deleted. */ int removed = 0; - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_iused > 0) { - struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; - assert(!IS_ASSEMBLER_OPCODE(b_last_instr->i_opcode)); - if (b_last_instr->i_opcode == JUMP || - b_last_instr->i_opcode == JUMP_NO_INTERRUPT) { - if (b_last_instr->i_target == NULL) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + struct instr *last = basicblock_last_instr(b); + if (last != NULL) { + assert(!IS_ASSEMBLER_OPCODE(last->i_opcode)); + if (last->i_opcode == JUMP || + last->i_opcode == JUMP_NO_INTERRUPT) { + if (last->i_target == NULL) { PyErr_SetString(PyExc_SystemError, "jump with NULL target"); return -1; } - if (b_last_instr->i_target == b->b_next) { + if (last->i_target == b->b_next) { assert(b->b_next->b_iused); - b_last_instr->i_opcode = NOP; + last->i_opcode = NOP; removed++; } } } } if (removed) { - eliminate_empty_basic_blocks(entryblock); + eliminate_empty_basic_blocks(g); } return 0; } @@ -8538,13 +8584,12 @@ assemble(struct compiler *c, int addNone) } cfg_builder *g = CFG_BUILDER(c); - basicblock *entryblock = g->g_entryblock; - assert(entryblock != NULL); + assert(g->g_entryblock != NULL); /* Set firstlineno if it wasn't explicitly set. */ if (!c->u->u_firstlineno) { - if (entryblock->b_instr && entryblock->b_instr->i_loc.lineno) { - c->u->u_firstlineno = entryblock->b_instr->i_loc.lineno; + if (g->g_entryblock->b_instr && g->g_entryblock->b_instr->i_loc.lineno) { + c->u->u_firstlineno = g->g_entryblock->b_instr->i_loc.lineno; } else { c->u->u_firstlineno = 1; @@ -8552,11 +8597,11 @@ assemble(struct compiler *c, int addNone) } // This must be called before fix_cell_offsets(). - if (insert_prefix_instructions(c, entryblock, cellfixedoffsets, nfreevars, code_flags)) { + if (insert_prefix_instructions(c, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) { goto error; } - int numdropped = fix_cell_offsets(c, entryblock, cellfixedoffsets); + int numdropped = fix_cell_offsets(c, g->g_entryblock, cellfixedoffsets); PyMem_Free(cellfixedoffsets); // At this point we're done with it. cellfixedoffsets = NULL; if (numdropped < 0) { @@ -8568,52 +8613,52 @@ assemble(struct compiler *c, int addNone) if (consts == NULL) { goto error; } - if (calculate_jump_targets(entryblock)) { + if (calculate_jump_targets(g->g_entryblock)) { goto error; } - if (optimize_cfg(entryblock, consts, c->c_const_cache)) { + if (optimize_cfg(g, consts, c->c_const_cache)) { goto error; } - if (trim_unused_consts(entryblock, consts)) { + if (trim_unused_consts(g->g_entryblock, consts)) { goto error; } - if (duplicate_exits_without_lineno(g)) { - return NULL; + if (duplicate_exits_without_lineno(g) < 0) { + goto error; } - propagate_line_numbers(entryblock); - guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); + propagate_line_numbers(g->g_entryblock); + guarantee_lineno_for_exits(g->g_entryblock, c->u->u_firstlineno); - int maxdepth = stackdepth(entryblock, code_flags); + int maxdepth = stackdepth(g->g_entryblock, code_flags); if (maxdepth < 0) { goto error; } /* TO DO -- For 3.12, make sure that `maxdepth <= MAX_ALLOWED_STACK_USE` */ - if (label_exception_targets(entryblock)) { + if (label_exception_targets(g->g_entryblock)) { goto error; } - convert_exception_handlers_to_nops(entryblock); + convert_exception_handlers_to_nops(g->g_entryblock); if (push_cold_blocks_to_end(g, code_flags) < 0) { goto error; } - - if (remove_redundant_jumps(entryblock) < 0) { - goto error; - } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { clean_basic_block(b); } /* Order of basic blocks must have been determined by now */ - normalize_jumps(entryblock); + if (normalize_jumps(g) < 0) { + goto error; + } - if (add_checks_for_loads_of_unknown_variables(entryblock, c) < 0) { + if (add_checks_for_loads_of_unknown_variables(g->g_entryblock, c) < 0) { goto error; } + assert(no_redundant_jumps(g)); + /* Can't modify the bytecode after computing jump offsets. */ - assemble_jump_offsets(entryblock); + assemble_jump_offsets(g->g_entryblock); /* Create assembler */ @@ -8621,7 +8666,7 @@ assemble(struct compiler *c, int addNone) goto error; /* Emit code. */ - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { for (int j = 0; j < b->b_iused; j++) if (!assemble_emit(&a, &b->b_instr[j])) goto error; @@ -8629,13 +8674,13 @@ assemble(struct compiler *c, int addNone) /* Emit location info */ a.a_lineno = c->u->u_firstlineno; - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { for (int j = 0; j < b->b_iused; j++) if (!assemble_emit_location(&a, &b->b_instr[j])) goto error; } - if (!assemble_exception_table(&a, entryblock)) { + if (!assemble_exception_table(&a, g->g_entryblock)) { goto error; } if (_PyBytes_Resize(&a.a_except_table, a.a_except_table_off) < 0) { @@ -9200,10 +9245,10 @@ basicblock_has_lineno(const basicblock *bb) { */ static int extend_block(basicblock *bb) { - if (bb->b_iused == 0) { + struct instr *last = basicblock_last_instr(bb); + if (last == NULL) { return 0; } - struct instr *last = &bb->b_instr[bb->b_iused-1]; if (last->i_opcode != JUMP && last->i_opcode != JUMP_FORWARD && last->i_opcode != JUMP_BACKWARD) { @@ -9345,16 +9390,19 @@ mark_reachable(basicblock *entryblock) { } static void -eliminate_empty_basic_blocks(basicblock *entryblock) { +eliminate_empty_basic_blocks(cfg_builder *g) { /* Eliminate empty blocks */ - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { basicblock *next = b->b_next; while (next && next->b_iused == 0) { next = next->b_next; } b->b_next = next; } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + while(g->g_entryblock && g->g_entryblock->b_iused == 0) { + g->g_entryblock = g->g_entryblock->b_next; + } + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { assert(b->b_iused > 0); for (int i = 0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i]; @@ -9381,7 +9429,8 @@ eliminate_empty_basic_blocks(basicblock *entryblock) { static void propagate_line_numbers(basicblock *entryblock) { for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_iused == 0) { + struct instr *last = basicblock_last_instr(b); + if (last == NULL) { continue; } @@ -9400,8 +9449,8 @@ propagate_line_numbers(basicblock *entryblock) { b->b_next->b_instr[0].i_loc = prev_location; } } - if (is_jump(&b->b_instr[b->b_iused-1])) { - basicblock *target = b->b_instr[b->b_iused-1].i_target; + if (is_jump(last)) { + basicblock *target = last->i_target; if (target->b_predecessors == 1) { if (target->b_instr[0].i_loc.lineno < 0) { target->b_instr[0].i_loc = prev_location; @@ -9460,44 +9509,47 @@ calculate_jump_targets(basicblock *entryblock) */ static int -optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) +optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (normalize_basic_block(b)) { return -1; } } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (extend_block(b)) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + if (extend_block(b) < 0) { return -1; } } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (optimize_basic_block(const_cache, b, consts)) { return -1; } clean_basic_block(b); assert(b->b_predecessors == 0); } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (extend_block(b)) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + if (extend_block(b) < 0) { return -1; } } - if (mark_reachable(entryblock)) { + if (mark_reachable(g->g_entryblock)) { return -1; } /* Delete unreachable instructions */ - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (b->b_predecessors == 0) { b->b_iused = 0; } } - eliminate_empty_basic_blocks(entryblock); - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + eliminate_empty_basic_blocks(g); + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { clean_basic_block(b); } + if (remove_redundant_jumps(g) < 0) { + return -1; + } return 0; } @@ -9558,15 +9610,16 @@ duplicate_exits_without_lineno(cfg_builder *g) */ basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_iused > 0 && is_jump(&b->b_instr[b->b_iused-1])) { - basicblock *target = b->b_instr[b->b_iused-1].i_target; + struct instr *last = basicblock_last_instr(b); + if (last != NULL && is_jump(last)) { + basicblock *target = last->i_target; if (is_exit_without_lineno(target) && target->b_predecessors > 1) { basicblock *new_target = copy_basicblock(g, target); if (new_target == NULL) { return -1; } - new_target->b_instr[0].i_loc = b->b_instr[b->b_iused-1].i_loc; - b->b_instr[b->b_iused-1].i_target = new_target; + new_target->b_instr[0].i_loc = last->i_loc; + last->i_target = new_target; target->b_predecessors--; new_target->b_predecessors = 1; new_target->b_next = target->b_next; @@ -9585,14 +9638,166 @@ duplicate_exits_without_lineno(cfg_builder *g) for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) { if (is_exit_without_lineno(b->b_next)) { - assert(b->b_next->b_iused > 0); - b->b_next->b_instr[0].i_loc = b->b_instr[b->b_iused-1].i_loc; + struct instr *last = basicblock_last_instr(b); + assert(last != NULL); + b->b_next->b_instr[0].i_loc = last->i_loc; + } + } + } + return 0; +} + + +/* Access to compiler optimizations for unit tests. + * + * _PyCompile_OptimizeCfg takes an instruction list, constructs + * a CFG, optimizes it and converts back to an instruction list. + * + * An instruction list is a PyList where each item is either + * a tuple describing a single instruction: + * (opcode, oparg, lineno, end_lineno, col, end_col), or + * a jump target label marking the beginning of a basic block. + */ + +static int +instructions_to_cfg(PyObject *instructions, cfg_builder *g) +{ + assert(PyList_Check(instructions)); + + Py_ssize_t instr_size = PyList_GET_SIZE(instructions); + for (Py_ssize_t i = 0; i < instr_size; i++) { + PyObject *item = PyList_GET_ITEM(instructions, i); + if (PyLong_Check(item)) { + int lbl_id = PyLong_AsLong(item); + if (PyErr_Occurred()) { + return -1; + } + if (lbl_id <= 0 || lbl_id > instr_size) { + /* expect label in a reasonable range */ + PyErr_SetString(PyExc_ValueError, "label out of range"); + return -1; + } + jump_target_label lbl = {lbl_id}; + if (cfg_builder_use_label(g, lbl) < 0) { + return -1; + } + } + else { + if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) { + PyErr_SetString(PyExc_ValueError, "expected a 6-tuple"); + return -1; + } + int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0)); + if (PyErr_Occurred()) { + return -1; + } + int oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1)); + if (PyErr_Occurred()) { + return -1; + } + struct location loc; + loc.lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 2)); + if (PyErr_Occurred()) { + return -1; + } + loc.end_lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 3)); + if (PyErr_Occurred()) { + return -1; + } + loc.col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 4)); + if (PyErr_Occurred()) { + return -1; + } + loc.end_col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 5)); + if (PyErr_Occurred()) { + return -1; + } + if (!cfg_builder_addop(g, opcode, oparg, loc)) { + return -1; } } } return 0; } +static PyObject * +cfg_to_instructions(cfg_builder *g) +{ + PyObject *instructions = PyList_New(0); + if (instructions == NULL) { + return NULL; + } + int lbl = 1; + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + b->b_label = lbl++; + } + for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { + PyObject *lbl = PyLong_FromLong(b->b_label); + if (lbl == NULL) { + goto error; + } + if (PyList_Append(instructions, lbl) != 0) { + Py_DECREF(lbl); + goto error; + } + Py_DECREF(lbl); + for (int i = 0; i < b->b_iused; i++) { + struct instr *instr = &b->b_instr[i]; + struct location loc = instr->i_loc; + int arg = HAS_TARGET(instr->i_opcode) ? instr->i_target->b_label : instr->i_oparg; + PyObject *inst_tuple = Py_BuildValue( + "(iiiiii)", instr->i_opcode, arg, + loc.lineno, loc.end_lineno, + loc.col_offset, loc.end_col_offset); + if (inst_tuple == NULL) { + goto error; + } + + if (PyList_Append(instructions, inst_tuple) != 0) { + Py_DECREF(inst_tuple); + goto error; + } + Py_DECREF(inst_tuple); + } + } + + return instructions; +error: + Py_DECREF(instructions); + return NULL; +} + + +PyObject * +_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts) +{ + PyObject *res = NULL; + PyObject *const_cache = NULL; + cfg_builder g; + memset(&g, 0, sizeof(cfg_builder)); + if (cfg_builder_init(&g) < 0) { + goto error; + } + if (instructions_to_cfg(instructions, &g) < 0) { + goto error; + } + const_cache = PyDict_New(); + if (const_cache == NULL) { + goto error; + } + if (calculate_jump_targets(g.g_entryblock)) { + goto error; + } + if (optimize_cfg(&g, consts, const_cache) < 0) { + goto error; + } + res = cfg_to_instructions(&g); +error: + Py_XDECREF(const_cache); + cfg_builder_fini(&g); + return res; +} + /* Retained for API compatibility. * Optimization is now done in optimize_cfg */ diff --git a/Python/frame.c b/Python/frame.c index 7c6705e208f3d37..14464df0a8d5062 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -13,7 +13,7 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg) { Py_VISIT(frame->frame_obj); Py_VISIT(frame->f_locals); - Py_VISIT(frame->f_func); + Py_VISIT(frame->f_funcobj); Py_VISIT(frame->f_code); /* locals */ PyObject **locals = _PyFrame_GetLocalsArray(frame); @@ -114,7 +114,7 @@ _PyFrame_Clear(_PyInterpreterFrame *frame) } Py_XDECREF(frame->frame_obj); Py_XDECREF(frame->f_locals); - Py_DECREF(frame->f_func); + Py_DECREF(frame->f_funcobj); Py_DECREF(frame->f_code); } diff --git a/Python/initconfig.c b/Python/initconfig.c index 70f0363297f3e06..f18ec4068bc4438 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -3,6 +3,7 @@ #include "pycore_getopt.h" // _PyOS_GetOpt() #include "pycore_initconfig.h" // _PyStatus_OK() #include "pycore_interp.h" // _PyInterpreterState.runtime +#include "pycore_long.h" // _PY_LONG_MAX_STR_DIGITS_THRESHOLD #include "pycore_pathconfig.h" // _Py_path_config #include "pycore_pyerrors.h" // _PyErr_Fetch() #include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig() @@ -118,8 +119,17 @@ The following implementation-specific options are available:\n\ files are desired as well as suppressing the extra visual location indicators \n\ when the interpreter displays tracebacks.\n\ \n\ +-X perf: activate support for the Linux \"perf\" profiler by activating the \"perf\"\n\ + trampoline. When this option is activated, the Linux \"perf\" profiler will be \n\ + able to report Python calls. This option is only available on some platforms and will \n\ + do nothing if is not supported on the current system. The default value is \"off\".\n\ +\n\ -X frozen_modules=[on|off]: whether or not frozen modules should be used.\n\ - The default is \"on\" (or \"off\" if you are running a local build)."; + The default is \"on\" (or \"off\" if you are running a local build).\n\ +\n\ +-X int_max_str_digits=number: limit the size of int<->str conversions.\n\ + This helps avoid denial of service attacks when parsing untrusted data.\n\ + The default is sys.int_info.default_max_str_digits. 0 disables."; /* Envvars that don't have equivalent command-line options are listed first */ static const char usage_envvars[] = @@ -139,6 +149,10 @@ static const char usage_envvars[] = " to seed the hashes of str and bytes objects. It can also be set to an\n" " integer in the range [0,4294967295] to get hash values with a\n" " predictable seed.\n" +"PYTHONINTMAXSTRDIGITS: limits the maximum digit characters in an int value\n" +" when converting from a string and when converting an int back to a str.\n" +" A value of 0 disables the limit. Conversions to or from bases 2, 4, 8,\n" +" 16, and 32 are never limited.\n" "PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n" " on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n" " hooks.\n" @@ -745,6 +759,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->use_hash_seed = -1; config->faulthandler = -1; config->tracemalloc = -1; + config->perf_profiling = -1; config->module_search_paths_set = 0; config->parse_argv = 0; config->site_import = -1; @@ -778,6 +793,10 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->code_debug_ranges = 1; } +/* Excluded from public struct PyConfig for backporting reasons. */ +/* default to unconfigured, _PyLong_InitTypes() does the rest */ +int _Py_global_config_int_max_str_digits = -1; + static void config_init_defaults(PyConfig *config) @@ -829,6 +848,7 @@ PyConfig_InitIsolatedConfig(PyConfig *config) config->use_hash_seed = 0; config->faulthandler = 0; config->tracemalloc = 0; + config->perf_profiling = 0; config->safe_path = 1; config->pathconfig_warnings = 0; #ifdef MS_WINDOWS @@ -940,6 +960,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(_install_importlib); COPY_ATTR(faulthandler); COPY_ATTR(tracemalloc); + COPY_ATTR(perf_profiling); COPY_ATTR(import_time); COPY_ATTR(code_debug_ranges); COPY_ATTR(show_ref_count); @@ -1050,6 +1071,7 @@ _PyConfig_AsDict(const PyConfig *config) SET_ITEM_UINT(hash_seed); SET_ITEM_INT(faulthandler); SET_ITEM_INT(tracemalloc); + SET_ITEM_INT(perf_profiling); SET_ITEM_INT(import_time); SET_ITEM_INT(code_debug_ranges); SET_ITEM_INT(show_ref_count); @@ -1331,6 +1353,7 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict) CHECK_VALUE("hash_seed", config->hash_seed <= MAX_HASH_SEED); GET_UINT(faulthandler); GET_UINT(tracemalloc); + GET_UINT(perf_profiling); GET_UINT(import_time); GET_UINT(code_debug_ranges); GET_UINT(show_ref_count); @@ -1687,6 +1710,26 @@ config_read_env_vars(PyConfig *config) return _PyStatus_OK(); } +static PyStatus +config_init_perf_profiling(PyConfig *config) +{ + int active = 0; + const char *env = config_get_env(config, "PYTHONPERFSUPPORT"); + if (env) { + if (_Py_str_to_int(env, &active) != 0) { + active = 0; + } + if (active) { + config->perf_profiling = 1; + } + } + const wchar_t *xoption = config_get_xoption(config, L"perf"); + if (xoption) { + config->perf_profiling = 1; + } + return _PyStatus_OK(); + +} static PyStatus config_init_tracemalloc(PyConfig *config) @@ -1732,6 +1775,48 @@ config_init_tracemalloc(PyConfig *config) return _PyStatus_OK(); } +static PyStatus +config_init_int_max_str_digits(PyConfig *config) +{ + int maxdigits; + int valid = 0; + + const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS"); + if (env) { + if (!_Py_str_to_int(env, &maxdigits)) { + valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)); + } + if (!valid) { +#define STRINGIFY(VAL) _STRINGIFY(VAL) +#define _STRINGIFY(VAL) #VAL + return _PyStatus_ERR( + "PYTHONINTMAXSTRDIGITS: invalid limit; must be >= " + STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD) + " or 0 for unlimited."); + } + _Py_global_config_int_max_str_digits = maxdigits; + } + + const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits"); + if (xoption) { + const wchar_t *sep = wcschr(xoption, L'='); + if (sep) { + if (!config_wstr_to_int(sep + 1, &maxdigits)) { + valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)); + } + } + if (!valid) { + return _PyStatus_ERR( + "-X int_max_str_digits: invalid limit; must be >= " + STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD) + " or 0 for unlimited."); +#undef _STRINGIFY +#undef STRINGIFY + } + _Py_global_config_int_max_str_digits = maxdigits; + } + return _PyStatus_OK(); +} static PyStatus config_init_pycache_prefix(PyConfig *config) @@ -1789,6 +1874,20 @@ config_read_complex_options(PyConfig *config) } } + if (config->perf_profiling < 0) { + status = config_init_perf_profiling(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + if (_Py_global_config_int_max_str_digits < 0) { + status = config_init_int_max_str_digits(config); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + if (config->pycache_prefix == NULL) { status = config_init_pycache_prefix(config); if (_PyStatus_EXCEPTION(status)) { @@ -2104,6 +2203,9 @@ config_read(PyConfig *config, int compute_path_config) if (config->tracemalloc < 0) { config->tracemalloc = 0; } + if (config->perf_profiling < 0) { + config->perf_profiling = 0; + } if (config->use_hash_seed < 0) { config->use_hash_seed = 0; config->hash_seed = 0; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index c9f65edfad1bdcd..c1ff367d4fd38df 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -54,38 +54,38 @@ static void *opcode_targets[256] = { &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_CLEANUP_THROW, &&TARGET_CALL_NO_KW_TYPE_1, &&TARGET_COMPARE_OP_ADAPTIVE, &&TARGET_COMPARE_OP_FLOAT_JUMP, &&TARGET_COMPARE_OP_INT_JUMP, - &&TARGET_COMPARE_OP_STR_JUMP, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_COMPARE_OP_STR_JUMP, &&TARGET_EXTENDED_ARG_QUICK, &&TARGET_FOR_ITER_ADAPTIVE, &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_JUMP_BACKWARD_QUICK, - &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, + &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_CLASS, - &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, + &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, + &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_PROPERTY, &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, - &&TARGET_LOAD_ATTR_METHOD_NO_DICT, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, - &&TARGET_LOAD_ATTR_METHOD_WITH_DICT, + &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, &&TARGET_ASYNC_GEN_WRAP, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, @@ -112,23 +112,23 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, - &&TARGET_POP_JUMP_FORWARD_IF_FALSE, - &&TARGET_POP_JUMP_FORWARD_IF_TRUE, + &&TARGET_LOAD_ATTR_METHOD_NO_DICT, + &&TARGET_POP_JUMP_IF_FALSE, + &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_LOAD_GLOBAL, &&TARGET_IS_OP, &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_LOAD_ATTR_METHOD_WITH_DICT, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, &&TARGET_LOAD_FAST_CHECK, - &&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE, - &&TARGET_POP_JUMP_FORWARD_IF_NONE, + &&TARGET_POP_JUMP_IF_NOT_NONE, + &&TARGET_POP_JUMP_IF_NONE, &&TARGET_RAISE_VARARGS, &&TARGET_GET_AWAITABLE, &&TARGET_MAKE_FUNCTION, @@ -140,9 +140,9 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,30 +152,28 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_RESUME_QUICK, - &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, - &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_CALL, &&TARGET_KW_NAMES, - &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, - &&TARGET_POP_JUMP_BACKWARD_IF_NONE, - &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, - &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, + &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, @@ -254,5 +252,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 11a45800533e014..8ce6d71651c10b8 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -787,6 +787,9 @@ pycore_init_builtins(PyThreadState *tstate) PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append)); assert(list_append); interp->callable_cache.list_append = list_append; + PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__)); + assert(object__getattribute__); + interp->callable_cache.object__getattribute__ = object__getattribute__; if (_PyBuiltins_AddExceptions(bimod) < 0) { return _PyStatus_ERR("failed to add exceptions to builtins"); @@ -1146,6 +1149,16 @@ init_interp_main(PyThreadState *tstate) if (_PyTraceMalloc_Init(config->tracemalloc) < 0) { return _PyStatus_ERR("can't initialize tracemalloc"); } + + +#ifdef PY_HAVE_PERF_TRAMPOLINE + if (config->perf_profiling) { + if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 || + _PyPerfTrampoline_Init(config->perf_profiling) < 0) { + return _PyStatus_ERR("can't initialize the perf trampoline"); + } + } +#endif } status = init_sys_streams(tstate); @@ -1720,6 +1733,7 @@ finalize_interp_clear(PyThreadState *tstate) _PyArg_Fini(); _Py_ClearFileSystemEncoding(); _Py_Deepfreeze_Fini(); + _PyPerfTrampoline_Fini(); } finalize_interp_types(tstate->interp); diff --git a/Python/pystate.c b/Python/pystate.c index 642d680ba20b1f2..1c96f4f75f29a6d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -810,7 +810,15 @@ new_threadstate(PyInterpreterState *interp) { PyThreadState *tstate; _PyRuntimeState *runtime = interp->runtime; - + // We don't need to allocate a thread state for the main interpreter + // (the common case), but doing it later for the other case revealed a + // reentrancy problem (deadlock). So for now we always allocate before + // taking the interpreters lock. See GH-96071. + PyThreadState *new_tstate = alloc_threadstate(); + int used_newtstate; + if (new_tstate == NULL) { + return NULL; + } /* We serialize concurrent creation to protect global state. */ HEAD_LOCK(runtime); @@ -822,18 +830,15 @@ new_threadstate(PyInterpreterState *interp) if (old_head == NULL) { // It's the interpreter's initial thread state. assert(id == 1); - + used_newtstate = 0; tstate = &interp->_initial_thread; } else { // Every valid interpreter must have at least one thread. assert(id > 1); assert(old_head->prev == NULL); - - tstate = alloc_threadstate(); - if (tstate == NULL) { - goto error; - } + used_newtstate = 1; + tstate = new_tstate; // Set to _PyThreadState_INIT. memcpy(tstate, &initial._main_interpreter._initial_thread, @@ -844,11 +849,11 @@ new_threadstate(PyInterpreterState *interp) init_threadstate(tstate, interp, id, old_head); HEAD_UNLOCK(runtime); + if (!used_newtstate) { + // Must be called with lock unlocked to avoid re-entrancy deadlock. + PyMem_RawFree(new_tstate); + } return tstate; - -error: - HEAD_UNLOCK(runtime); - return NULL; } PyThreadState * @@ -2190,15 +2195,12 @@ _PyInterpreterFrame * _PyThreadState_PushFrame(PyThreadState *tstate, size_t size) { assert(size < INT_MAX/sizeof(PyObject *)); - PyObject **base = tstate->datastack_top; - PyObject **top = base + size; - if (top >= tstate->datastack_limit) { - base = push_chunk(tstate, (int)size); - } - else { - tstate->datastack_top = top; + if (_PyThreadState_HasStackSpace(tstate, (int)size)) { + _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top; + tstate->datastack_top += size; + return res; } - return (_PyInterpreterFrame *)base; + return (_PyInterpreterFrame *)push_chunk(tstate, (int)size); } void diff --git a/Python/specialize.c b/Python/specialize.c index d5877a191a10cda..299adf34528a587 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -362,6 +362,8 @@ miss_counter_start(void) { #define SPEC_FAIL_OUT_OF_RANGE 4 #define SPEC_FAIL_EXPECTED_ERROR 5 #define SPEC_FAIL_WRONG_NUMBER_ARGUMENTS 6 +#define SPEC_FAIL_NOT_PY_FUNCTION 7 + #define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18 @@ -387,6 +389,7 @@ miss_counter_start(void) { #define SPEC_FAIL_ATTR_HAS_MANAGED_DICT 25 #define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26 #define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27 +#define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28 /* Binary subscr and store subscr */ @@ -498,6 +501,9 @@ miss_counter_start(void) { #define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 8 #define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 9 +static int function_kind(PyCodeObject *code); +static bool function_check_args(PyObject *o, int expected_argcount, int opcode); +static uint32_t function_get_version(PyObject *o, int opcode); static int specialize_module_load_attr(PyObject *owner, _Py_CODEUNIT *instr, @@ -505,7 +511,6 @@ specialize_module_load_attr(PyObject *owner, _Py_CODEUNIT *instr, { _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); PyModuleObject *m = (PyModuleObject *)owner; - PyObject *value = NULL; assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); PyDictObject *dict = (PyDictObject *)m->md_dict; if (dict == NULL) { @@ -516,14 +521,13 @@ specialize_module_load_attr(PyObject *owner, _Py_CODEUNIT *instr, SPECIALIZATION_FAIL(opcode, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT); return -1; } - Py_ssize_t index = _PyDict_GetItemHint(dict, &_Py_ID(__getattr__), -1, - &value); + Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__)); assert(index != DKIX_ERROR); if (index != DKIX_EMPTY) { SPECIALIZATION_FAIL(opcode, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND); return -1; } - index = _PyDict_GetItemHint(dict, name, -1, &value); + index = _PyDict_LookupIndex(dict, name); assert (index != DKIX_ERROR); if (index != (uint16_t)index) { SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_RANGE); @@ -557,13 +561,15 @@ typedef enum { MUTABLE, /* Instance of a mutable class; might, or might not, be a descriptor */ ABSENT, /* Attribute is not present on the class */ DUNDER_CLASS, /* __class__ attribute */ - GETSET_OVERRIDDEN /* __getattribute__ or __setattr__ has been overridden */ + GETSET_OVERRIDDEN, /* __getattribute__ or __setattr__ has been overridden */ + GETATTRIBUTE_IS_PYTHON_FUNCTION /* Descriptor requires calling a Python __getattribute__ */ } DescriptorClassification; static DescriptorClassification analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int store) { + bool has_getattr = false; if (store) { if (type->tp_setattro != PyObject_GenericSetAttr) { *descr = NULL; @@ -571,7 +577,42 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto } } else { - if (type->tp_getattro != PyObject_GenericGetAttr) { + getattrofunc getattro_slot = type->tp_getattro; + if (getattro_slot == PyObject_GenericGetAttr) { + /* Normal attribute lookup; */ + has_getattr = false; + } + else if (getattro_slot == _Py_slot_tp_getattr_hook || + getattro_slot == _Py_slot_tp_getattro) { + /* One or both of __getattribute__ or __getattr__ may have been + overridden See typeobject.c for why these functions are special. */ + PyObject *getattribute = _PyType_Lookup(type, + &_Py_ID(__getattribute__)); + PyInterpreterState *interp = _PyInterpreterState_GET(); + bool has_custom_getattribute = getattribute != NULL && + getattribute != interp->callable_cache.object__getattribute__; + has_getattr = _PyType_Lookup(type, &_Py_ID(__getattr__)) != NULL; + if (has_custom_getattribute) { + if (getattro_slot == _Py_slot_tp_getattro && + !has_getattr && + Py_IS_TYPE(getattribute, &PyFunction_Type)) { + *descr = getattribute; + return GETATTRIBUTE_IS_PYTHON_FUNCTION; + } + /* Potentially both __getattr__ and __getattribute__ are set. + Too complicated */ + *descr = NULL; + return GETSET_OVERRIDDEN; + } + /* Potentially has __getattr__ but no custom __getattribute__. + Fall through to usual descriptor analysis. + Usual attribute lookup should only be allowed at runtime + if we can guarantee that there is no way an exception can be + raised. This means some specializations, e.g. specializing + for property() isn't safe. + */ + } + else { *descr = NULL; return GETSET_OVERRIDDEN; } @@ -595,7 +636,10 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto return OTHER_SLOT; } if (desc_cls == &PyProperty_Type) { - return PROPERTY; + /* We can't detect at runtime whether an attribute exists + with property. So that means we may have to call + __getattr__. */ + return has_getattr ? GETSET_OVERRIDDEN : PROPERTY; } if (PyUnicode_CompareWithASCIIString(name, "__class__") == 0) { if (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)) { @@ -657,14 +701,13 @@ specialize_dict_access( return 0; } // We found an instance with a __dict__. - PyObject *value = NULL; - Py_ssize_t hint = - _PyDict_GetItemHint(dict, name, -1, &value); - if (hint != (uint16_t)hint) { + Py_ssize_t index = + _PyDict_LookupIndex(dict, name); + if (index != (uint16_t)index) { SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE); return 0; } - cache->index = (uint16_t)hint; + cache->index = (uint16_t)index; write_u32(cache->version, type->tp_version_tag); _Py_SET_OPCODE(*instr, hint_op); } @@ -674,7 +717,6 @@ specialize_dict_access( static int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name, PyObject* descr, DescriptorClassification kind); static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name); -static int function_kind(PyCodeObject *code); int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) @@ -729,24 +771,15 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); goto fail; } - if (Py_TYPE(fget) != &PyFunction_Type) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY); - goto fail; - } - PyFunctionObject *func = (PyFunctionObject *)fget; - PyCodeObject *fcode = (PyCodeObject *)func->func_code; - int kind = function_kind(fcode); - if (kind != SIMPLE_FUNCTION) { - SPECIALIZATION_FAIL(LOAD_ATTR, kind); + if (!Py_IS_TYPE(fget, &PyFunction_Type)) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION); goto fail; } - if (fcode->co_argcount != 1) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + if (!function_check_args(fget, 1, LOAD_ATTR)) { goto fail; } - int version = _PyFunction_GetVersionForCurrentState(func); + uint32_t version = function_get_version(fget, LOAD_ATTR); if (version == 0) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); goto fail; } write_u32(lm_cache->keys_version, version); @@ -795,6 +828,20 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) case GETSET_OVERRIDDEN: SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN); goto fail; + case GETATTRIBUTE_IS_PYTHON_FUNCTION: + { + assert(type->tp_getattro == _Py_slot_tp_getattro); + assert(Py_IS_TYPE(descr, &PyFunction_Type)); + _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1); + if (!function_check_args(descr, 2, LOAD_ATTR)) { + goto fail; + } + /* borrowed */ + write_obj(lm_cache->descr, descr); + write_u32(lm_cache->type_version, type->tp_version_tag); + _Py_SET_OPCODE(*instr, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN); + goto success; + } case BUILTIN_CLASSMETHOD: case PYTHON_CLASSMETHOD: case NON_OVERRIDING: @@ -873,6 +920,7 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) case MUTABLE: SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; + case GETATTRIBUTE_IS_PYTHON_FUNCTION: case GETSET_OVERRIDDEN: SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN); goto fail; @@ -1215,6 +1263,39 @@ function_kind(PyCodeObject *code) { return SIMPLE_FUNCTION; } +/* Returning false indicates a failure. */ +static bool +function_check_args(PyObject *o, int expected_argcount, int opcode) +{ + assert(Py_IS_TYPE(o, &PyFunction_Type)); + PyFunctionObject *func = (PyFunctionObject *)o; + PyCodeObject *fcode = (PyCodeObject *)func->func_code; + int kind = function_kind(fcode); + if (kind != SIMPLE_FUNCTION) { + SPECIALIZATION_FAIL(opcode, kind); + return false; + } + if (fcode->co_argcount != expected_argcount) { + SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + return false; + } + return true; +} + +/* Returning 0 indicates a failure. */ +static uint32_t +function_get_version(PyObject *o, int opcode) +{ + assert(Py_IS_TYPE(o, &PyFunction_Type)); + PyFunctionObject *func = (PyFunctionObject *)o; + uint32_t version = _PyFunction_GetVersionForCurrentState(func); + if (version == 0) { + SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS); + return 0; + } + return version; +} + int _Py_Specialize_BinarySubscr( PyObject *container, PyObject *sub, _Py_CODEUNIT *instr) @@ -1918,10 +1999,8 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP); _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1); int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]); - if (next_opcode != POP_JUMP_FORWARD_IF_FALSE && - next_opcode != POP_JUMP_BACKWARD_IF_FALSE && - next_opcode != POP_JUMP_FORWARD_IF_TRUE && - next_opcode != POP_JUMP_BACKWARD_IF_TRUE) { + if (next_opcode != POP_JUMP_IF_FALSE && + next_opcode != POP_JUMP_IF_TRUE) { // Can't ever combine, so don't don't bother being adaptive (unless // we're collecting stats, where it's more important to get accurate hit // counts for the unadaptive version and each of the different failure @@ -1940,14 +2019,9 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, } assert(oparg <= Py_GE); int when_to_jump_mask = compare_masks[oparg]; - if (next_opcode == POP_JUMP_FORWARD_IF_FALSE || - next_opcode == POP_JUMP_BACKWARD_IF_FALSE) { + if (next_opcode == POP_JUMP_IF_FALSE) { when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask; } - if (next_opcode == POP_JUMP_BACKWARD_IF_TRUE || - next_opcode == POP_JUMP_BACKWARD_IF_FALSE) { - when_to_jump_mask <<= 3; - } if (Py_TYPE(lhs) != Py_TYPE(rhs)) { SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); goto failure; @@ -1975,7 +2049,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, } else { _Py_SET_OPCODE(*instr, COMPARE_OP_STR_JUMP); - cache->mask = when_to_jump_mask; + cache->mask = (when_to_jump_mask & 2) == 0; goto success; } } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index b8009b2db45f7be..653b5a55e885e5e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -20,6 +20,7 @@ Data members: #include "pycore_code.h" // _Py_QuickenedCount #include "pycore_frame.h" // _PyInterpreterFrame #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_long.h" // _PY_LONG_MAX_STR_DIGITS_THRESHOLD #include "pycore_namespace.h" // _PyNamespace_New() #include "pycore_object.h" // _PyObject_IS_GC() #include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0() @@ -1021,6 +1022,36 @@ Set the global debug tracing function. It will be called on each\n\ function call. See the debugger chapter in the library manual." ); +/*[clinic input] +sys._settraceallthreads + + arg: object + / + +Set the global debug tracing function in all running threads belonging to the current interpreter. + +It will be called on each function call. See the debugger chapter +in the library manual. +[clinic start generated code]*/ + +static PyObject * +sys__settraceallthreads(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=161cca30207bf3ca input=5906aa1485a50289]*/ +{ + PyObject* argument = NULL; + Py_tracefunc func = NULL; + + if (arg != Py_None) { + func = trace_trampoline; + argument = arg; + } + + + PyEval_SetTraceAllThreads(func, argument); + + Py_RETURN_NONE; +} + /*[clinic input] sys.gettrace @@ -1066,6 +1097,35 @@ Set the profiling function. It will be called on each function call\n\ and return. See the profiler chapter in the library manual." ); +/*[clinic input] +sys._setprofileallthreads + + arg: object + / + +Set the profiling function in all running threads belonging to the current interpreter. + +It will be called on each function call and return. See the profiler chapter +in the library manual. +[clinic start generated code]*/ + +static PyObject * +sys__setprofileallthreads(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=2d61319e27b309fe input=d1a356d3f4f9060a]*/ +{ + PyObject* argument = NULL; + Py_tracefunc func = NULL; + + if (arg != Py_None) { + func = profile_trampoline; + argument = arg; + } + + PyEval_SetProfileAllThreads(func, argument); + + Py_RETURN_NONE; +} + /*[clinic input] sys.getprofile @@ -1427,6 +1487,44 @@ static PyStructSequence_Desc windows_version_desc = { via indexing, the rest are name only */ }; +static PyObject * +_sys_getwindowsversion_from_kernel32() +{ + HANDLE hKernel32; + wchar_t kernel32_path[MAX_PATH]; + LPVOID verblock; + DWORD verblock_size; + VS_FIXEDFILEINFO *ffi; + UINT ffi_len; + DWORD realMajor, realMinor, realBuild; + + Py_BEGIN_ALLOW_THREADS + hKernel32 = GetModuleHandleW(L"kernel32.dll"); + Py_END_ALLOW_THREADS + if (!hKernel32 || !GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH)) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL); + if (!verblock_size) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + verblock = PyMem_RawMalloc(verblock_size); + if (!verblock || + !GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) || + !VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + + realMajor = HIWORD(ffi->dwProductVersionMS); + realMinor = LOWORD(ffi->dwProductVersionMS); + realBuild = HIWORD(ffi->dwProductVersionLS); + PyMem_RawFree(verblock); + return Py_BuildValue("(kkk)", realMajor, realMinor, realBuild); +} + /* Disable deprecation warnings about GetVersionEx as the result is being passed straight through to the caller, who is responsible for using it correctly. */ @@ -1456,11 +1554,13 @@ sys_getwindowsversion_impl(PyObject *module) PyObject *version; int pos = 0; OSVERSIONINFOEXW ver; - DWORD realMajor, realMinor, realBuild; - HANDLE hKernel32; - wchar_t kernel32_path[MAX_PATH]; - LPVOID verblock; - DWORD verblock_size; + + version = PyObject_GetAttrString(module, "_cached_windows_version"); + if (version && PyObject_TypeCheck(version, &WindowsVersionType)) { + return version; + } + Py_XDECREF(version); + PyErr_Clear(); ver.dwOSVersionInfoSize = sizeof(ver); if (!GetVersionExW((OSVERSIONINFOW*) &ver)) @@ -1480,41 +1580,34 @@ sys_getwindowsversion_impl(PyObject *module) PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask)); PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType)); - realMajor = ver.dwMajorVersion; - realMinor = ver.dwMinorVersion; - realBuild = ver.dwBuildNumber; - // GetVersion will lie if we are running in a compatibility mode. // We need to read the version info from a system file resource // to accurately identify the OS version. If we fail for any reason, // just return whatever GetVersion said. - Py_BEGIN_ALLOW_THREADS - hKernel32 = GetModuleHandleW(L"kernel32.dll"); - Py_END_ALLOW_THREADS - if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) && - (verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) && - (verblock = PyMem_RawMalloc(verblock_size))) { - VS_FIXEDFILEINFO *ffi; - UINT ffi_len; - - if (GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) && - VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) { - realMajor = HIWORD(ffi->dwProductVersionMS); - realMinor = LOWORD(ffi->dwProductVersionMS); - realBuild = HIWORD(ffi->dwProductVersionLS); - } - PyMem_RawFree(verblock); + PyObject *realVersion = _sys_getwindowsversion_from_kernel32(); + if (!realVersion) { + PyErr_Clear(); + realVersion = Py_BuildValue("(kkk)", + ver.dwMajorVersion, + ver.dwMinorVersion, + ver.dwBuildNumber + ); + } + + if (realVersion) { + PyStructSequence_SET_ITEM(version, pos++, realVersion); } - PyStructSequence_SET_ITEM(version, pos++, Py_BuildValue("(kkk)", - realMajor, - realMinor, - realBuild - )); if (PyErr_Occurred()) { Py_DECREF(version); return NULL; } + + if (PyObject_SetAttrString(module, "_cached_windows_version", version) < 0) { + Py_DECREF(version); + return NULL; + } + return version; } @@ -1612,6 +1705,45 @@ sys_mdebug_impl(PyObject *module, int flag) } #endif /* USE_MALLOPT */ + +/*[clinic input] +sys.get_int_max_str_digits + +Set the maximum string digits limit for non-binary int<->str conversions. +[clinic start generated code]*/ + +static PyObject * +sys_get_int_max_str_digits_impl(PyObject *module) +/*[clinic end generated code: output=0042f5e8ae0e8631 input=8dab13e2023e60d5]*/ +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return PyLong_FromSsize_t(interp->int_max_str_digits); +} + +/*[clinic input] +sys.set_int_max_str_digits + + maxdigits: int + +Set the maximum string digits limit for non-binary int<->str conversions. +[clinic start generated code]*/ + +static PyObject * +sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits) +/*[clinic end generated code: output=734d4c2511f2a56d input=d7e3f325db6910c5]*/ +{ + PyThreadState *tstate = _PyThreadState_GET(); + if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) { + tstate->interp->int_max_str_digits = maxdigits; + Py_RETURN_NONE; + } else { + PyErr_Format( + PyExc_ValueError, "maxdigits must be 0 or larger than %d", + _PY_LONG_MAX_STR_DIGITS_THRESHOLD); + return NULL; + } +} + size_t _PySys_GetSizeOf(PyObject *o) { @@ -1994,6 +2126,80 @@ sys_getandroidapilevel_impl(PyObject *module) } #endif /* ANDROID_API_LEVEL */ +/*[clinic input] +sys.activate_stack_trampoline + + backend: str + / + +Activate the perf profiler trampoline. +[clinic start generated code]*/ + +static PyObject * +sys_activate_stack_trampoline_impl(PyObject *module, const char *backend) +/*[clinic end generated code: output=5783cdeb51874b43 input=b09020e3a17c78c5]*/ +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + if (strcmp(backend, "perf") == 0) { + _PyPerf_Callbacks cur_cb; + _PyPerfTrampoline_GetCallbacks(&cur_cb); + if (cur_cb.init_state != _Py_perfmap_callbacks.init_state) { + if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 ) { + PyErr_SetString(PyExc_ValueError, "can't activate perf trampoline"); + return NULL; + } + } + } + else { + PyErr_Format(PyExc_ValueError, "invalid backend: %s", backend); + return NULL; + } + if (_PyPerfTrampoline_Init(1) < 0) { + return NULL; + } + Py_RETURN_NONE; +#else + PyErr_SetString(PyExc_ValueError, "perf trampoline not available"); + return NULL; +#endif +} + + +/*[clinic input] +sys.deactivate_stack_trampoline + +Dectivate the perf profiler trampoline. +[clinic start generated code]*/ + +static PyObject * +sys_deactivate_stack_trampoline_impl(PyObject *module) +/*[clinic end generated code: output=b50da25465df0ef1 input=491f4fc1ed615736]*/ +{ + if (_PyPerfTrampoline_Init(0) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +sys.is_stack_trampoline_active + +Returns *True* if the perf profiler trampoline is active. +[clinic start generated code]*/ + +static PyObject * +sys_is_stack_trampoline_active_impl(PyObject *module) +/*[clinic end generated code: output=ab2746de0ad9d293 input=061fa5776ac9dd59]*/ +{ +#ifdef PY_HAVE_PERF_TRAMPOLINE + if (_PyIsPerfTrampolineActive()) { + Py_RETURN_TRUE; + } +#endif + Py_RETURN_FALSE; +} + + static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ SYS_ADDAUDITHOOK_METHODDEF @@ -2035,9 +2241,11 @@ static PyMethodDef sys_methods[] = { SYS_GETSWITCHINTERVAL_METHODDEF SYS_SETDLOPENFLAGS_METHODDEF {"setprofile", sys_setprofile, METH_O, setprofile_doc}, + SYS__SETPROFILEALLTHREADS_METHODDEF SYS_GETPROFILE_METHODDEF SYS_SETRECURSIONLIMIT_METHODDEF {"settrace", sys_settrace, METH_O, settrace_doc}, + SYS__SETTRACEALLTHREADS_METHODDEF SYS_GETTRACE_METHODDEF SYS_CALL_TRACING_METHODDEF SYS__DEBUGMALLOCSTATS_METHODDEF @@ -2047,7 +2255,12 @@ static PyMethodDef sys_methods[] = { METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc}, SYS_GET_ASYNCGEN_HOOKS_METHODDEF SYS_GETANDROIDAPILEVEL_METHODDEF + SYS_ACTIVATE_STACK_TRAMPOLINE_METHODDEF + SYS_DEACTIVATE_STACK_TRAMPOLINE_METHODDEF + SYS_IS_STACK_TRAMPOLINE_ACTIVE_METHODDEF SYS_UNRAISABLEHOOK_METHODDEF + SYS_GET_INT_MAX_STR_DIGITS_METHODDEF + SYS_SET_INT_MAX_STR_DIGITS_METHODDEF #ifdef Py_STATS SYS__STATS_ON_METHODDEF SYS__STATS_OFF_METHODDEF @@ -2548,6 +2761,7 @@ static PyStructSequence_Field flags_fields[] = { {"utf8_mode", "-X utf8"}, {"warn_default_encoding", "-X warn_default_encoding"}, {"safe_path", "-P"}, + {"int_max_str_digits", "-X int_max_str_digits"}, {0} }; @@ -2555,7 +2769,7 @@ static PyStructSequence_Desc flags_desc = { "sys.flags", /* name */ flags__doc__, /* doc */ flags_fields, /* fields */ - 17 + 18 }; static int @@ -2596,6 +2810,7 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags) SetFlag(preconfig->utf8_mode); SetFlag(config->warn_default_encoding); SetFlagObj(PyBool_FromLong(config->safe_path)); + SetFlag(_Py_global_config_int_max_str_digits); #undef SetFlagObj #undef SetFlag return 0; diff --git a/Python/thread.c b/Python/thread.c index e206a69c0507daa..8c8a4e81895eb68 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -59,7 +59,7 @@ PyThread_init_thread(void) # define PYTHREAD_NAME "pthread-stubs" # include "thread_pthread_stubs.h" #elif defined(_POSIX_THREADS) -# if defined(__EMSCRIPTEN__) || !defined(__EMSCRIPTEN_PTHREADS__) +# if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__) # define PYTHREAD_NAME "pthread-stubs" # else # define PYTHREAD_NAME "pthread" diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index a1d349dc0b0ddbf..3fa9fefbd5ec0b9 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -385,6 +385,9 @@ def get_parsed_vartype(decl): elif isinstance(decl, Variable): storage = decl.storage typequal, typespec, abstract = decl.vartype + elif isinstance(decl, Signature): + storage = None + typequal, typespec, abstract = decl.returntype elif isinstance(decl, Function): storage = decl.storage typequal, typespec, abstract = decl.signature.returntype @@ -789,6 +792,7 @@ def _from_row(cls, row): if kind is not cls.kind: raise TypeError(f'expected kind {cls.kind.value!r}, got {row!r}') fileinfo = FileInfo.from_raw(filename) + extra = None if isinstance(data, str): data, extra = cls._parse_data(data, fmt='row') if extra: @@ -1012,6 +1016,18 @@ def __str__(self): def returns(self): return self.returntype + @property + def typequal(self): + return self.returntype.typequal + + @property + def typespec(self): + return self.returntype.typespec + + @property + def abstract(self): + return self.returntype.abstract + class Function(Declaration): kind = KIND.FUNCTION @@ -1106,9 +1122,16 @@ class TypeDef(TypeDeclaration): def _resolve_data(cls, data): if not data: raise NotImplementedError(data) - vartype = dict(data) - del vartype['storage'] - return VarType(**vartype), None + kwargs = dict(data) + del kwargs['storage'] + if 'returntype' in kwargs: + vartype = kwargs['returntype'] + del vartype['storage'] + kwargs['returntype'] = VarType(**vartype) + datacls = Signature + else: + datacls = VarType + return datacls(**kwargs), None @classmethod def _raw_data(self, data): diff --git a/Tools/c-analyzer/c_parser/parser/_common.py b/Tools/c-analyzer/c_parser/parser/_common.py index 40c36039f3f47dc..d468d5442a939f0 100644 --- a/Tools/c-analyzer/c_parser/parser/_common.py +++ b/Tools/c-analyzer/c_parser/parser/_common.py @@ -9,7 +9,11 @@ def log_match(group, m): from . import _logger - _logger.debug(f'matched <{group}> ({m.group(0)})') + text = m.group(0) + if text.startswith(('(', ')')) or text.endswith(('(', ')')): + _logger.debug(f'matched <{group}> ({text!r})') + else: + _logger.debug(f'matched <{group}> ({text})') ############################# diff --git a/Tools/c-analyzer/cpython/_analyzer.py b/Tools/c-analyzer/cpython/_analyzer.py index 741fbaddf16d95a..4a11fc99a4064de 100644 --- a/Tools/c-analyzer/cpython/_analyzer.py +++ b/Tools/c-analyzer/cpython/_analyzer.py @@ -60,6 +60,46 @@ # {ID => reason} } +# XXX We should be handling these through known.tsv. +_OTHER_SUPPORTED_TYPES = { + # Holds tuple of strings, which we statically initialize: + '_PyArg_Parser', + # Uses of these should be const, but we don't worry about it. + 'PyModuleDef', + 'PyModuleDef_Slot[]', + 'PyType_Spec', + 'PyType_Slot[]', + 'PyMethodDef', + 'PyMethodDef[]', + 'PyMemberDef[]', + 'PyGetSetDef[]', + 'PyNumberMethods', + 'PySequenceMethods', + 'PyMappingMethods', + 'PyAsyncMethods', + 'PyBufferProcs', + 'PyStructSequence_Field[]', + 'PyStructSequence_Desc', +} + +# XXX We should normalize all cases to a single name, +# e.g. "kwlist" (currently the most common). +_KWLIST_VARIANTS = [ + ('*', 'kwlist'), + ('*', 'keywords'), + ('*', 'kwargs'), + ('Modules/_csv.c', 'dialect_kws'), + ('Modules/_datetimemodule.c', 'date_kws'), + ('Modules/_datetimemodule.c', 'datetime_kws'), + ('Modules/_datetimemodule.c', 'time_kws'), + ('Modules/_datetimemodule.c', 'timezone_kws'), + ('Modules/_lzmamodule.c', 'optnames'), + ('Modules/_lzmamodule.c', 'arg_names'), + ('Modules/cjkcodecs/multibytecodec.c', 'incnewkwarglist'), + ('Modules/cjkcodecs/multibytecodec.c', 'streamkwarglist'), + ('Modules/socketmodule.c', 'kwnames'), +] + KINDS = frozenset((*KIND.TYPES, KIND.VARIABLE)) @@ -202,6 +242,8 @@ def _check_typedep(decl, typedecl, types, knowntypes): # XXX Fail? return 'typespec (missing)' elif typedecl is _info.UNKNOWN: + if _has_other_supported_type(decl): + return None # XXX Is this right? return 'typespec (unknown)' elif not isinstance(typedecl, TypeDeclaration): @@ -216,12 +258,42 @@ def _check_typedep(decl, typedecl, types, knowntypes): elif decl.kind is KIND.VARIABLE: if not is_process_global(decl): return None + if _is_kwlist(decl): + return None + if _has_other_supported_type(decl): + return None checked = _check_vartype(decl, typedecl, types, knowntypes) return 'mutable' if checked is FIXED_TYPE else checked else: raise NotImplementedError(decl) +def _is_kwlist(decl): + # keywords for PyArg_ParseTupleAndKeywords() + # "static char *name[]" -> "static const char * const name[]" + # XXX These should be made const. + for relpath, name in _KWLIST_VARIANTS: + if decl.name == name: + if relpath == '*': + break + assert os.path.isabs(decl.file.filename) + relpath = os.path.normpath(relpath) + if decl.file.filename.endswith(os.path.sep + relpath): + break + else: + return False + vartype = ''.join(str(decl.vartype).split()) + return vartype == 'char*[]' + + +def _has_other_supported_type(decl): + vartype = str(decl.vartype).split() + if vartype[0] == 'struct': + vartype = vartype[1:] + vartype = ''.join(vartype) + return vartype in _OTHER_SUPPORTED_TYPES + + def _check_vartype(decl, typedecl, types, knowntypes): """Return failure reason.""" checked = _check_typespec(decl, typedecl, types, knowntypes) diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py index af223b114941854..dc8423bfcbad0a6 100644 --- a/Tools/c-analyzer/cpython/_parser.py +++ b/Tools/c-analyzer/cpython/_parser.py @@ -86,8 +86,6 @@ def clean_lines(text): # generated Python/deepfreeze/*.c Python/frozen_modules/*.h -Python/opcode_targets.h -Python/stdlib_module_names.h # @end=conf@ ''') @@ -109,9 +107,7 @@ def clean_lines(text): Modules/_dbmmodule.c Modules/cjkcodecs/_codecs_*.c -Modules/expat/xmlrole.c Modules/expat/xmlparse.c -Python/initconfig.c ''') INCL_DIRS = clean_lines(''' @@ -141,6 +137,7 @@ def clean_lines(text): Objects/**/*.c Py_BUILD_CORE 1 Modules/_asynciomodule.c Py_BUILD_CORE 1 +Modules/_codecsmodule.c Py_BUILD_CORE 1 Modules/_collectionsmodule.c Py_BUILD_CORE 1 Modules/_ctypes/_ctypes.c Py_BUILD_CORE 1 Modules/_ctypes/cfield.c Py_BUILD_CORE 1 @@ -177,7 +174,6 @@ def clean_lines(text): Objects/stringlib/unicode_format.h Py_BUILD_CORE 1 Parser/string_parser.h Py_BUILD_CORE 1 Parser/pegen.h Py_BUILD_CORE 1 -Python/ceval_gil.h Py_BUILD_CORE 1 Python/condvar.h Py_BUILD_CORE 1 Modules/_json.c Py_BUILD_CORE_BUILTIN 1 @@ -293,6 +289,10 @@ def clean_lines(text): ] MAX_SIZES = { + # GLOB: (MAXTEXT, MAXLINES), + # First match wins. + _abs('Include/internal/pycore_global_strings.h'): (5_000, 1000), + _abs('Include/internal/pycore_runtime_init_generated.h'): (5_000, 1000), _abs('Include/**/*.h'): (5_000, 500), _abs('Modules/_ctypes/ctypes.h'): (5_000, 500), _abs('Modules/_datetimemodule.c'): (20_000, 300), @@ -303,8 +303,12 @@ def clean_lines(text): _abs('Objects/stringlib/unicode_format.h'): (10_000, 400), _abs('Objects/typeobject.c'): (20_000, 200), _abs('Python/compile.c'): (20_000, 500), + _abs('Python/deepfreeze/*.c'): (20_000, 500), + _abs('Python/frozen_modules/*.h'): (20_000, 500), _abs('Python/pylifecycle.c'): (500_000, 5000), _abs('Python/pystate.c'): (500_000, 5000), + _abs('Python/opcode_targets.h'): (10_000, 500), + _abs('Python/stdlib_module_names.h'): (5_000, 500), } diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c8d23e9db0e127d..e3a0f1a376042f7 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -290,7 +290,6 @@ Objects/exceptions.c - PyExc_EncodingWarning - Objects/boolobject.c - _Py_FalseStruct - Objects/boolobject.c - _Py_TrueStruct - Objects/dictobject.c - empty_keys_struct - -Objects/dictobject.c - empty_values_struct - Objects/object.c - _Py_NoneStruct - Objects/object.c - _Py_NotImplementedStruct - Objects/setobject.c - _dummy_struct - @@ -301,96 +300,27 @@ Objects/sliceobject.c - _Py_EllipsisObject - # cached - initialized once # manually cached PyUnicodeObject -# XXX This should have been found by the analyzer but wasn't: Python/ast_unparse.c - _str_replace_inf - -# _PyArg_Parser (holds tuple of strings) -Objects/clinic/bytearrayobject.c.h bytearray___init__ _parser - -Objects/clinic/bytearrayobject.c.h bytearray_decode _parser - -Objects/clinic/bytearrayobject.c.h bytearray_hex _parser - -Objects/clinic/bytearrayobject.c.h bytearray_rsplit _parser - -Objects/clinic/bytearrayobject.c.h bytearray_split _parser - -Objects/clinic/bytearrayobject.c.h bytearray_splitlines _parser - -Objects/clinic/bytearrayobject.c.h bytearray_translate _parser - -Objects/clinic/bytesobject.c.h bytes_decode _parser - -Objects/clinic/bytesobject.c.h bytes_hex _parser - -Objects/clinic/bytesobject.c.h bytes_new _parser - -Objects/clinic/bytesobject.c.h bytes_rsplit _parser - -Objects/clinic/bytesobject.c.h bytes_split _parser - -Objects/clinic/bytesobject.c.h bytes_splitlines _parser - -Objects/clinic/bytesobject.c.h bytes_translate _parser - -Objects/clinic/codeobject.c.h code__varname_from_oparg _parser - -Objects/clinic/codeobject.c.h code_replace _parser - -Objects/clinic/complexobject.c.h complex_new _parser - -Objects/clinic/descrobject.c.h mappingproxy_new _parser - -Objects/clinic/descrobject.c.h property_init _parser - -Objects/clinic/enumobject.c.h enum_new _parser - -Objects/clinic/funcobject.c.h func_new _parser - -Objects/clinic/listobject.c.h list_sort _parser - -Objects/clinic/longobject.c.h int_from_bytes _parser - -Objects/clinic/longobject.c.h int_to_bytes _parser - -Objects/clinic/longobject.c.h long_new _parser - -Objects/clinic/memoryobject.c.h memoryview _parser - -Objects/clinic/memoryobject.c.h memoryview_cast _parser - -Objects/clinic/memoryobject.c.h memoryview_hex _parser - -Objects/clinic/memoryobject.c.h memoryview_tobytes _parser - -Objects/clinic/moduleobject.c.h module___init__ _parser - -Objects/clinic/odictobject.c.h OrderedDict_fromkeys _parser - -Objects/clinic/odictobject.c.h OrderedDict_move_to_end _parser - -Objects/clinic/odictobject.c.h OrderedDict_pop _parser - -Objects/clinic/odictobject.c.h OrderedDict_popitem _parser - -Objects/clinic/odictobject.c.h OrderedDict_setdefault _parser - -Objects/clinic/structseq.c.h structseq_new _parser - -Objects/clinic/unicodeobject.c.h unicode_encode _parser - -Objects/clinic/unicodeobject.c.h unicode_expandtabs _parser - -Objects/clinic/unicodeobject.c.h unicode_new _parser - -Objects/clinic/unicodeobject.c.h unicode_rsplit _parser - -Objects/clinic/unicodeobject.c.h unicode_split _parser - -Objects/clinic/unicodeobject.c.h unicode_splitlines _parser - -Python/clinic/Python-tokenize.c.h tokenizeriter_new _parser - -Python/clinic/_warnings.c.h warnings_warn _parser - -Python/clinic/_warnings.c.h warnings_warn_explicit _parser - -Python/clinic/bltinmodule.c.h builtin___import__ _parser - -Python/clinic/bltinmodule.c.h builtin_compile _parser - -Python/clinic/bltinmodule.c.h builtin_exec _parser - -Python/clinic/bltinmodule.c.h builtin_pow _parser - -Python/clinic/bltinmodule.c.h builtin_print _parser - -Python/clinic/bltinmodule.c.h builtin_round _parser - -Python/clinic/bltinmodule.c.h builtin_sum _parser - -Python/clinic/import.c.h _imp_find_frozen _parser - -Python/clinic/import.c.h _imp_source_hash _parser - -Python/clinic/sysmodule.c.h sys_addaudithook _parser - -Python/clinic/sysmodule.c.h sys_set_coroutine_origin_tracking_depth _parser - -Python/clinic/traceback.c.h tb_new _parser - - # holds strings Objects/typeobject.c - slotdefs - # other -Objects/typeobject.c - method_cache - Objects/typeobject.c object___reduce_ex___impl objreduce - Objects/unicodeobject.c - _string_module - Objects/unicodeobject.c - interned - -Objects/unicodeobject.c - static_strings - #----------------------- # other # initialized once -# XXX This should have been found by the analyzer but wasn't: Python/context.c - _token_missing - -# XXX This should have been found by the analyzer but wasn't: Python/fileutils.c - _Py_open_cloexec_works - -# XXX This should have been found by the analyzer but wasn't: Python/hamt.c - _empty_bitmap_node - -# XXX This should have been found by the analyzer but wasn't: Python/hamt.c - _empty_hamt - -# XXX This should have been found by the analyzer but wasn't: -Python/import.c PyImport_Import silly_list - # state Objects/typeobject.c resolve_slotdups pname - -# XXX This should have been found by the analyzer but wasn't: Python/import.c - extensions - @@ -406,23 +336,43 @@ Modules/getbuildinfo.c Py_GetBuildInfo buildinfo - # during init Objects/typeobject.c - slotdefs_initialized - Objects/unicodeobject.c - bloom_linebreak - -Parser/parser.c - Py_DebugFlag - Python/bootstrap_hash.c - _Py_HashSecret_Initialized - Python/bootstrap_hash.c py_getrandom getrandom_works - +Python/initconfig.c - Py_DebugFlag - +Python/initconfig.c - Py_UTF8Mode - +Python/initconfig.c - Py_DebugFlag - +Python/initconfig.c - Py_VerboseFlag - +Python/initconfig.c - Py_QuietFlag - +Python/initconfig.c - Py_InteractiveFlag - +Python/initconfig.c - Py_InspectFlag - +Python/initconfig.c - Py_OptimizeFlag - +Python/initconfig.c - Py_NoSiteFlag - +Python/initconfig.c - Py_BytesWarningFlag - +Python/initconfig.c - Py_FrozenFlag - +Python/initconfig.c - Py_IgnoreEnvironmentFlag - +Python/initconfig.c - Py_DontWriteBytecodeFlag - +Python/initconfig.c - Py_NoUserSiteDirectory - +Python/initconfig.c - Py_UnbufferedStdioFlag - +Python/initconfig.c - Py_HashRandomizationFlag - +Python/initconfig.c - Py_IsolatedFlag - +Python/initconfig.c - Py_LegacyWindowsFSEncodingFlag - +Python/initconfig.c - Py_LegacyWindowsStdioFlag - +Python/initconfig.c - orig_argv - Python/pyhash.c - _Py_HashSecret - Python/pylifecycle.c - runtime_initialized - Python/sysmodule.c - _PySys_ImplCacheTag - Python/sysmodule.c - _PySys_ImplName - Python/sysmodule.c - _preinit_warnoptions - Python/sysmodule.c - _preinit_xoptions - -Python/thread.c - thread_debug - Python/thread.c - initialized - +# set by embedders during init +Python/initconfig.c - _Py_StandardStreamEncoding - +Python/initconfig.c - _Py_StandardStreamErrors - + # lazy Objects/floatobject.c - double_format - Objects/floatobject.c - float_format - -Objects/floatobject.c - detected_double_format - -Objects/floatobject.c - detected_float_format - Objects/longobject.c PyLong_FromString log_base_BASE - Objects/longobject.c PyLong_FromString convwidth_base - Objects/longobject.c PyLong_FromString convmultmax_base - @@ -431,11 +381,8 @@ Parser/action_helpers.c _PyPegen_dummy_name cache - Python/dtoa.c - p5s - Python/fileutils.c - force_ascii - Python/fileutils.c set_inheritable ioctl_works - -# XXX This should have been found by the analyzer but wasn't: Python/import.c - import_lock - -# XXX This should have been found by the analyzer but wasn't: Python/import.c import_find_and_load header - -Python/specialize.c - _list_append - #----------------------- # unlikely to change after init (or main thread) @@ -501,37 +448,24 @@ Python/getargs.c - static_arg_parsers - # other Objects/dictobject.c - _pydict_global_version - Objects/dictobject.c - next_dict_keys_version - -Objects/dictobject.c - pydict_global_version - Objects/funcobject.c - next_func_version - Objects/moduleobject.c - max_module_number - Objects/object.c - _Py_RefTotal - Objects/typeobject.c - next_version_tag - Objects/typeobject.c resolve_slotdups ptrs - Parser/pegen.c - memo_statistics - -# XXX This should have been found by the analyzer but wasn't: Python/bootstrap_hash.c - urandom_cache - -# XXX This should have been found by the analyzer but wasn't: -Python/ceval.c - lltrace - -# XXX This should have been found by the analyzer but wasn't: -Python/ceval.c make_pending_calls busy - +Python/ceval_gil.c make_pending_calls busy - Python/ceval.c _PyEval_SetProfile reentrant - Python/ceval.c _PyEval_SetTrace reentrant - -Python/dynload_shlib.c - handles - -Python/dynload_shlib.c - nhandles - -# XXX This should have been found by the analyzer but wasn't: Python/import.c - import_lock_level - -# XXX This should have been found by the analyzer but wasn't: Python/import.c - import_lock_thread - -# XXX This should have been found by the analyzer but wasn't: Python/import.c import_find_and_load accumulated - -# XXX This should have been found by the analyzer but wasn't: Python/import.c import_find_and_load import_level - Python/modsupport.c - _Py_PackageContext - Python/pyfpe.c - PyFPE_counter - Python/pylifecycle.c _Py_FatalErrorFormat reentrant - -# XXX This should have been found by the analyzer but wasn't: Python/pylifecycle.c - _Py_UnhandledKeyboardInterrupt - -# XXX This should have been found by the analyzer but wasn't: Python/pylifecycle.c fatal_error reentrant - Python/specialize.c - _Py_QuickenedCount - @@ -547,10 +481,6 @@ Modules/_collectionsmodule.c - deque_type - Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - -Modules/_functoolsmodule.c - keyobject_type - -Modules/_functoolsmodule.c - lru_cache_type - -Modules/_functoolsmodule.c - lru_list_elem_type - -Modules/_functoolsmodule.c - partial_type - Modules/_io/bufferedio.c - PyBufferedIOBase_Type - Modules/_io/bufferedio.c - PyBufferedRWPair_Type - Modules/_io/bufferedio.c - PyBufferedRandom_Type - @@ -565,15 +495,12 @@ Modules/_io/stringio.c - PyStringIO_Type - Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - Modules/_io/textio.c - PyTextIOBase_Type - Modules/_io/textio.c - PyTextIOWrapper_Type - +# XXX This should have been found by the analyzer but wasn't: Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - Modules/_testcapi/vectorcall.c - MethodDescriptor2_Type - -Modules/_threadmodule.c - Locktype - -Modules/_threadmodule.c - RLocktype - -Modules/_threadmodule.c - localdummytype - -Modules/_threadmodule.c - localtype - Modules/itertoolsmodule.c - _grouper_type - Modules/itertoolsmodule.c - accumulate_type - Modules/itertoolsmodule.c - chain_type - @@ -596,90 +523,19 @@ Modules/itertoolsmodule.c - tee_type - Modules/itertoolsmodule.c - teedataobject_type - Modules/itertoolsmodule.c - ziplongest_type - -#----------------------- -# non-static types - initialized once - -# structseq types -Modules/_threadmodule.c - ExceptHookArgsType - -Modules/signalmodule.c - SiginfoType - -Modules/timemodule.c - StructTimeType - - -# exception types -Modules/_threadmodule.c - ThreadError - -Modules/signalmodule.c - ItimerError - - -#----------------------- -# cached - initialized once - -# _PyArg_Parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task__check_future _parser - -Modules/clinic/_csv.c.h _csv_unregister_dialect _parser - -Modules/clinic/_csv.c.h _csv_get_dialect _parser - -Modules/clinic/_csv.c.h _csv_field_size_limit _parser - -Modules/clinic/_codecsmodule.c.h _codecs_decode _parser - -Modules/clinic/_codecsmodule.c.h _codecs_encode _parser - -Modules/clinic/_sre.c.h _sre_SRE_Match_expand _parser - -Modules/clinic/_sre.c.h _sre_SRE_Match_groupdict _parser - -Modules/clinic/_sre.c.h _sre_SRE_Match_groups _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_findall _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_finditer _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_fullmatch _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_match _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_scanner _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_search _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_split _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_sub _parser - -Modules/clinic/_sre.c.h _sre_SRE_Pattern_subn _parser - -Modules/clinic/_sre.c.h _sre_SRE_Scanner_match _parser - -Modules/clinic/_sre.c.h _sre_SRE_Scanner_search _parser - -Modules/clinic/_sre.c.h _sre_compile _parser - -Modules/clinic/_winapi.c.h _winapi_LCMapStringEx _parser - -Modules/clinic/arraymodule.c.h array_array_fromfile _parser - -Modules/clinic/arraymodule.c.h array_array_tofile _parser - -Modules/clinic/arraymodule.c.h array_array___reduce_ex__ _parser - -Modules/clinic/gcmodule.c.h gc_collect _parser - -Modules/clinic/gcmodule.c.h gc_get_objects _parser - -Modules/clinic/itertoolsmodule.c.h itertools_accumulate _parser - -Modules/clinic/itertoolsmodule.c.h itertools_combinations _parser - -Modules/clinic/itertoolsmodule.c.h itertools_combinations_with_replacement _parser - -Modules/clinic/itertoolsmodule.c.h itertools_compress _parser - -Modules/clinic/itertoolsmodule.c.h itertools_count _parser - -Modules/clinic/itertoolsmodule.c.h itertools_groupby _parser - -Modules/clinic/itertoolsmodule.c.h itertools_permutations _parser - -Modules/clinic/posixmodule.c.h os_DirEntry_is_dir _parser - -Modules/clinic/posixmodule.c.h os_DirEntry_is_file _parser - -Modules/clinic/posixmodule.c.h os_DirEntry_is_symlink _parser - -Modules/clinic/posixmodule.c.h os_DirEntry_stat _parser - -Modules/clinic/posixmodule.c.h os__exit _parser - -Modules/clinic/posixmodule.c.h os__path_normpath _parser - -Modules/clinic/posixmodule.c.h os_access _parser - -Modules/clinic/posixmodule.c.h os_chdir _parser - -Modules/clinic/posixmodule.c.h os_chmod _parser - -Modules/clinic/posixmodule.c.h os_close _parser - -Modules/clinic/posixmodule.c.h os_device_encoding _parser - -Modules/clinic/posixmodule.c.h os_dup2 _parser - -Modules/clinic/posixmodule.c.h os_fspath _parser - -Modules/clinic/posixmodule.c.h os_fstat _parser - -Modules/clinic/posixmodule.c.h os_listdir _parser - -Modules/clinic/posixmodule.c.h os_lstat _parser - -Modules/clinic/posixmodule.c.h os_mkdir _parser - -Modules/clinic/posixmodule.c.h os_open _parser - -Modules/clinic/posixmodule.c.h os_remove _parser - -Modules/clinic/posixmodule.c.h os_rename _parser - -Modules/clinic/posixmodule.c.h os_replace _parser - -Modules/clinic/posixmodule.c.h os_rmdir _parser - -Modules/clinic/posixmodule.c.h os_scandir _parser - -Modules/clinic/posixmodule.c.h os_stat _parser - -Modules/clinic/posixmodule.c.h os_unlink _parser - -Modules/clinic/posixmodule.c.h os_utime _parser - -Modules/clinic/socketmodule.c.h sock_initobj _parser - - #----------------------- # other +# statically initializd pointer to static type +# XXX should be const? +# XXX This should have been found by the analyzer but wasn't: +Modules/_io/winconsoleio.c - _PyWindowsConsoleIO_Type - + # initialized once Modules/_functoolsmodule.c - kwd_mark - Modules/_io/_iomodule.c - _PyIO_empty_bytes - +Modules/_testcapi/heaptype.c - _testcapimodule - +Modules/_testcapi/unicode.c - _testcapimodule - Modules/_tracemalloc.c - tracemalloc_empty_traceback - Modules/signalmodule.c - DefaultHandler - Modules/signalmodule.c - IgnoreHandler - @@ -701,13 +557,9 @@ Modules/signalmodule.c - Handlers - # initialized once Modules/_io/bufferedio.c _PyIO_trap_eintr eintr_int - -#Modules/cjkcodecs/cjkcodecs.h - codec_list - -#Modules/cjkcodecs/cjkcodecs.h - mapping_list - Modules/posixmodule.c os_dup2_impl dup3_works - Modules/posixmodule.c - structseq_new - Modules/posixmodule.c - ticks_per_second - -Modules/signalmodule.c - initialized - -Modules/timemodule.c - initialized - Modules/timemodule.c _PyTime_GetClockWithInfo initialized - Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second - @@ -734,75 +586,6 @@ Modules/signalmodule.c - wakeup - ################################## # global objects to fix in extension modules -#----------------------- -# modules - -Modules/_asynciomodule.c - _asynciomodule - -Modules/_bisectmodule.c - _bisectmodule - -Modules/_blake2/blake2module.c - blake2_module - -Modules/_bz2module.c - _bz2module - -Modules/_contextvarsmodule.c - _contextvarsmodule - -Modules/_cryptmodule.c - cryptmodule - -Modules/_csv.c - _csvmodule - -Modules/_ctypes/_ctypes.c - _ctypesmodule - -Modules/_curses_panel.c - _curses_panelmodule - -Modules/_cursesmodule.c - _cursesmodule - -Modules/_datetimemodule.c - datetimemodule - -Modules/_decimal/_decimal.c - _decimal_module - -Modules/_elementtree.c - elementtreemodule - -Modules/_gdbmmodule.c - _gdbmmodule - -Modules/_hashopenssl.c - _hashlibmodule - -Modules/_heapqmodule.c - _heapqmodule - -Modules/_json.c - jsonmodule - -Modules/_lsprof.c - _lsprofmodule - -Modules/_lzmamodule.c - _lzmamodule - -Modules/_multiprocessing/multiprocessing.c - multiprocessing_module - -Modules/_multiprocessing/posixshmem.c - this_module - -Modules/_opcode.c - opcodemodule - -Modules/_operator.c - operatormodule - -Modules/_pickle.c - _picklemodule - -Modules/_posixsubprocess.c - _posixsubprocessmodule - -Modules/_queuemodule.c - queuemodule - -Modules/_randommodule.c - _randommodule - -Modules/_sha3/sha3module.c - _sha3module - -Modules/_sqlite/module.c - _sqlite3module - -Modules/_ssl.c - PySocketModule - -Modules/_ssl.c - _sslmodule - -Modules/_statisticsmodule.c - statisticsmodule - -Modules/_struct.c - _structmodule - -Modules/_tkinter.c - _tkintermodule - -Modules/_uuidmodule.c - uuidmodule - -Modules/_xxsubinterpretersmodule.c - interpretersmodule - -Modules/_zoneinfo.c - zoneinfomodule - -Modules/arraymodule.c - arraymodule - -Modules/audioop.c - audioopmodule - -Modules/binascii.c - binasciimodule - -Modules/cjkcodecs/multibytecodec.c - _multibytecodecmodule - -Modules/cmathmodule.c - cmathmodule - -Modules/fcntlmodule.c - fcntlmodule - -Modules/grpmodule.c - grpmodule - -Modules/mathmodule.c - mathmodule - -Modules/md5module.c - _md5module - -Modules/mmapmodule.c - mmapmodule - -Modules/nismodule.c - nismodule - -Modules/ossaudiodev.c - ossaudiodevmodule - -Modules/pyexpat.c - pyexpatmodule - -Modules/readline.c - readlinemodule - -Modules/resource.c - resourcemodule - -Modules/selectmodule.c - selectmodule - -Modules/sha1module.c - _sha1module - -Modules/sha256module.c - _sha256module - -Modules/sha512module.c - _sha512module - -Modules/socketmodule.c - socketmodule - -Modules/spwdmodule.c - spwdmodule - -Modules/syslogmodule.c - syslogmodule - -Modules/termios.c - termiosmodule - -Modules/unicodedata.c - unicodedata_module - -Modules/xxlimited.c - xxmodule - -Modules/xxmodule.c - xxmodule - -Modules/xxsubtype.c - xxsubtypemodule - -Modules/zlibmodule.c - zlibmodule - - #----------------------- # static types @@ -811,9 +594,6 @@ Modules/_asynciomodule.c - FutureType - Modules/_asynciomodule.c - PyRunningLoopHolder_Type - Modules/_asynciomodule.c - TaskStepMethWrapper_Type - Modules/_asynciomodule.c - TaskType - -Modules/_csv.c - Dialect_Type - -Modules/_csv.c - Reader_Type - -Modules/_csv.c - Writer_Type - Modules/_ctypes/_ctypes.c - DictRemover_Type - Modules/_ctypes/_ctypes.c - PyCArrayType_Type - Modules/_ctypes/_ctypes.c - PyCArray_Type - @@ -824,7 +604,6 @@ Modules/_ctypes/_ctypes.c - PyCPointerType_Type - Modules/_ctypes/_ctypes.c - PyCPointer_Type - Modules/_ctypes/_ctypes.c - PyCSimpleType_Type - Modules/_ctypes/_ctypes.c - PyCStructType_Type - -Modules/_ctypes/_ctypes.c - PyComError_Type - Modules/_ctypes/_ctypes.c - Simple_Type - Modules/_ctypes/_ctypes.c - StructParam_Type - Modules/_ctypes/_ctypes.c - Struct_Type - @@ -850,35 +629,16 @@ Modules/_elementtree.c - ElementIter_Type - Modules/_elementtree.c - Element_Type - Modules/_elementtree.c - TreeBuilder_Type - Modules/_elementtree.c - XMLParser_Type - -Modules/_multiprocessing/semaphore.c - _PyMp_SemLockType - Modules/_pickle.c - Pdata_Type - Modules/_pickle.c - PicklerMemoProxyType - Modules/_pickle.c - Pickler_Type - Modules/_pickle.c - UnpicklerMemoProxyType - Modules/_pickle.c - Unpickler_Type - -Modules/_queuemodule.c - PySimpleQueueType - -Modules/_sre.c - Match_Type - -Modules/_sre.c - Pattern_Type - -Modules/_sre.c - Scanner_Type - -Modules/_ssl.c - PySSLContext_Type - -Modules/_ssl.c - PySSLMemoryBIO_Type - -Modules/_ssl.c - PySSLSession_Type - -Modules/_ssl.c - PySSLSocket_Type - Modules/_xxsubinterpretersmodule.c - ChannelIDtype - Modules/_zoneinfo.c - PyZoneInfo_ZoneInfoType - -Modules/arraymodule.c - Arraytype - -Modules/arraymodule.c - PyArrayIter_Type - -Modules/cjkcodecs/multibytecodec.c - MultibyteCodec_Type - -Modules/cjkcodecs/multibytecodec.c - MultibyteIncrementalDecoder_Type - -Modules/cjkcodecs/multibytecodec.c - MultibyteIncrementalEncoder_Type - -Modules/cjkcodecs/multibytecodec.c - MultibyteStreamReader_Type - -Modules/cjkcodecs/multibytecodec.c - MultibyteStreamWriter_Type - -Modules/mmapmodule.c - mmap_object_type - Modules/ossaudiodev.c - OSSAudioType - Modules/ossaudiodev.c - OSSMixerType - -Modules/pyexpat.c - Xmlparsetype - Modules/socketmodule.c - sock_type - -Modules/xxlimited_35.c - Xxo_Type - Modules/xxmodule.c - Null_Type - Modules/xxmodule.c - Str_Type - Modules/xxmodule.c - Xxo_Type - @@ -888,31 +648,18 @@ Modules/xxsubtype.c - spamlist_type - #----------------------- # non-static types - initialized once -# structseq types -Modules/_cursesmodule.c - NcursesVersionType - -Modules/resource.c - StructRUsageType - -Modules/spwdmodule.c - StructSpwdType - - # heap types Modules/_decimal/_decimal.c - DecimalTuple - Modules/_decimal/_decimal.c - PyDecSignalDict_Type - Modules/_tkinter.c - PyTclObject_Type - Modules/_tkinter.c - Tkapp_Type - Modules/_tkinter.c - Tktt_Type - -Modules/xxlimited.c - Xxo_Type - +Modules/xxlimited_35.c - Xxo_Type - # exception types Modules/_ctypes/_ctypes.c - PyExc_ArgError - Modules/_cursesmodule.c - PyCursesError - Modules/_decimal/_decimal.c - DecimalException - -Modules/_queuemodule.c - EmptyError - -Modules/_ssl.c - PySSLErrorObject - -Modules/_ssl.c - PySSLCertVerificationErrorObject - -Modules/_ssl.c - PySSLZeroReturnErrorObject - -Modules/_ssl.c - PySSLWantReadErrorObject - -Modules/_ssl.c - PySSLWantWriteErrorObject - -Modules/_ssl.c - PySSLSyscallErrorObject - -Modules/_ssl.c - PySSLEOFErrorObject - Modules/_tkinter.c - Tkinter_TclError - Modules/_xxsubinterpretersmodule.c - ChannelError - Modules/_xxsubinterpretersmodule.c - ChannelNotFoundError - @@ -921,11 +668,9 @@ Modules/_xxsubinterpretersmodule.c - ChannelEmptyError - Modules/_xxsubinterpretersmodule.c - ChannelNotEmptyError - Modules/_xxsubinterpretersmodule.c - RunFailedError - Modules/ossaudiodev.c - OSSAudioError - -Modules/pyexpat.c - ErrorObject - Modules/socketmodule.c - socket_herror - Modules/socketmodule.c - socket_gaierror - -Modules/socketmodule.c - socket_timeout - -Modules/xxlimited.c - ErrorObject - +Modules/xxlimited_35.c - ErrorObject - Modules/xxmodule.c - ErrorObject - #----------------------- @@ -934,43 +679,17 @@ Modules/xxmodule.c - ErrorObject - # _Py_IDENTIFIER (global) Modules/_asynciomodule.c - PyId___asyncio_running_event_loop__ - Modules/_asynciomodule.c - PyId__asyncio_future_blocking - -Modules/_asynciomodule.c - PyId__check_future static - Modules/_asynciomodule.c - PyId_add_done_callback - Modules/_asynciomodule.c - PyId_call_soon - Modules/_asynciomodule.c - PyId_cancel - Modules/_asynciomodule.c - PyId_get_event_loop - Modules/_asynciomodule.c - PyId_throw - -Modules/_bisectmodule.c - PyId_insert - Modules/_datetimemodule.c - PyId_as_integer_ratio - Modules/_datetimemodule.c - PyId_fromutc - Modules/_datetimemodule.c - PyId_isoformat - Modules/_datetimemodule.c - PyId_strftime - -Modules/_sqlite/connection.c - PyId_cursor - -Modules/cjkcodecs/multibytecodec.c - PyId_write - -Modules/unicodedata.c - PyId_NFC - -Modules/unicodedata.c - PyId_NFD - -Modules/unicodedata.c - PyId_NFKC - -Modules/unicodedata.c - PyId_NFKD - # _Py_IDENTIFIER (local) -Modules/_json.c _encoded_const PyId_false - -Modules/_json.c _encoded_const PyId_null - -Modules/_json.c _encoded_const PyId_true - -Modules/_json.c encoder_listencode_dict PyId_close_dict - -Modules/_json.c encoder_listencode_dict PyId_empty_dict - -Modules/_json.c encoder_listencode_dict PyId_open_dict - -Modules/_json.c encoder_listencode_list PyId_close_array - -Modules/_json.c encoder_listencode_list PyId_empty_array - -Modules/_json.c encoder_listencode_list PyId_open_array - -Modules/_json.c raise_errmsg PyId_JSONDecodeError - -Modules/_json.c raise_errmsg PyId_decoder - -Modules/_sqlite/connection.c final_callback PyId_finalize - -Modules/_sqlite/connection.c pysqlite_connection_execute_impl PyId_execute - -Modules/_sqlite/connection.c pysqlite_connection_executemany_impl PyId_executemany - -Modules/_sqlite/connection.c pysqlite_connection_executescript PyId_executescript - -Modules/_sqlite/connection.c pysqlite_connection_iterdump_impl PyId__iterdump - -Modules/_sqlite/module.c pysqlite_register_converter_impl PyId_upper - -Modules/pyexpat.c pyexpat_xmlparser_ParseFile_impl PyId_read - Modules/_asynciomodule.c FutureObj_finalize PyId_call_exception_handler - Modules/_asynciomodule.c FutureObj_finalize PyId_exception - Modules/_asynciomodule.c FutureObj_finalize PyId_future - @@ -979,7 +698,6 @@ Modules/_asynciomodule.c FutureObj_finalize PyId_source_traceback - Modules/_asynciomodule.c FutureObj_get_state PyId_CANCELLED - Modules/_asynciomodule.c FutureObj_get_state PyId_FINISHED - Modules/_asynciomodule.c FutureObj_get_state PyId_PENDING - -Modules/_asynciomodule.c FutureObj_repr PyId__repr_info - Modules/_asynciomodule.c TaskObj_finalize PyId_call_exception_handler - Modules/_asynciomodule.c TaskObj_finalize PyId_message - Modules/_asynciomodule.c TaskObj_finalize PyId_source_traceback - @@ -989,7 +707,6 @@ Modules/_asynciomodule.c get_future_loop PyId__loop - Modules/_asynciomodule.c get_future_loop PyId_get_loop - Modules/_asynciomodule.c register_task PyId_add - Modules/_asynciomodule.c unregister_task PyId_discard - -Modules/_csv.c csv_writer PyId_write - Modules/_ctypes/_ctypes.c CDataType_from_param PyId__as_parameter_ - Modules/_ctypes/_ctypes.c PyCArrayType_new PyId__length_ - Modules/_ctypes/_ctypes.c PyCArrayType_new PyId__type_ - @@ -1021,15 +738,12 @@ Modules/_cursesmodule.c _curses_getwin PyId_read - Modules/_cursesmodule.c _curses_window_putwin PyId_write - Modules/_cursesmodule.c update_lines_cols PyId_COLS - Modules/_cursesmodule.c update_lines_cols PyId_LINES - -Modules/_datetimemodule.c build_struct_time PyId_struct_time - Modules/_datetimemodule.c call_tzname PyId_tzname - Modules/_datetimemodule.c date_strftime PyId_timetuple - Modules/_datetimemodule.c date_today PyId_fromtimestamp - Modules/_datetimemodule.c datetime_strptime PyId__strptime_datetime - Modules/_datetimemodule.c make_Zreplacement PyId_replace - -Modules/_datetimemodule.c time_time PyId_time - Modules/_datetimemodule.c tzinfo_reduce PyId___getinitargs__ - -Modules/_datetimemodule.c tzinfo_reduce PyId___getstate__ - Modules/_elementtree.c _elementtree_Element_find_impl PyId_find - Modules/_elementtree.c _elementtree_Element_findall_impl PyId_findall - Modules/_elementtree.c _elementtree_Element_findtext_impl PyId_findtext - @@ -1038,225 +752,27 @@ Modules/_elementtree.c expat_start_doctype_handler PyId_doctype - Modules/_elementtree.c treebuilder_add_subelement PyId_append - Modules/_elementtree.c treebuilder_flush_data PyId_tail - Modules/_elementtree.c treebuilder_flush_data PyId_text - -Modules/_gdbmmodule.c gdbm__exit__ PyId_close - -Modules/_lzmamodule.c build_filter_spec PyId_dict_size - -Modules/_lzmamodule.c build_filter_spec PyId_dist - -Modules/_lzmamodule.c build_filter_spec PyId_id - -Modules/_lzmamodule.c build_filter_spec PyId_lc - -Modules/_lzmamodule.c build_filter_spec PyId_lp - -Modules/_lzmamodule.c build_filter_spec PyId_pb - -Modules/_lzmamodule.c build_filter_spec PyId_start_offset - -Modules/_operator.c methodcaller_reduce PyId_partial - -Modules/_pickle.c _Pickle_InitState PyId_getattr - -Modules/_pickle.c _Pickler_SetOutputStream PyId_write - -Modules/_pickle.c _Unpickler_SetInputStream PyId_peek - -Modules/_pickle.c _Unpickler_SetInputStream PyId_read - -Modules/_pickle.c _Unpickler_SetInputStream PyId_readinto - -Modules/_pickle.c _Unpickler_SetInputStream PyId_readline - -Modules/_pickle.c _pickle_Pickler___init___impl PyId_dispatch_table - -Modules/_pickle.c _pickle_Pickler___init___impl PyId_persistent_id - -Modules/_pickle.c _pickle_Unpickler___init___impl PyId_persistent_load - -Modules/_pickle.c do_append PyId_append - -Modules/_pickle.c do_append PyId_extend - -Modules/_pickle.c dump PyId_reducer_override - -Modules/_pickle.c find_class PyId_find_class - -Modules/_pickle.c get_class PyId___class__ - -Modules/_pickle.c instantiate PyId___getinitargs__ - -Modules/_pickle.c instantiate PyId___new__ - -Modules/_pickle.c load_additems PyId_add - -Modules/_pickle.c load_build PyId___dict__ - -Modules/_pickle.c load_build PyId___setstate__ - -Modules/_pickle.c save PyId___reduce__ - -Modules/_pickle.c save PyId___reduce_ex__ - -Modules/_pickle.c save_bytes PyId_latin1 - -Modules/_pickle.c save_dict PyId_items - -Modules/_pickle.c save_global PyId___name__ - -Modules/_pickle.c save_global PyId___qualname__ - -Modules/_pickle.c save_reduce PyId___name__ - -Modules/_pickle.c save_reduce PyId___new__ - -Modules/_pickle.c save_reduce PyId___newobj__ - -Modules/_pickle.c save_reduce PyId___newobj_ex__ - -Modules/_pickle.c whichmodule PyId___main__ - -Modules/_pickle.c whichmodule PyId___module__ - -Modules/_pickle.c whichmodule PyId_modules - -Modules/_sqlite/connection.c _pysqlite_final_callback PyId_finalize - -Modules/_sqlite/connection.c pysqlite_connection_create_collation PyId_upper - -Modules/_sqlite/connection.c pysqlite_connection_iterdump PyId__iterdump - -Modules/_sqlite/connection.c pysqlite_connection_set_isolation_level PyId_upper - -Modules/_sqlite/cursor.c _pysqlite_get_converter PyId_upper - -Modules/_sqlite/microprotocols.c pysqlite_microprotocols_adapt PyId___adapt__ - -Modules/_sqlite/microprotocols.c pysqlite_microprotocols_adapt PyId___conform__ - -Modules/_sqlite/module.c module_register_converter PyId_upper - -Modules/_ssl.c fill_and_set_sslerror PyId_library - -Modules/_ssl.c fill_and_set_sslerror PyId_reason - -Modules/_ssl.c fill_and_set_sslerror PyId_verify_code - -Modules/_ssl.c fill_and_set_sslerror PyId_verify_message - -Modules/arraymodule.c array_array___reduce_ex__ PyId___dict__ - -Modules/arraymodule.c array_array___reduce_ex__ PyId__array_reconstructor - -Modules/arraymodule.c array_array_fromfile_impl PyId_read - -Modules/arraymodule.c array_array_tofile PyId_write - -Modules/arraymodule.c array_arrayiterator___reduce___impl PyId_iter - -Modules/mathmodule.c math_ceil PyId___ceil__ - -Modules/mathmodule.c math_floor PyId___floor__ - -Modules/mathmodule.c math_trunc PyId___trunc__ - -Modules/mmapmodule.c mmap__exit__method PyId_close - +Modules/_json.c _encoded_const PyId_false - +Modules/_json.c _encoded_const PyId_null - +Modules/_json.c _encoded_const PyId_true - +Modules/_json.c raise_errmsg PyId_JSONDecodeError - +Modules/_json.c raise_errmsg PyId_decoder - Modules/ossaudiodev.c oss_exit PyId_close - -Modules/pyexpat.c pyexpat_xmlparser_ParseFile PyId_read - - -# _Py_static_string -Modules/_pickle.c get_dotted_path PyId_dot - # manually cached PyUnicodeOjbect Modules/_asynciomodule.c - context_kwname - Modules/_ctypes/callproc.c _ctypes_get_errobj error_object_name - Modules/_ctypes/_ctypes.c CreateSwappedType suffix - -Modules/_json.c _encoded_const s_null - -Modules/_json.c _encoded_const s_true - -Modules/_json.c _encoded_const s_false - -Modules/_json.c encoder_listencode_dict open_dict - -Modules/_json.c encoder_listencode_dict close_dict - -Modules/_json.c encoder_listencode_dict empty_dict - -Modules/_json.c encoder_listencode_list open_array - -Modules/_json.c encoder_listencode_list close_array - -Modules/_json.c encoder_listencode_list empty_array - - -# _PyArg_Parser -Modules/clinic/_asynciomodule.c.h _asyncio_Future___init__ _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Future_add_done_callback _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Future_cancel _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Task___init__ _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Task_cancel _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Task_get_stack _parser - -Modules/clinic/_asynciomodule.c.h _asyncio_Task_print_stack _parser - -Modules/clinic/_asynciomodule.c.h _asyncio__enter_task _parser - -Modules/clinic/_asynciomodule.c.h _asyncio__get_event_loop _parser - -Modules/clinic/_asynciomodule.c.h _asyncio__leave_task _parser - -Modules/clinic/_asynciomodule.c.h _asyncio__register_task _parser - -Modules/clinic/_asynciomodule.c.h _asyncio__unregister_task _parser - -Modules/clinic/_bisectmodule.c.h _bisect_bisect_left _parser - -Modules/clinic/_bisectmodule.c.h _bisect_bisect_right _parser - -Modules/clinic/_bisectmodule.c.h _bisect_insort_left _parser - -Modules/clinic/_bisectmodule.c.h _bisect_insort_right _parser - -Modules/clinic/_bz2module.c.h _bz2_BZ2Decompressor_decompress _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_bottom _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_hide _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_move _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_replace _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_set_userptr _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_show _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_top _parser - -Modules/clinic/_curses_panel.c.h _curses_panel_panel_userptr _parser - -Modules/clinic/_cursesmodule.c.h _curses_setupterm _parser - -Modules/clinic/_datetimemodule.c.h datetime_datetime_now _parser - -Modules/clinic/_datetimemodule.c.h iso_calendar_date_new _parser - -Modules/clinic/_dbmmodule.c.h _dbm_dbm_get _parser - -Modules/clinic/_dbmmodule.c.h _dbm_dbm_keys _parser - -Modules/clinic/_dbmmodule.c.h _dbm_dbm_setdefault _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_find _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_findall _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_findtext _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_get _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_iter _parser - -Modules/clinic/_elementtree.c.h _elementtree_Element_iterfind _parser - -Modules/clinic/_elementtree.c.h _elementtree_TreeBuilder___init__ _parser - -Modules/clinic/_elementtree.c.h _elementtree_XMLParser___init__ _parser - -Modules/clinic/_gdbmmodule.c.h _gdbm_gdbm_firstkey _parser - -Modules/clinic/_gdbmmodule.c.h _gdbm_gdbm_keys _parser - -Modules/clinic/_gdbmmodule.c.h _gdbm_gdbm_nextkey _parser - -Modules/clinic/_gdbmmodule.c.h _gdbm_gdbm_reorganize _parser - -Modules/clinic/_gdbmmodule.c.h _gdbm_gdbm_sync _parser - -Modules/clinic/_hashopenssl.c.h EVP_new _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_HMAC_update _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_hmac_new _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_hmac_singleshot _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_md5 _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_sha1 _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_sha224 _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_sha256 _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_sha384 _parser - -Modules/clinic/_hashopenssl.c.h _hashlib_openssl_sha512 _parser - -Modules/clinic/_hashopenssl.c.h pbkdf2_hmac _parser - -Modules/clinic/_lsprof.c.h _lsprof_Profiler_getstats _parser - -Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor___init__ _parser - -Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor_decompress _parser - -Modules/clinic/_opcode.c.h _opcode_stack_effect _parser - -Modules/clinic/_pickle.c.h _pickle_Pickler___init__ _parser - -Modules/clinic/_pickle.c.h _pickle_Unpickler___init__ _parser - -Modules/clinic/_pickle.c.h _pickle_dump _parser - -Modules/clinic/_pickle.c.h _pickle_dumps _parser - -Modules/clinic/_pickle.c.h _pickle_load _parser - -Modules/clinic/_pickle.c.h _pickle_loads _parser - -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_get _parser - -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_get_nowait _parser - -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put _parser - -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put_nowait _parser - -Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_bio _parser - -Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_socket _parser - -Modules/clinic/_ssl.c.h _ssl__SSLContext_get_ca_certs _parser - -Modules/clinic/_ssl.c.h _ssl__SSLContext_load_cert_chain _parser - -Modules/clinic/_ssl.c.h _ssl__SSLContext_load_verify_locations _parser - -Modules/clinic/_ssl.c.h _ssl__SSLSocket_get_channel_binding _parser - -Modules/clinic/_ssl.c.h _ssl_txt2obj _parser - -Modules/clinic/_struct.c.h Struct___init__ _parser - -Modules/clinic/_struct.c.h Struct_unpack_from _parser - -Modules/clinic/_struct.c.h unpack_from _parser - -Modules/clinic/_testmultiphase.c.h _testmultiphase_StateAccessType_get_count _parser - -Modules/clinic/_testmultiphase.c.h _testmultiphase_StateAccessType_get_defining_module _parser - -Modules/clinic/_testmultiphase.c.h _testmultiphase_StateAccessType_getmodulebydef_bad_def _parser - -Modules/clinic/_testmultiphase.c.h _testmultiphase_StateAccessType_increment_count_clinic _parser - -Modules/clinic/_winapi.c.h _winapi_ConnectNamedPipe _parser - -Modules/clinic/_winapi.c.h _winapi_GetFileType _parser - -Modules/clinic/_winapi.c.h _winapi_ReadFile _parser - -Modules/clinic/_winapi.c.h _winapi_WriteFile _parser - -Modules/clinic/_winapi.c.h _winapi__mimetypes_read_windows_registry _parser - -Modules/clinic/arraymodule.c.h array_array_extend _parser - -Modules/clinic/binascii.c.h binascii_a2b_base64 _parser - -Modules/clinic/binascii.c.h binascii_a2b_qp _parser - -Modules/clinic/binascii.c.h binascii_b2a_base64 _parser - -Modules/clinic/binascii.c.h binascii_b2a_hex _parser - -Modules/clinic/binascii.c.h binascii_b2a_qp _parser - -Modules/clinic/binascii.c.h binascii_b2a_uu _parser - -Modules/clinic/binascii.c.h binascii_hexlify _parser - -Modules/clinic/cmathmodule.c.h cmath_isclose _parser - -Modules/clinic/grpmodule.c.h grp_getgrgid _parser - -Modules/clinic/grpmodule.c.h grp_getgrnam _parser - -Modules/clinic/mathmodule.c.h math_isclose _parser - -Modules/clinic/mathmodule.c.h math_prod _parser - -Modules/clinic/md5module.c.h MD5Type_copy _parser - -Modules/clinic/md5module.c.h _md5_md5 _parser - -Modules/clinic/overlapped.c.h _overlapped_Overlapped _parser - -Modules/clinic/pyexpat.c.h pyexpat_ParserCreate _parser - -Modules/clinic/pyexpat.c.h pyexpat_xmlparser_ExternalEntityParserCreate _parser - -Modules/clinic/pyexpat.c.h pyexpat_xmlparser_Parse _parser - -Modules/clinic/pyexpat.c.h pyexpat_xmlparser_ParseFile _parser - -Modules/clinic/sha1module.c.h SHA1Type_copy _parser - -Modules/clinic/sha1module.c.h _sha1_sha1 _parser - -Modules/clinic/sha256module.c.h SHA256Type_copy _parser - -Modules/clinic/sha256module.c.h _sha256_sha224 _parser - -Modules/clinic/sha256module.c.h _sha256_sha256 _parser - -Modules/clinic/sha512module.c.h SHA512Type_copy _parser - -Modules/clinic/sha512module.c.h _sha512_sha384 _parser - -Modules/clinic/sha512module.c.h _sha512_sha512 _parser - -Modules/clinic/zlibmodule.c.h zlib_Compress_compress _parser - -Modules/clinic/zlibmodule.c.h zlib_Compress_flush _parser - -Modules/clinic/zlibmodule.c.h zlib_Decompress_decompress _parser - -Modules/clinic/zlibmodule.c.h zlib_Decompress_flush _parser - -Modules/clinic/zlibmodule.c.h zlib_compress _parser - -Modules/clinic/zlibmodule.c.h zlib_compressobj _parser - -Modules/clinic/zlibmodule.c.h zlib_decompress _parser - -Modules/clinic/zlibmodule.c.h zlib_decompressobj _parser - # other - during module init Modules/_asynciomodule.c - asyncio_mod - Modules/_asynciomodule.c - traceback_extract_stack - Modules/_asynciomodule.c - asyncio_future_repr_func - -Modules/_asynciomodule.c - asyncio_future_repr_info_func - Modules/_asynciomodule.c - asyncio_get_event_loop_policy - Modules/_asynciomodule.c - asyncio_iscoroutine_func - Modules/_asynciomodule.c - asyncio_task_get_stack_func - Modules/_asynciomodule.c - asyncio_task_print_stack_func - Modules/_asynciomodule.c - asyncio_task_repr_func - -Modules/_asynciomodule.c - asyncio_task_repr_info_func - Modules/_asynciomodule.c - asyncio_InvalidStateError - Modules/_asynciomodule.c - asyncio_CancelledError - Modules/_zoneinfo.c - io_open - @@ -1280,7 +796,6 @@ Modules/_datetimemodule.c - us_per_hour - Modules/_datetimemodule.c - us_per_day - Modules/_datetimemodule.c - us_per_week - Modules/_datetimemodule.c - seconds_per_day - -Modules/_decimal/_decimal.c PyInit__decimal capsule - Modules/_decimal/_decimal.c - basic_context_template - Modules/_decimal/_decimal.c - current_context_var - Modules/_decimal/_decimal.c - default_context_template - @@ -1288,18 +803,7 @@ Modules/_decimal/_decimal.c - extended_context_template - Modules/_decimal/_decimal.c - round_map - Modules/_decimal/_decimal.c - Rational - Modules/_decimal/_decimal.c - SignalTuple - -Modules/_json.c raise_errmsg JSONDecodeError - -Modules/_sqlite/microprotocols.c - psyco_adapters - -Modules/_sqlite/module.h - _pysqlite_converters - -Modules/_ssl.c - err_codes_to_names - -Modules/_ssl.c - err_names_to_codes - -Modules/_ssl.c - lib_codes_to_names - -# XXX This should have been found by the analyzer but wasn't: -Modules/_ssl.c - _ssl_locks - -Modules/_struct.c - cache - -Modules/arraymodule.c array_array___reduce_ex__ array_reconstructor - Modules/arraymodule.c array_array___reduce_ex___impl array_reconstructor - -Modules/cjkcodecs/cjkcodecs.h getmultibytecodec cofunc - # state Modules/_asynciomodule.c - cached_running_holder - @@ -1317,7 +821,6 @@ Modules/_tkinter.c - trbInCmd - Modules/_zoneinfo.c - TIMEDELTA_CACHE - Modules/_zoneinfo.c - ZONEINFO_WEAK_CACHE - Modules/syslogmodule.c - S_ident_o - -Modules/xxlimited_35.c - ErrorObject - ################################## @@ -1339,32 +842,20 @@ Modules/_cursesmodule.c - initialised - Modules/_cursesmodule.c - initialised_setupterm - Modules/_cursesmodule.c - initialisedcolors - Modules/_cursesmodule.c - screen_encoding - -Modules/_cursesmodule.c PyInit__curses PyCurses_API - -Modules/_datetimemodule.c - CAPI - -Modules/_decimal/_decimal.c PyInit__decimal initialized - Modules/_decimal/_decimal.c - _py_long_multiply - Modules/_decimal/_decimal.c - _py_long_floor_divide - Modules/_decimal/_decimal.c - _py_long_power - Modules/_decimal/_decimal.c - _py_float_abs - Modules/_decimal/_decimal.c - _py_long_bit_length - Modules/_decimal/_decimal.c - _py_float_as_integer_ratio - -Modules/_decimal/_decimal.c - _decimal_api - Modules/_elementtree.c - expat_capi - -Modules/_sqlite/module.h - _pysqlite_enable_callback_tracebacks - -Modules/_sqlite/module.h - pysqlite_BaseTypeAdapted - -Modules/_ssl.c - _ssl_locks_count - Modules/cjkcodecs/cjkcodecs.h - codec_list - Modules/cjkcodecs/cjkcodecs.h - mapping_list - -Modules/getaddrinfo.c - gai_afdl - -Modules/pyexpat.c PyInit_pyexpat capi - Modules/readline.c - libedit_append_replace_history_offset - Modules/readline.c - using_libedit_emulation - Modules/readline.c - libedit_history_start - -Modules/resource.c - initialized - Modules/socketmodule.c - accept4_works - Modules/socketmodule.c - sock_cloexec_works - -Modules/socketmodule.c - PySocketModuleAPI - -Modules/spwdmodule.c - initialized - #----------------------- # state @@ -1398,4 +889,3 @@ Modules/rotatingtree.c - random_stream - Modules/rotatingtree.c - random_value - Modules/socketmodule.c - defaulttimeout - Modules/syslogmodule.c - S_log_open - -Modules/clinic/_asynciomodule.c.h _asyncio_Task__check_future _parser - diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index a395775e8f1b2ff..b6508a0c4991069 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -2,10 +2,18 @@ filename funcname name reason #??? - somevar ??? ################################## -# ignored by design +# mutable but known to be safe Python/pylifecycle.c - _PyRuntime - +# All uses of _PyArg_Parser are handled in c-analyzr/cpython/_analyzer.py. + +#----------------------- +# others + +# XXX The analyzer should have ignored these. +Modules/_io/_iomodule.c - _PyIO_Module - +Modules/_sqlite/module.c - _sqlite3module - ################################## # forward/extern references @@ -71,6 +79,58 @@ Objects/object.c - _PyLineIterator - Objects/object.c - _PyPositionsIterator - Python/importdl.h - _PyImport_DynLoadFiletab - +Modules/expat/xmlrole.c - prolog0 - +Modules/expat/xmlrole.c - prolog1 - +Modules/expat/xmlrole.c - prolog2 - +Modules/expat/xmlrole.c - doctype0 - +Modules/expat/xmlrole.c - doctype1 - +Modules/expat/xmlrole.c - doctype2 - +Modules/expat/xmlrole.c - doctype3 - +Modules/expat/xmlrole.c - doctype4 - +Modules/expat/xmlrole.c - doctype5 - +Modules/expat/xmlrole.c - internalSubset - +Modules/expat/xmlrole.c - entity0 - +Modules/expat/xmlrole.c - entity1 - +Modules/expat/xmlrole.c - entity2 - +Modules/expat/xmlrole.c - entity3 - +Modules/expat/xmlrole.c - entity4 - +Modules/expat/xmlrole.c - entity5 - +Modules/expat/xmlrole.c - entity6 - +Modules/expat/xmlrole.c - entity7 - +Modules/expat/xmlrole.c - entity8 - +Modules/expat/xmlrole.c - entity9 - +Modules/expat/xmlrole.c - entity10 - +Modules/expat/xmlrole.c - notation0 - +Modules/expat/xmlrole.c - notation1 - +Modules/expat/xmlrole.c - notation2 - +Modules/expat/xmlrole.c - notation3 - +Modules/expat/xmlrole.c - notation4 - +Modules/expat/xmlrole.c - attlist0 - +Modules/expat/xmlrole.c - attlist1 - +Modules/expat/xmlrole.c - attlist2 - +Modules/expat/xmlrole.c - attlist3 - +Modules/expat/xmlrole.c - attlist4 - +Modules/expat/xmlrole.c - attlist5 - +Modules/expat/xmlrole.c - attlist6 - +Modules/expat/xmlrole.c - attlist7 - +Modules/expat/xmlrole.c - attlist8 - +Modules/expat/xmlrole.c - attlist9 - +Modules/expat/xmlrole.c - element0 - +Modules/expat/xmlrole.c - element1 - +Modules/expat/xmlrole.c - element2 - +Modules/expat/xmlrole.c - element3 - +Modules/expat/xmlrole.c - element4 - +Modules/expat/xmlrole.c - element5 - +Modules/expat/xmlrole.c - element6 - +Modules/expat/xmlrole.c - element7 - +Modules/expat/xmlrole.c - externalSubset0 - +Modules/expat/xmlrole.c - externalSubset1 - +Modules/expat/xmlrole.c - condSect0 - +Modules/expat/xmlrole.c - condSect1 - +Modules/expat/xmlrole.c - condSect2 - +Modules/expat/xmlrole.c - declClose - +Modules/expat/xmlrole.c - error - + ################################## # test code @@ -274,1233 +334,8 @@ Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput AST_LITERAL_EVAL_INITIALIZED # These are all variables that we will be leaving global. -#----------------------- -# keywords for PyArg_ParseTupleAndKeywords() -# "static char *name[]" -> "static const char * const name[]" - -Modules/cjkcodecs/multibytecodec.c - incnewkwarglist - -Modules/cjkcodecs/multibytecodec.c - streamkwarglist - -Modules/_csv.c - dialect_kws - -Modules/_datetimemodule.c date_fromisocalendar keywords - -Modules/_datetimemodule.c - date_kws - -Modules/_datetimemodule.c date_strftime keywords - -Modules/_datetimemodule.c datetime_astimezone keywords - -Modules/_datetimemodule.c datetime_combine keywords - -Modules/_datetimemodule.c datetime_fromtimestamp keywords - -Modules/_datetimemodule.c datetime_isoformat keywords - -Modules/_datetimemodule.c - datetime_kws - -Modules/_datetimemodule.c delta_new keywords - -Modules/_datetimemodule.c time_isoformat keywords - -Modules/_datetimemodule.c - time_kws - -Modules/_datetimemodule.c time_strftime keywords - -Modules/_datetimemodule.c - timezone_kws - -Modules/_decimal/_decimal.c context_init kwlist - -Modules/_decimal/_decimal.c ctxmanager_new kwlist - -Modules/_decimal/_decimal.c ctx_mpd_qpow kwlist - -Modules/_decimal/_decimal.c dec_mpd_class kwlist - -Modules/_decimal/_decimal.c dec_mpd_compare_total kwlist - -Modules/_decimal/_decimal.c dec_mpd_compare_total_mag kwlist - -Modules/_decimal/_decimal.c dec_mpd_isnormal kwlist - -Modules/_decimal/_decimal.c dec_mpd_issubnormal kwlist - -Modules/_decimal/_decimal.c dec_mpd_qand kwlist - -Modules/_decimal/_decimal.c dec_mpd_qcompare kwlist - -Modules/_decimal/_decimal.c dec_mpd_qcompare_signal kwlist - -Modules/_decimal/_decimal.c dec_mpd_qcopy_sign kwlist - -Modules/_decimal/_decimal.c dec_mpd_qexp kwlist - -Modules/_decimal/_decimal.c dec_mpd_qfma kwlist - -Modules/_decimal/_decimal.c dec_mpd_qinvert kwlist - -Modules/_decimal/_decimal.c dec_mpd_qln kwlist - -Modules/_decimal/_decimal.c dec_mpd_qlog10 kwlist - -Modules/_decimal/_decimal.c dec_mpd_qlogb kwlist - -Modules/_decimal/_decimal.c dec_mpd_qmax kwlist - -Modules/_decimal/_decimal.c dec_mpd_qmax_mag kwlist - -Modules/_decimal/_decimal.c dec_mpd_qmin kwlist - -Modules/_decimal/_decimal.c dec_mpd_qmin_mag kwlist - -Modules/_decimal/_decimal.c dec_mpd_qnext_minus kwlist - -Modules/_decimal/_decimal.c dec_mpd_qnext_plus kwlist - -Modules/_decimal/_decimal.c dec_mpd_qnext_toward kwlist - -Modules/_decimal/_decimal.c dec_mpd_qor kwlist - -Modules/_decimal/_decimal.c dec_mpd_qquantize kwlist - -Modules/_decimal/_decimal.c dec_mpd_qreduce kwlist - -Modules/_decimal/_decimal.c dec_mpd_qrem_near kwlist - -Modules/_decimal/_decimal.c dec_mpd_qrotate kwlist - -Modules/_decimal/_decimal.c dec_mpd_qscaleb kwlist - -Modules/_decimal/_decimal.c dec_mpd_qshift kwlist - -Modules/_decimal/_decimal.c dec_mpd_qsqrt kwlist - -Modules/_decimal/_decimal.c dec_mpd_qxor kwlist - -Modules/_decimal/_decimal.c dec_mpd_same_quantum kwlist - -Modules/_decimal/_decimal.c dec_mpd_to_eng kwlist - -Modules/_decimal/_decimal.c dec_new kwlist - -Modules/_decimal/_decimal.c PyDec_ToIntegralExact kwlist - -Modules/_decimal/_decimal.c PyDec_ToIntegralValue kwlist - -Modules/_elementtree.c element_setstate_from_Python kwlist - -Modules/faulthandler.c faulthandler_dump_traceback_later kwlist - -Modules/faulthandler.c faulthandler_dump_traceback_py kwlist - -Modules/faulthandler.c faulthandler_py_enable kwlist - -Modules/faulthandler.c faulthandler_register_py kwlist - -Modules/_functoolsmodule.c functools_cmp_to_key kwargs - -Modules/_functoolsmodule.c keyobject_call kwargs - -Modules/_functoolsmodule.c lru_cache_new keywords - -Modules/itertoolsmodule.c repeat_new kwargs - -Modules/_json.c encoder_call kwlist - -Modules/_json.c encoder_new kwlist - -Modules/_json.c scanner_call kwlist - -Modules/_json.c scanner_new kwlist - -Modules/_lsprof.c profiler_enable kwlist - -Modules/_lsprof.c profiler_init kwlist - -Modules/_lzmamodule.c Compressor_init arg_names - -Modules/_lzmamodule.c parse_filter_spec_bcj optnames - -Modules/_lzmamodule.c parse_filter_spec_delta optnames - -Modules/_lzmamodule.c parse_filter_spec_lzma optnames - -Modules/mmapmodule.c new_mmap_object keywords - -Modules/nismodule.c nis_cat kwlist - -Modules/nismodule.c nis_maps kwlist - -Modules/nismodule.c nis_match kwlist - -Modules/signalmodule.c signal_set_wakeup_fd kwlist - -Modules/socketmodule.c sock_initobj keywords - -Modules/socketmodule.c sock_recvfrom_into kwlist - -Modules/socketmodule.c sock_recv_into kwlist - -Modules/socketmodule.c sock_sendmsg_afalg keywords - -Modules/socketmodule.c socket_getaddrinfo kwnames - -Modules/_sqlite/connection.c pysqlite_connection_backup keywords - -Modules/_sqlite/connection.c pysqlite_connection_create_aggregate kwlist - -Modules/_sqlite/connection.c pysqlite_connection_create_function kwlist - -Modules/_sqlite/connection.c pysqlite_connection_cursor kwlist - -Modules/_sqlite/connection.c pysqlite_connection_init kwlist - -Modules/_sqlite/connection.c pysqlite_connection_set_authorizer kwlist - -Modules/_sqlite/connection.c pysqlite_connection_set_progress_handler kwlist - -Modules/_sqlite/connection.c pysqlite_connection_set_trace_callback kwlist - -Modules/_sqlite/cursor.c pysqlite_cursor_fetchmany kwlist - -Modules/_sqlite/module.c module_complete kwlist - -Modules/_sqlite/module.c module_connect kwlist - -Modules/_sqlite/module.c module_enable_shared_cache kwlist - -Modules/syslogmodule.c syslog_openlog keywords - -Modules/_xxsubinterpretersmodule.c channel_close kwlist - -Modules/_xxsubinterpretersmodule.c channel_destroy kwlist - -Modules/_xxsubinterpretersmodule.c channelid_new kwlist - -Modules/_xxsubinterpretersmodule.c channel_list_interpreters kwlist - -Modules/_xxsubinterpretersmodule.c channel_recv kwlist - -Modules/_xxsubinterpretersmodule.c channel_release kwlist - -Modules/_xxsubinterpretersmodule.c channel_send kwlist - -Modules/_xxsubinterpretersmodule.c interp_create kwlist - -Modules/_xxsubinterpretersmodule.c interp_destroy kwlist - -Modules/_xxsubinterpretersmodule.c interp_is_running kwlist - -Modules/_xxsubinterpretersmodule.c interp_run_string kwlist - -Modules/_xxsubinterpretersmodule.c object_is_shareable kwlist - -Modules/_zoneinfo.c zoneinfo_clear_cache kwlist - -Modules/_zoneinfo.c zoneinfo_from_file kwlist - -Modules/_zoneinfo.c zoneinfo_new kwlist - -Modules/_zoneinfo.c zoneinfo_no_cache kwlist - -Objects/exceptions.c ImportError_init kwlist - -Objects/interpreteridobject.c interpid_new kwlist - -Objects/weakrefobject.c weakref_call kwlist - -Objects/exceptions.c NameError_init kwlist - -Objects/exceptions.c AttributeError_init kwlist - -Python/_warnings.c warnings_warn_explicit kwd_list - -Python/bltinmodule.c builtin___import__ kwlist - -Python/bltinmodule.c min_max kwlist - -Python/bltinmodule.c zip_new kwlist - -Python/context.c contextvar_tp_new kwlist - -Python/sysmodule.c sys_getsizeof kwlist - -Python/sysmodule.c sys_set_asyncgen_hooks keywords - - -#----------------------- -# PyModuleDef - -Modules/_abc.c - _abcmodule - -Modules/_codecsmodule.c - codecsmodule - -Modules/_collectionsmodule.c - _collectionsmodule - -Modules/_functoolsmodule.c - _functools_module - -Modules/_io/_iomodule.c - _PyIO_Module - -Modules/_localemodule.c - _localemodule - -Modules/_multiprocessing/posixshmem.c - _posixshmemmodule - -Modules/_sqlite/module.h - _sqlite3module - -Modules/_sre/sre.c - sremodule - -Modules/_ssl.c - _sslmodule_def - -Modules/_ssl.h - _sslmodule_def - -Modules/_stat.c - statmodule - -Modules/_testcapi/heaptype.c - _testcapimodule - -Modules/_testmultiphase.c - def_module_state_shared - -Modules/_threadmodule.c - thread_module - -Modules/_tracemalloc.c - module_def - -Modules/_typingmodule.c - typingmodule - -Modules/_weakref.c - weakrefmodule - -Modules/atexitmodule.c - atexitmodule - -Modules/errnomodule.c - errnomodule - -Modules/faulthandler.c - module_def - -Modules/gcmodule.c - gcmodule - -Modules/itertoolsmodule.c - itertoolsmodule - -Modules/posixmodule.c - posixmodule - -Modules/pwdmodule.c - pwdmodule - -Modules/signalmodule.c - signal_module - -Modules/symtablemodule.c - symtablemodule - -Modules/timemodule.c - timemodule - -Modules/xxlimited_35.c - xxmodule - -Python/Python-ast.c - _astmodule - -Python/Python-tokenize.c - _tokenizemodule - -Python/_warnings.c - warnings_module - -Python/bltinmodule.c - builtinsmodule - -Python/import.c - imp_module - -Python/marshal.c - marshalmodule - -Python/sysmodule.c - sysmodule - - -#----------------------- -# PyModuleDef_Slot - -Modules/_abc.c - _abcmodule_slots - -Modules/_bisectmodule.c - bisect_slots - -Modules/_blake2/blake2module.c - _blake2_slots - -Modules/_bz2module.c - _bz2_slots - -Modules/_codecsmodule.c - _codecs_slots - -Modules/_collectionsmodule.c - collections_slots - -Modules/_contextvarsmodule.c - _contextvars_slots - -Modules/_cryptmodule.c - _crypt_slots - -Modules/_csv.c - csv_slots - -Modules/_curses_panel.c - _curses_slots - -Modules/_dbmmodule.c - _dbmmodule_slots - -Modules/_functoolsmodule.c - _functools_slots - -Modules/_gdbmmodule.c - _gdbm_module_slots - -Modules/_hashopenssl.c - hashlib_slots - -Modules/_heapqmodule.c - heapq_slots - -Modules/_json.c - _json_slots - -Modules/_localemodule.c - _locale_slots - -Modules/_lsprof.c - _lsprofslots - -Modules/_lzmamodule.c - lzma_slots - -Modules/_multiprocessing/multiprocessing.c - multiprocessing_slots - -Modules/_operator.c - operator_slots - -Modules/_posixsubprocess.c - _posixsubprocess_slots - -Modules/_queuemodule.c - queuemodule_slots - -Modules/_randommodule.c - _random_slots - -Modules/_scproxy.c - _scproxy_slots - -Modules/_sha3/sha3module.c - _sha3_slots - -Modules/_sqlite/module.c - module_slots - -Modules/_sre.c - sre_slots - -Modules/_sre/sre.c - sre_slots - -Modules/_ssl.c - sslmodule_slots - -Modules/_stat.c - stat_slots - -Modules/_statisticsmodule.c - _statisticsmodule_slots - -Modules/_struct.c - _structmodule_slots - -Modules/_threadmodule.c - thread_module_slots - -Modules/_typingmodule.c - _typingmodule_slots - -Modules/_uuidmodule.c - uuid_slots - -Modules/_weakref.c - weakref_slots - -Modules/_winapi.c - winapi_slots - -Modules/_zoneinfo.c - zoneinfomodule_slots - -Modules/arraymodule.c - arrayslots - -Modules/atexitmodule.c - atexit_slots - -Modules/audioop.c - audioop_slots - -Modules/binascii.c - binascii_slots - -Modules/cjkcodecs/cjkcodecs.h - _cjk_slots - -Modules/cjkcodecs/multibytecodec.c - _multibytecodec_slots - -Modules/cmathmodule.c - cmath_slots - -Modules/errnomodule.c - errno_slots - -Modules/faulthandler.c - faulthandler_slots - -Modules/fcntlmodule.c - fcntl_slots - -Modules/gcmodule.c - gcmodule_slots - -Modules/gcmodule.c - gcmodule_slots - -Modules/grpmodule.c - grpmodule_slots - -Modules/itertoolsmodule.c - itertoolsmodule_slots - -Modules/mathmodule.c - math_slots - -Modules/md5module.c - _md5_slots - -Modules/mmapmodule.c - mmap_slots - -Modules/nismodule.c - nis_slots - -Modules/overlapped.c - overlapped_slots - -Modules/posixmodule.c - posixmodile_slots - -Modules/pwdmodule.c - pwdmodule_slots - -Modules/pyexpat.c - pyexpat_slots - -Modules/resource.c - resource_slots - -Modules/selectmodule.c - _select_slots - -Modules/sha1module.c - _sha1_slots - -Modules/sha256module.c - _sha256_slots - -Modules/sha512module.c - _sha512_slots - -Modules/signalmodule.c - signal_slots - -Modules/spwdmodule.c - spwdmodule_slots - -Modules/symtablemodule.c - symtable_slots - -Modules/syslogmodule.c - syslog_slots - -Modules/termios.c - termios_slots - -Modules/timemodule.c - time_slots - -Modules/unicodedata.c - unicodedata_slots - -Modules/xxlimited.c - xx_slots - -Modules/xxlimited_35.c - xx_slots - -Modules/xxmodule.c - xx_slots - -Modules/xxsubtype.c - xxsubtype_slots - -Modules/zlibmodule.c - zlib_slots - -Python/Python-ast.c - astmodule_slots - -Python/Python-tokenize.c - tokenizemodule_slots - -Python/_warnings.c - warnings_slots - -Python/marshal.c - marshalmodule_slots - - -#----------------------- -# PyMethodDef and PyMethodDef[], for static types and modules - -Modules/_abc.c - _abcmodule_methods - -Modules/_abc.c - _destroy_def - -Modules/_asynciomodule.c - FutureIter_methods - -Modules/_asynciomodule.c - FutureType_methods - -Modules/_asynciomodule.c - TaskType_methods - -Modules/_asynciomodule.c - TaskWakeupDef - -Modules/_asynciomodule.c - asyncio_methods - -Modules/_bisectmodule.c - bisect_methods - -Modules/_blake2/blake2b_impl.c - py_blake2b_methods - -Modules/_blake2/blake2module.c - blake2mod_functions - -Modules/_blake2/blake2s_impl.c - py_blake2s_methods - -Modules/_bz2module.c - BZ2Compressor_methods - -Modules/_bz2module.c - BZ2Decompressor_methods - -Modules/_codecsmodule.c - _codecs_functions - -Modules/_collectionsmodule.c - collections_methods - -Modules/_collectionsmodule.c - defdict_methods - -Modules/_collectionsmodule.c - deque_methods - -Modules/_collectionsmodule.c - dequeiter_methods - -Modules/_collectionsmodule.c - tuplegetter_methods - -Modules/_contextvarsmodule.c - _contextvars_methods - -Modules/_cryptmodule.c - crypt_methods - -Modules/_csv.c - Reader_methods - -Modules/_csv.c - Writer_methods - -Modules/_csv.c - csv_methods - -Modules/_csv.c - dialect_methods - -Modules/_ctypes/_ctypes.c - Array_methods - -Modules/_ctypes/_ctypes.c - CDataType_methods - -Modules/_ctypes/_ctypes.c - PyCData_methods - -Modules/_ctypes/_ctypes.c - PyCPointerType_methods - -Modules/_ctypes/_ctypes.c - PyCSimpleType_methods - -Modules/_ctypes/_ctypes.c - Simple_methods - -Modules/_ctypes/_ctypes.c - c_char_p_method - -Modules/_ctypes/_ctypes.c - c_void_p_method - -Modules/_ctypes/_ctypes.c - c_wchar_p_method - -Modules/_ctypes/callproc.c - _ctypes_module_methods - -Modules/_ctypes/stgdict.c - PyCStgDict_methods - -Modules/_curses_panel.c - PyCursesPanel_Methods - -Modules/_curses_panel.c - PyCurses_methods - -Modules/_cursesmodule.c - PyCursesWindow_Methods - -Modules/_cursesmodule.c - PyCurses_methods - -Modules/_datetimemodule.c - date_methods - -Modules/_datetimemodule.c - datetime_methods - -Modules/_datetimemodule.c - delta_methods - -Modules/_datetimemodule.c - iso_calendar_date_methods - -Modules/_datetimemodule.c - module_methods - -Modules/_datetimemodule.c - time_methods - -Modules/_datetimemodule.c - timezone_methods - -Modules/_datetimemodule.c - tzinfo_methods - -Modules/_dbmmodule.c - dbm_methods - -Modules/_dbmmodule.c - dbmmodule_methods - -Modules/_decimal/_decimal.c - _decimal_methods - -Modules/_decimal/_decimal.c - context_methods - -Modules/_decimal/_decimal.c - ctxmanager_methods - -Modules/_decimal/_decimal.c - dec_methods - -Modules/_decimal/_decimal.c - signaldict_methods - -Modules/_elementtree.c - _functions - -Modules/_elementtree.c - element_methods - -Modules/_elementtree.c - treebuilder_methods - -Modules/_elementtree.c - xmlparser_methods - -Modules/_functoolsmodule.c - _functools_methods - -Modules/_functoolsmodule.c - lru_cache_methods - -Modules/_functoolsmodule.c - partial_methods - -Modules/_gdbmmodule.c - _gdbm_module_methods - -Modules/_gdbmmodule.c - gdbm_methods - -Modules/_hashopenssl.c - EVPXOF_methods - -Modules/_hashopenssl.c - EVP_functions - -Modules/_hashopenssl.c - EVP_methods - -Modules/_hashopenssl.c - HMAC_methods - -Modules/_heapqmodule.c - heapq_methods - -Modules/_io/_iomodule.c - module_methods - -Modules/_io/bufferedio.c - bufferediobase_methods - -Modules/_io/bufferedio.c - bufferedrandom_methods - -Modules/_io/bufferedio.c - bufferedreader_methods - -Modules/_io/bufferedio.c - bufferedrwpair_methods - -Modules/_io/bufferedio.c - bufferedwriter_methods - -Modules/_io/bytesio.c - bytesio_methods - -Modules/_io/fileio.c - fileio_methods - -Modules/_io/iobase.c - iobase_methods - -Modules/_io/iobase.c - rawiobase_methods - -Modules/_io/stringio.c - stringio_methods - -Modules/_io/textio.c - incrementalnewlinedecoder_methods - -Modules/_io/textio.c - textiobase_methods - -Modules/_io/textio.c - textiowrapper_methods - -Modules/_io/winconsoleio.c - winconsoleio_methods - -Modules/_json.c - speedups_methods - -Modules/_localemodule.c - PyLocale_Methods - -Modules/_lsprof.c - moduleMethods - -Modules/_lsprof.c - profiler_methods - -Modules/_lzmamodule.c - Compressor_methods - -Modules/_lzmamodule.c - Decompressor_methods - -Modules/_lzmamodule.c - lzma_methods - -Modules/_multiprocessing/multiprocessing.c - module_methods - -Modules/_multiprocessing/posixshmem.c - module_methods - -Modules/_multiprocessing/semaphore.c - semlock_methods - -Modules/_opcode.c - opcode_functions - -Modules/_operator.c - attrgetter_methods - -Modules/_operator.c - itemgetter_methods - -Modules/_operator.c - methodcaller_methods - -Modules/_operator.c - operator_methods - -Modules/_pickle.c - Pickler_methods - -Modules/_pickle.c - Unpickler_methods - -Modules/_pickle.c - pickle_methods - -Modules/_pickle.c - picklerproxy_methods - -Modules/_pickle.c - unpicklerproxy_methods - -Modules/_posixsubprocess.c - module_methods - -Modules/_queuemodule.c - simplequeue_methods - -Modules/_randommodule.c - random_methods - -Modules/_scproxy.c - mod_methods - -Modules/_sha3/sha3module.c - SHA3_methods - -Modules/_sha3/sha3module.c - SHAKE_methods - -Modules/_sqlite/blob.c - blob_methods static PyMethodDef[] -Modules/_sqlite/connection.c - connection_methods - -Modules/_sqlite/cursor.c - cursor_methods - -Modules/_sqlite/module.c - module_methods - -Modules/_sqlite/row.c - row_methods - -Modules/_sre/sre.c - _functions - -Modules/_sre/sre.c - pattern_methods - -Modules/_sre/sre.c - match_methods - -Modules/_sre/sre.c - scanner_methods - -Modules/_sre.c - _functions - -Modules/_sre.c - match_methods - -Modules/_sre.c - pattern_methods - -Modules/_sre.c - scanner_methods - -Modules/_ssl.c - PySSLMethods - -Modules/_ssl.c - PySSL_methods - -Modules/_ssl.c - context_methods - -Modules/_ssl.c - memory_bio_methods - -Modules/_ssl/cert.c - certificate_methods - -Modules/_stat.c - stat_methods - -Modules/_statisticsmodule.c - statistics_methods - -Modules/_struct.c - module_functions - -Modules/_struct.c - s_methods - -Modules/_struct.c - unpackiter_methods - -Modules/_testcapi/heaptype.c - TestMethods - -Modules/_testcapi/vectorcall.c - TestMethods - -Modules/_threadmodule.c - lock_methods - -Modules/_threadmodule.c - rlock_methods - -Modules/_threadmodule.c - thread_methods - -Modules/_threadmodule.c local_new wr_callback_def - -Modules/_tkinter.c - Tkapp_methods - -Modules/_tkinter.c - Tktt_methods - -Modules/_tkinter.c - moduleMethods - -Modules/_tracemalloc.c - module_methods - -Modules/_typingmodule.c - typing_methods - -Modules/_uuidmodule.c - uuid_methods - -Modules/_weakref.c - weakref_functions - -Modules/_winapi.c - overlapped_methods - -Modules/_winapi.c - winapi_functions - -Modules/_xxsubinterpretersmodule.c - module_functions - -Modules/_zoneinfo.c - module_methods - -Modules/_zoneinfo.c - zoneinfo_methods - -Modules/arraymodule.c - a_methods - -Modules/arraymodule.c - array_methods - -Modules/arraymodule.c - arrayiter_methods - -Modules/atexitmodule.c - atexit_methods - -Modules/audioop.c - audioop_methods - -Modules/binascii.c - binascii_module_methods - -Modules/cjkcodecs/cjkcodecs.h - __methods - -Modules/cjkcodecs/cjkcodecs.h - _cjk_methods - -Modules/cjkcodecs/multibytecodec.c - __methods - -Modules/cjkcodecs/multibytecodec.c - _multibytecodec_methods - -Modules/cjkcodecs/multibytecodec.c - mbidecoder_methods - -Modules/cjkcodecs/multibytecodec.c - mbiencoder_methods - -Modules/cjkcodecs/multibytecodec.c - mbstreamreader_methods - -Modules/cjkcodecs/multibytecodec.c - mbstreamwriter_methods - -Modules/cjkcodecs/multibytecodec.c - multibytecodec_methods - -Modules/cmathmodule.c - cmath_methods - -Modules/errnomodule.c - errno_methods - -Modules/faulthandler.c - module_methods - -Modules/fcntlmodule.c - fcntl_methods - -Modules/gcmodule.c - GcMethods - -Modules/getpath.c - getpath_methods - -Modules/getpath.c - getpath_nowarn_method - -Modules/getpath.c - getpath_warn_method - -Modules/grpmodule.c - grp_methods - -Modules/itertoolsmodule.c - _grouper_methods - -Modules/itertoolsmodule.c - accumulate_methods - -Modules/itertoolsmodule.c - chain_methods - -Modules/itertoolsmodule.c - combinations_methods - -Modules/itertoolsmodule.c - compress_methods - -Modules/itertoolsmodule.c - count_methods - -Modules/itertoolsmodule.c - cwr_methods - -Modules/itertoolsmodule.c - cycle_methods - -Modules/itertoolsmodule.c - dropwhile_methods - -Modules/itertoolsmodule.c - filterfalse_methods - -Modules/itertoolsmodule.c - groupby_methods - -Modules/itertoolsmodule.c - islice_methods - -Modules/itertoolsmodule.c - module_methods - -Modules/itertoolsmodule.c - permuations_methods - -Modules/itertoolsmodule.c - product_methods - -Modules/itertoolsmodule.c - repeat_methods - -Modules/itertoolsmodule.c - starmap_methods - -Modules/itertoolsmodule.c - takewhile_reduce_methods - -Modules/itertoolsmodule.c - tee_methods - -Modules/itertoolsmodule.c - teedataobject_methods - -Modules/itertoolsmodule.c - zip_longest_methods - -Modules/mathmodule.c - math_methods - -Modules/md5module.c - MD5_functions - -Modules/md5module.c - MD5_methods - -Modules/mmapmodule.c - mmap_object_methods - -Modules/nismodule.c - nis_methods - -Modules/ossaudiodev.c - oss_methods - -Modules/ossaudiodev.c - oss_mixer_methods - -Modules/ossaudiodev.c - ossaudiodev_methods - -Modules/overlapped.c - Overlapped_methods - -Modules/overlapped.c - overlapped_functions - -Modules/posixmodule.c - DirEntry_methods - -Modules/posixmodule.c - ScandirIterator_methods - -Modules/posixmodule.c - posix_methods - -Modules/pwdmodule.c - pwd_methods - -Modules/pyexpat.c - pyexpat_methods - -Modules/pyexpat.c - xmlparse_methods - -Modules/readline.c - readline_methods - -Modules/resource.c - resource_methods - -Modules/selectmodule.c - devpoll_methods - -Modules/selectmodule.c - kqueue_queue_methods - -Modules/selectmodule.c - poll_methods - -Modules/selectmodule.c - pyepoll_methods - -Modules/selectmodule.c - select_methods - -Modules/sha1module.c - SHA1_functions - -Modules/sha1module.c - SHA1_methods - -Modules/sha256module.c - SHA_functions - -Modules/sha256module.c - SHA_methods - -Modules/sha512module.c - SHA_functions - -Modules/sha512module.c - SHA_methods - -Modules/signalmodule.c - signal_methods - -Modules/socketmodule.c - sock_methods - -Modules/socketmodule.c - socket_methods - -Modules/spwdmodule.c - spwd_methods - -Modules/symtablemodule.c - symtable_methods - -Modules/syslogmodule.c - syslog_methods - -Modules/termios.c - termios_methods - -Modules/timemodule.c - time_methods - -Modules/unicodedata.c - unicodedata_functions - -Modules/xxlimited.c - Xxo_methods - -Modules/xxlimited.c - xx_methods - -Modules/xxlimited_35.c - Xxo_methods - -Modules/xxlimited_35.c - xx_methods - -Modules/xxmodule.c - Xxo_methods - -Modules/xxmodule.c - xx_methods - -Modules/xxsubtype.c - spamdict_methods - -Modules/xxsubtype.c - spamlist_methods - -Modules/xxsubtype.c - xxsubtype_functions - -Modules/zlibmodule.c - Decomp_methods - -Modules/zlibmodule.c - comp_methods - -Modules/zlibmodule.c - zlib_methods - -Objects/bytearrayobject.c - bytearray_methods - -Objects/bytearrayobject.c - bytearrayiter_methods - -Objects/bytesobject.c - bytes_methods - -Objects/bytesobject.c - striter_methods - -Objects/classobject.c - method_methods - -Objects/codeobject.c - code_methods - -Objects/complexobject.c - complex_methods - -Objects/descrobject.c - descr_methods - -Objects/descrobject.c - mappingproxy_methods - -Objects/descrobject.c - property_methods - -Objects/descrobject.c - wrapper_methods - -Objects/dictobject.c - dictitems_methods - -Objects/dictobject.c - dictiter_methods - -Objects/dictobject.c - dictkeys_methods - -Objects/dictobject.c - dictvalues_methods - -Objects/dictobject.c - mapp_methods - -Objects/enumobject.c - enum_methods - -Objects/enumobject.c - reversediter_methods - -Objects/exceptions.c - AttributeError_methods - -Objects/exceptions.c - BaseExceptionGroup_methods - -Objects/exceptions.c - BaseException_methods - -Objects/exceptions.c - ImportError_methods - -Objects/exceptions.c - NameError_methods - -Objects/exceptions.c - OSError_methods - -Objects/fileobject.c - stdprinter_methods - -Objects/floatobject.c - float_methods - -Objects/frameobject.c - frame_methods - -Objects/genericaliasobject.c - ga_methods - -Objects/genericaliasobject.c - ga_iter_methods - -Objects/genobject.c - async_gen_asend_methods - -Objects/genobject.c - async_gen_athrow_methods - -Objects/genobject.c - async_gen_methods - -Objects/genobject.c - coro_methods - -Objects/genobject.c - coro_wrapper_methods - -Objects/genobject.c - gen_methods - -Objects/iterobject.c - anextawaitable_methods - -Objects/iterobject.c - calliter_methods - -Objects/iterobject.c - seqiter_methods - -Objects/listobject.c - list_methods - -Objects/listobject.c - listiter_methods - -Objects/listobject.c - listreviter_methods - -Objects/longobject.c - long_methods - -Objects/memoryobject.c - memory_methods - -Objects/methodobject.c - meth_methods - -Objects/moduleobject.c - module_methods - -Objects/namespaceobject.c - namespace_methods - -Objects/object.c - notimplemented_methods - -Objects/odictobject.c - odict_methods - -Objects/odictobject.c - odictitems_methods - -Objects/odictobject.c - odictiter_methods - -Objects/odictobject.c - odictkeys_methods - -Objects/odictobject.c - odictvalues_methods - -Objects/picklebufobject.c - picklebuf_methods - -Objects/rangeobject.c - longrangeiter_methods - -Objects/rangeobject.c - range_methods - -Objects/rangeobject.c - rangeiter_methods - -Objects/setobject.c - frozenset_methods - -Objects/setobject.c - set_methods - -Objects/setobject.c - setiter_methods - -Objects/sliceobject.c - ellipsis_methods - -Objects/sliceobject.c - slice_methods - -Objects/stringlib/unicode_format.h - fieldnameiter_methods - -Objects/stringlib/unicode_format.h - formatteriter_methods - -Objects/structseq.c - structseq_methods - -Objects/tupleobject.c - tuple_methods - -Objects/tupleobject.c - tupleiter_methods - -Objects/typeobject.c - object_methods - -Objects/typeobject.c - tp_new_methoddef - -Objects/typeobject.c - type_methods - -Objects/unicodeobject.c - _string_methods - -Objects/unicodeobject.c - encoding_map_methods - -Objects/unicodeobject.c - unicode_methods - -Objects/unicodeobject.c - unicodeiter_methods - -Objects/unionobject.c - union_methods - -Objects/weakrefobject.c - proxy_methods - -Objects/weakrefobject.c - weakref_methods - -Python/Python-ast.c - ast_type_methods - -Python/Python-tokenize.c - tokenize_methods - -Python/_warnings.c - warnings_functions - -Python/bltinmodule.c - builtin_methods - -Python/bltinmodule.c - filter_methods - -Python/bltinmodule.c - map_methods - -Python/bltinmodule.c - zip_methods - -Python/context.c - PyContextTokenType_methods - -Python/context.c - PyContextVar_methods - -Python/context.c - PyContext_methods - -Python/hamt.c - PyHamt_methods - -Python/import.c - imp_slots - -Python/import.c - imp_methods - -Python/marshal.c - marshal_methods - -Python/sysmodule.c - sys_methods - -Python/traceback.c - tb_methods - - -#----------------------- -# PyMemberDef[], for static types and strucseq - -Modules/_bz2module.c - BZ2Decompressor_members - -Modules/_collectionsmodule.c - defdict_members - -Modules/_collectionsmodule.c - tuplegetter_members - -Modules/_csv.c - Dialect_memberlist - -Modules/_csv.c - Reader_memberlist - -Modules/_csv.c - Writer_memberlist - -Modules/_ctypes/_ctypes.c - PyCData_members - -Modules/_ctypes/callproc.c - PyCArgType_members - -Modules/_datetimemodule.c - delta_members - -Modules/_elementtree.c - xmlparser_members - -Modules/_functoolsmodule.c - keyobject_members - -Modules/_functoolsmodule.c - lru_cache_memberlist - -Modules/_functoolsmodule.c - partial_memberlist - -Modules/_io/bufferedio.c - bufferedrandom_members - -Modules/_io/bufferedio.c - bufferedreader_members - -Modules/_io/bufferedio.c - bufferedwriter_members - -Modules/_io/fileio.c - fileio_members - -Modules/_io/textio.c - textiowrapper_members - -Modules/_io/winconsoleio.c - winconsoleio_members - -Modules/_json.c - encoder_members - -Modules/_json.c - scanner_members - -Modules/_lzmamodule.c - Decompressor_members - -Modules/_multiprocessing/semaphore.c - semlock_members - -Modules/_operator.c - attrgetter_members - -Modules/_operator.c - itemgetter_members - -Modules/_pickle.c - Pickler_members - -Modules/_queuemodule.c - simplequeue_members - -Modules/_sqlite/blob.c - blob_members - -Modules/_sqlite/connection.c - connection_members - -Modules/_sqlite/cursor.c - cursor_members - -Modules/_sqlite/statement.c - stmt_members - -Modules/_sre/sre.c - match_members - -Modules/_sre/sre.c - pattern_members - -Modules/_sre/sre.c - scanner_members - -Modules/_sre.c - match_members - -Modules/_sre.c - pattern_members - -Modules/_sre.c - scanner_members - -Modules/_struct.c - s_members - -Modules/_testcapi/heaptype.c - heapctype_members - -Modules/_testcapi/heaptype.c - heapctypesetattr_members - -Modules/_testcapi/heaptype.c - heapctypesubclass_members - -Modules/_testcapi/heaptype.c - heapctypewithdict_members - -Modules/_testcapi/heaptype.c - heapctypewithnegativedict_members - -Modules/_testcapi/heaptype.c - heapctypewithweakref_members - -Modules/_testcapi/heaptype.c - members_to_repeat - -Modules/_threadmodule.c - local_dummy_type_members - -Modules/_threadmodule.c - local_type_members - -Modules/_threadmodule.c - lock_type_members - -Modules/_threadmodule.c - rlock_type_members - -Modules/_winapi.c - overlapped_members - -Modules/_zoneinfo.c - zoneinfo_members - -Modules/arraymodule.c - array_members - -Modules/cjkcodecs/multibytecodec.c - mbstreamreader_members - -Modules/cjkcodecs/multibytecodec.c - mbstreamwriter_members - -Modules/mmapmodule.c - mmap_object_members - -Modules/ossaudiodev.c - oss_members - -Modules/overlapped.c - Overlapped_members - -Modules/posixmodule.c - DirEntry_members - -Modules/pyexpat.c - xmlparse_members - -Modules/selectmodule.c - kqueue_event_members - -Modules/sha256module.c - SHA_members - -Modules/sha512module.c - SHA_members - -Modules/socketmodule.c - sock_memberlist - -Modules/unicodedata.c - DB_members - -Modules/xxsubtype.c - spamdict_members - -Modules/zlibmodule.c - Decomp_members - -Objects/classobject.c - instancemethod_memberlist - -Objects/classobject.c - method_memberlist - -Objects/codeobject.c - code_memberlist - -Objects/complexobject.c - complex_members - -Objects/descrobject.c - descr_members - -Objects/descrobject.c - property_members - -Objects/descrobject.c - wrapper_members - -Objects/exceptions.c - AttributeError_members - -Objects/exceptions.c - BaseExceptionGroup_members - -Objects/exceptions.c - BaseException_members - -Objects/exceptions.c - ImportError_members - -Objects/exceptions.c - NameError_members - -Objects/exceptions.c - OSError_members - -Objects/exceptions.c - StopIteration_members - -Objects/exceptions.c - SyntaxError_members - -Objects/exceptions.c - SystemExit_members - -Objects/exceptions.c - UnicodeError_members - -Objects/frameobject.c - frame_memberlist - -Objects/funcobject.c - cm_memberlist - -Objects/funcobject.c - func_memberlist - -Objects/funcobject.c - sm_memberlist - -Objects/genericaliasobject.c - ga_members - -Objects/genobject.c - async_gen_memberlist - -Objects/genobject.c - coro_memberlist - -Objects/genobject.c - gen_memberlist - -Objects/methodobject.c - meth_members - -Objects/moduleobject.c - module_members - -Objects/namespaceobject.c - namespace_members - -Objects/rangeobject.c - range_members - -Objects/sliceobject.c - slice_members - -Objects/typeobject.c - super_members - -Objects/typeobject.c - type_members - -Objects/unionobject.c - union_members - -Objects/weakrefobject.c - weakref_members - -Python/Python-ast.c - ast_type_members - -Python/context.c - PyContextVar_members - -Python/symtable.c - ste_memberlist - -Python/traceback.c - tb_memberlist - - -#----------------------- -# for static types - -# PyNumberMethods -Modules/_collectionsmodule.c - deque_as_number - -Modules/_collectionsmodule.c - defdict_as_number - -Modules/_ctypes/_ctypes.c - PyCFuncPtr_as_number - -Modules/_ctypes/_ctypes.c - Simple_as_number - -Modules/_ctypes/_ctypes.c - Pointer_as_number - -Modules/_datetimemodule.c - delta_as_number - -Modules/_datetimemodule.c - date_as_number - -Modules/_datetimemodule.c - datetime_as_number - -Modules/_decimal/_decimal.c - dec_number_methods - -Modules/_xxsubinterpretersmodule.c - channelid_as_number - -Objects/boolobject.c - bool_as_number - -Objects/bytearrayobject.c - bytearray_as_number - -Objects/bytesobject.c - bytes_as_number - -Objects/complexobject.c - complex_as_number - -Objects/descrobject.c - mappingproxy_as_number - -Objects/dictobject.c - dict_as_number - -Objects/dictobject.c - dictviews_as_number - -Objects/floatobject.c - float_as_number - -Objects/genericaliasobject.c - ga_as_number - -Objects/interpreteridobject.c - interpid_as_number - -Objects/longobject.c - long_as_number - -Objects/object.c - none_as_number - -Objects/object.c - notimplemented_as_number - -Objects/odictobject.c - odict_as_number - -Objects/rangeobject.c - range_as_number - -Objects/setobject.c - set_as_number - -Objects/setobject.c - frozenset_as_number - -Objects/typeobject.c - type_as_number - -Objects/unicodeobject.c - unicode_as_number - -Objects/unionobject.c - union_as_number - -Objects/weakrefobject.c - proxy_as_number - - -# PySequenceMethods -Modules/arraymodule.c - array_as_sequence - -Modules/_collectionsmodule.c - deque_as_sequence - -Modules/_ctypes/_ctypes.c - CDataType_as_sequence - -Modules/_ctypes/_ctypes.c - Array_as_sequence - -Modules/_ctypes/_ctypes.c - Pointer_as_sequence - -Modules/_elementtree.c - element_as_sequence - -Modules/mmapmodule.c - mmap_as_sequence - -Objects/bytearrayobject.c - bytearray_as_sequence - -Objects/bytesobject.c - bytes_as_sequence - -Objects/descrobject.c - mappingproxy_as_sequence - -Objects/dictobject.c - dict_as_sequence - -Objects/dictobject.c - dictkeys_as_sequence - -Objects/dictobject.c - dictitems_as_sequence - -Objects/dictobject.c - dictvalues_as_sequence - -Objects/listobject.c - list_as_sequence - -Objects/memoryobject.c - memory_as_sequence - -Objects/rangeobject.c - range_as_sequence - -Objects/setobject.c - set_as_sequence - -Objects/tupleobject.c - tuple_as_sequence - -Objects/unicodeobject.c - unicode_as_sequence - -Objects/weakrefobject.c - proxy_as_sequence - -Python/context.c - PyContext_as_sequence - -Python/hamt.c - PyHamt_as_sequence - - -# PyMappingMethods -Modules/arraymodule.c - array_as_mapping - -Modules/_ctypes/_ctypes.c - Array_as_mapping - -Modules/_ctypes/_ctypes.c - Pointer_as_mapping - -Modules/_decimal/_decimal.c - signaldict_as_mapping - -Modules/_elementtree.c - element_as_mapping - -Modules/mmapmodule.c - mmap_as_mapping - -Modules/_sre.c - match_as_mapping - -Objects/bytearrayobject.c - bytearray_as_mapping - -Objects/bytesobject.c - bytes_as_mapping - -Objects/descrobject.c - mappingproxy_as_mapping - -Objects/dictobject.c - dict_as_mapping - -Objects/genericaliasobject.c - ga_as_mapping - -Objects/listobject.c - list_as_mapping - -Objects/memoryobject.c - memory_as_mapping - -Objects/odictobject.c - odict_as_mapping - -Objects/rangeobject.c - range_as_mapping - -Objects/tupleobject.c - tuple_as_mapping - -Objects/unicodeobject.c - unicode_as_mapping - -Objects/unionobject.c - union_as_mapping - -Objects/weakrefobject.c - proxy_as_mapping - -Python/context.c - PyContext_as_mapping - -Python/hamt.c - PyHamtIterator_as_mapping - -Python/hamt.c - PyHamt_as_mapping - - -# PyAsyncMethods -Modules/_asynciomodule.c - FutureIterType_as_async - -Modules/_asynciomodule.c - FutureType_as_async - -Objects/genobject.c - async_gen_as_async - -Objects/genobject.c - async_gen_asend_as_async - -Objects/genobject.c - async_gen_athrow_as_async - -Objects/genobject.c - coro_as_async - -Objects/genobject.c - gen_as_async - -Objects/iterobject.c - anextawaitable_as_async - - -# PyBufferProcs -Modules/arraymodule.c - array_as_buffer - -Modules/_ctypes/_ctypes.c - PyCData_as_buffer - -Modules/_io/bytesio.c - bytesiobuf_as_buffer - -Modules/mmapmodule.c - mmap_as_buffer - -Objects/bytearrayobject.c - bytearray_as_buffer - -Objects/bytesobject.c - bytes_as_buffer - -Objects/memoryobject.c - memory_as_buffer - -Objects/picklebufobject.c - picklebuf_as_buffer - - -# PyGetSetDef -Modules/_asynciomodule.c - FutureType_getsetlist - -Modules/_asynciomodule.c - TaskStepMethWrapper_getsetlist - -Modules/_asynciomodule.c - TaskType_getsetlist - -Modules/_blake2/blake2b_impl.c - py_blake2b_getsetters - -Modules/_blake2/blake2s_impl.c - py_blake2s_getsetters - -Modules/_collectionsmodule.c - deque_getset - -Modules/_csv.c - Dialect_getsetlist - -Modules/_ctypes/_ctypes.c - CharArray_getsets - -Modules/_ctypes/_ctypes.c - Pointer_getsets - -Modules/_ctypes/_ctypes.c - PyCFuncPtr_getsets - -Modules/_ctypes/_ctypes.c - Simple_getsets - -Modules/_ctypes/_ctypes.c - WCharArray_getsets - -Modules/_ctypes/cfield.c - PyCField_getset - -Modules/_cursesmodule.c - PyCursesWindow_getsets - -Modules/_datetimemodule.c - date_getset - -Modules/_datetimemodule.c - datetime_getset - -Modules/_datetimemodule.c - iso_calendar_date_getset - -Modules/_datetimemodule.c - time_getset - -Modules/_decimal/_decimal.c - context_getsets - -Modules/_decimal/_decimal.c - dec_getsets - -Modules/_elementtree.c - element_getsetlist - -Modules/_elementtree.c - xmlparser_getsetlist - -Modules/_functoolsmodule.c - lru_cache_getsetlist - -Modules/_functoolsmodule.c - partial_getsetlist - -Modules/_hashopenssl.c - EVPXOF_getseters - -Modules/_hashopenssl.c - EVP_getseters - -Modules/_hashopenssl.c - HMAC_getset - -Modules/_io/bufferedio.c - bufferedrandom_getset - -Modules/_io/bufferedio.c - bufferedreader_getset - -Modules/_io/bufferedio.c - bufferedrwpair_getset - -Modules/_io/bufferedio.c - bufferedwriter_getset - -Modules/_io/bytesio.c - bytesio_getsetlist - -Modules/_io/fileio.c - fileio_getsetlist - -Modules/_io/iobase.c - iobase_getset - -Modules/_io/stringio.c - stringio_getset - -Modules/_io/textio.c - incrementalnewlinedecoder_getset - -Modules/_io/textio.c - textiobase_getset - -Modules/_io/textio.c - textiowrapper_getset - -Modules/_io/winconsoleio.c - winconsoleio_getsetlist - -Modules/_pickle.c - Pickler_getsets - -Modules/_pickle.c - Unpickler_getsets - -Modules/_sha3/sha3module.c - SHA3_getseters - -Modules/_sha3/sha3module.c - SHAKE_getseters - -Modules/_sqlite/connection.c - connection_getset - -Modules/_sre/sre.c - pattern_getset - -Modules/_sre/sre.c - match_getset - -Modules/_sre.c - match_getset - -Modules/_sre.c - pattern_getset - -Modules/_ssl.c - PySSLSession_getsetlist - -Modules/_ssl.c - context_getsetlist - -Modules/_ssl.c - memory_bio_getsetlist - -Modules/_ssl.c - ssl_getsetlist - -Modules/_struct.c - s_getsetlist - -Modules/_testcapi/heaptype.c - heapctypewithdict_getsetlist - -Modules/_tkinter.c - PyTclObject_getsetlist - -Modules/_xxsubinterpretersmodule.c - channelid_getsets - -Modules/arraymodule.c - array_getsets - -Modules/cjkcodecs/multibytecodec.c - codecctx_getsets - -Modules/md5module.c - MD5_getseters - -Modules/mmapmodule.c - mmap_object_getset - -Modules/ossaudiodev.c - oss_getsetlist - -Modules/overlapped.c - Overlapped_getsets - -Modules/pyexpat.c - xmlparse_getsetlist - -Modules/selectmodule.c - devpoll_getsetlist - -Modules/selectmodule.c - kqueue_queue_getsetlist - -Modules/selectmodule.c - pyepoll_getsetlist - -Modules/sha1module.c - SHA1_getseters - -Modules/sha256module.c - SHA_getseters - -Modules/sha512module.c - SHA_getseters - -Modules/socketmodule.c - sock_getsetlist - -Modules/xxlimited.c - Xxo_getsetlist - -Modules/xxsubtype.c - spamlist_getsets - -Objects/cellobject.c - cell_getsetlist - -Objects/classobject.c - instancemethod_getset - -Objects/classobject.c - method_getset - -Objects/codeobject.c - code_getsetlist - -Objects/descrobject.c - getset_getset - -Objects/descrobject.c - member_getset - -Objects/descrobject.c - method_getset - -Objects/descrobject.c - property_getsetlist - -Objects/descrobject.c - wrapper_getsets - -Objects/descrobject.c - wrapperdescr_getset - -Objects/dictobject.c - dictview_getset - -Objects/exceptions.c - BaseException_getset - -Objects/exceptions.c - OSError_getset - -Objects/fileobject.c - stdprinter_getsetlist - -Objects/floatobject.c - float_getset - -Objects/frameobject.c - frame_getsetlist - -Objects/funcobject.c - cm_getsetlist - -Objects/funcobject.c - func_getsetlist - -Objects/funcobject.c - sm_getsetlist - -Objects/genericaliasobject.c - ga_properties - -Objects/genobject.c - async_gen_getsetlist - -Objects/genobject.c - coro_getsetlist - -Objects/genobject.c - gen_getsetlist - -Objects/longobject.c - long_getset - -Objects/memoryobject.c - memory_getsetlist - -Objects/methodobject.c - meth_getsets - -Objects/moduleobject.c - module_getsets - -Objects/odictobject.c - odict_getset - -Objects/typeobject.c - object_getsets - -Objects/typeobject.c - subtype_getsets_dict_only - -Objects/typeobject.c - subtype_getsets_full - -Objects/typeobject.c - subtype_getsets_weakref_only - -Objects/typeobject.c - type_getsets - -Objects/unionobject.c - union_properties - -Python/Python-ast.c - ast_type_getsets - -Python/context.c - PyContextTokenType_getsetlist - -Python/traceback.c - tb_getsetters - - -#----------------------- -# for heap types - -# PyType_Slot -Modules/_abc.c - _abc_data_type_spec_slots - -Modules/_blake2/blake2b_impl.c - blake2b_type_slots - -Modules/_blake2/blake2s_impl.c - blake2s_type_slots - -Modules/_bz2module.c - bz2_compressor_type_slots - -Modules/_bz2module.c - bz2_decompressor_type_slots - -Modules/_csv.c - Dialect_Type_slots - -Modules/_csv.c - Reader_Type_slots - -Modules/_csv.c - Writer_Type_slots - -Modules/_csv.c - error_slots - -Modules/_curses_panel.c - PyCursesPanel_Type_slots - -Modules/_dbmmodule.c - dbmtype_spec_slots - -Modules/_functoolsmodule.c - keyobject_type_slots - -Modules/_functoolsmodule.c - lru_cache_type_slots - -Modules/_functoolsmodule.c - lru_list_elem_type_slots - -Modules/_functoolsmodule.c - partial_type_slots - -Modules/_gdbmmodule.c - gdbmtype_spec_slots - -Modules/_hashopenssl.c - EVPXOFtype_slots - -Modules/_hashopenssl.c - EVPtype_slots - -Modules/_hashopenssl.c - HMACtype_slots - -Modules/_json.c - PyEncoderType_slots - -Modules/_json.c - PyScannerType_slots - -Modules/_lsprof.c - _lsprof_profiler_type_spec_slots - -Modules/_lzmamodule.c - lzma_compressor_type_slots - -Modules/_lzmamodule.c - lzma_decompressor_type_slots - -Modules/_multiprocessing/semaphore.c - _PyMp_SemLockType_slots - -Modules/_operator.c - attrgetter_type_slots - -Modules/_operator.c - itemgetter_type_slots - -Modules/_operator.c - methodcaller_type_slots - -Modules/_queuemodule.c - simplequeue_slots - -Modules/_randommodule.c - Random_Type_slots - -Modules/_sha3/sha3module.c - SHAKE128slots - -Modules/_sha3/sha3module.c - SHAKE256slots - -Modules/_sha3/sha3module.c - sha3_224_slots - -Modules/_sha3/sha3module.c - sha3_256_slots - -Modules/_sha3/sha3module.c - sha3_384_slots - -Modules/_sha3/sha3module.c - sha3_512_slots - -Modules/_sha3/sha3module.c - type_slots_obj - -Modules/_sqlite/blob.c - blob_slots - -Modules/_sqlite/connection.c - connection_slots - -Modules/_sqlite/cursor.c - cursor_slots - -Modules/_sqlite/prepare_protocol.c - type_slots - -Modules/_sqlite/row.c - row_slots - -Modules/_sqlite/statement.c - stmt_slots - -Modules/_sre/sre.c - match_slots - -Modules/_sre/sre.c - pattern_slots - -Modules/_sre/sre.c - scanner_slots - -Modules/_sre.c - match_slots - -Modules/_sre.c - pattern_slots - -Modules/_sre.c - scanner_slots - -Modules/_ssl.c - PySSLContext_slots - -Modules/_ssl.c - PySSLMemoryBIO_slots - -Modules/_ssl.c - PySSLSession_slots - -Modules/_ssl.c - PySSLSocket_slots - -Modules/_ssl.c - sslerror_type_slots - -Modules/_ssl/cert.c - PySSLCertificate_slots - -Modules/_struct.c - PyStructType_slots - -Modules/_struct.c - unpackiter_type_slots - -Modules/_testcapi/heaptype.c - HeapCTypeMetaclassCustomNew_slots - -Modules/_testcapi/heaptype.c - HeapCTypeMetaclass_slots - -Modules/_testcapi/heaptype.c - HeapCTypeSetattr_slots - -Modules/_testcapi/heaptype.c - HeapCTypeSubclassWithFinalizer_slots - -Modules/_testcapi/heaptype.c - HeapCTypeSubclass_slots - -Modules/_testcapi/heaptype.c - HeapCTypeWithBuffer_slots - -Modules/_testcapi/heaptype.c - HeapCTypeWithDict_slots - -Modules/_testcapi/heaptype.c - HeapCTypeWithNegativeDict_slots - -Modules/_testcapi/heaptype.c - HeapCTypeWithWeakref_slots - -Modules/_testcapi/heaptype.c - HeapCType_slots - -Modules/_testcapi/heaptype.c - HeapDocCType_slots - -Modules/_testcapi/heaptype.c - HeapGcCType_slots - -Modules/_testcapi/heaptype.c - NullTpDocType_slots - -Modules/_testcapi/heaptype.c - empty_type_slots - -Modules/_testcapi/heaptype.c - repeated_doc_slots - -Modules/_testcapi/heaptype.c - repeated_members_slots - -Modules/_testcapimodule.c - HeapTypeNameType_slots - -Modules/_testcapimodule.c - NullTpDocType_slots - -Modules/_threadmodule.c - local_dummy_type_slots - -Modules/_threadmodule.c - local_type_slots - -Modules/_threadmodule.c - lock_type_slots - -Modules/_threadmodule.c - rlock_type_slots - -Modules/_tkinter.c - PyTclObject_Type_slots - -Modules/_tkinter.c - Tkapp_Type_slots - -Modules/_tkinter.c - Tktt_Type_slots - -Modules/_winapi.c - winapi_overlapped_type_slots - -Modules/arraymodule.c - array_slots - -Modules/arraymodule.c - arrayiter_slots - -Modules/cjkcodecs/multibytecodec.c - decoder_slots - -Modules/cjkcodecs/multibytecodec.c - encoder_slots - -Modules/cjkcodecs/multibytecodec.c - multibytecodec_slots - -Modules/cjkcodecs/multibytecodec.c - reader_slots - -Modules/cjkcodecs/multibytecodec.c - writer_slots - -Modules/md5module.c - md5_type_slots - -Modules/mmapmodule.c - mmap_object_slots - -Modules/overlapped.c - overlapped_type_slots - -Modules/posixmodule.c - DirEntryType_slots - -Modules/posixmodule.c - ScandirIteratorType_slots - -Modules/pyexpat.c - _xml_parse_type_spec_slots - -Modules/selectmodule.c - devpoll_Type_slots - -Modules/selectmodule.c - kqueue_event_Type_slots - -Modules/selectmodule.c - kqueue_queue_Type_slots - -Modules/selectmodule.c - poll_Type_slots - -Modules/selectmodule.c - pyEpoll_Type_slots - -Modules/sha1module.c - sha1_type_slots - -Modules/sha256module.c - sha256_types_slots - -Modules/sha512module.c - sha512_sha384_type_slots - -Modules/sha512module.c - sha512_sha512_type_slots - -Modules/unicodedata.c - ucd_type_slots - -Modules/xxlimited.c - Null_Type_slots - -Modules/xxlimited.c - Str_Type_slots - -Modules/xxlimited.c - Xxo_Type_slots - -Modules/xxlimited_35.c - Null_Type_slots - -Modules/xxlimited_35.c - Str_Type_slots - -Modules/xxlimited_35.c - Xxo_Type_slots - -Modules/zlibmodule.c - Comptype_slots - -Modules/zlibmodule.c - Decomptype_slots - -Python/Python-ast.c - AST_type_slots - -Python/Python-tokenize.c - tokenizeriter_slots - - -# PyType_Spec -Modules/_abc.c - _abc_data_type_spec - -Modules/_blake2/blake2b_impl.c - blake2b_type_spec - -Modules/_blake2/blake2s_impl.c - blake2s_type_spec - -Modules/_bz2module.c - bz2_compressor_type_spec - -Modules/_bz2module.c - bz2_decompressor_type_spec - -Modules/_csv.c - Dialect_Type_spec - -Modules/_csv.c - Reader_Type_spec - -Modules/_csv.c - Writer_Type_spec - -Modules/_csv.c - error_spec - -Modules/_curses_panel.c - PyCursesPanel_Type_spec - -Modules/_dbmmodule.c - dbmtype_spec - -Modules/_functoolsmodule.c - keyobject_type_spec - -Modules/_functoolsmodule.c - lru_cache_type_spec - -Modules/_functoolsmodule.c - lru_list_elem_type_spec - -Modules/_functoolsmodule.c - partial_type_spec - -Modules/_gdbmmodule.c - gdbmtype_spec - -Modules/_hashopenssl.c - EVPXOFtype_spec - -Modules/_hashopenssl.c - EVPtype_spec - -Modules/_hashopenssl.c - HMACtype_spec - -Modules/_json.c - PyEncoderType_spec - -Modules/_json.c - PyScannerType_spec - -Modules/_lsprof.c - _lsprof_profiler_type_spec - -Modules/_lzmamodule.c - lzma_compressor_type_spec - -Modules/_lzmamodule.c - lzma_decompressor_type_spec - -Modules/_multiprocessing/multiprocessing.h - _PyMp_SemLockType_spec - -Modules/_multiprocessing/semaphore.c - _PyMp_SemLockType_spec - -Modules/_operator.c - attrgetter_type_spec - -Modules/_operator.c - itemgetter_type_spec - -Modules/_operator.c - methodcaller_type_spec - -Modules/_queuemodule.c - simplequeue_spec - -Modules/_randommodule.c - Random_Type_spec - -Modules/_sha3/sha3module.c - SHAKE128_spec - -Modules/_sha3/sha3module.c - SHAKE256_spec - -Modules/_sha3/sha3module.c - sha3_224_spec - -Modules/_sha3/sha3module.c - sha3_256_spec - -Modules/_sha3/sha3module.c - sha3_384_spec - -Modules/_sha3/sha3module.c - sha3_512_spec - -Modules/_sha3/sha3module.c - type_spec_obj - -Modules/_sqlite/blob.c - blob_spec - -Modules/_sqlite/connection.c - connection_spec - -Modules/_sqlite/cursor.c - cursor_spec - -Modules/_sqlite/prepare_protocol.c - type_spec - -Modules/_sqlite/row.c - row_spec - -Modules/_sqlite/statement.c - stmt_spec - -Modules/_sre/sre.c - pattern_spec - -Modules/_sre/sre.c - match_spec - -Modules/_sre/sre.c - scanner_spec - -Modules/_sre.c - match_spec - -Modules/_sre.c - pattern_spec - -Modules/_sre.c - scanner_spec - -Modules/_ssl.c - PySSLContext_spec - -Modules/_ssl.c - PySSLMemoryBIO_spec - -Modules/_ssl.c - PySSLSession_spec - -Modules/_ssl.c - PySSLSocket_spec - -Modules/_ssl.c - sslerror_type_spec - -Modules/_ssl/cert.c - PySSLCertificate_spec - -Modules/_struct.c - PyStructType_spec - -Modules/_struct.c - unpackiter_type_spec - -Modules/_testcapi/heaptype.c - MinimalMetaclass_spec - -Modules/_testcapi/heaptype.c - MinimalType_spec - -Modules/_testcapi/heaptype.c - repeated_doc_slots_spec - -Modules/_testcapi/heaptype.c - repeated_members_slots_spec - -Modules/_testcapi/heaptype.c - HeapDocCType_spec - -Modules/_testcapi/heaptype.c - NullTpDocType_spec - -Modules/_testcapi/heaptype.c - HeapGcCType_spec - -Modules/_testcapi/heaptype.c - HeapCType_spec - -Modules/_testcapi/heaptype.c - HeapCTypeSubclass_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithBuffer_spec - -Modules/_testcapi/heaptype.c - HeapCTypeSubclassWithFinalizer_spec - -Modules/_testcapi/heaptype.c - HeapCTypeMetaclass_spec - -Modules/_testcapi/heaptype.c - HeapCTypeMetaclassCustomNew_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithDict_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithDict2_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithNegativeDict_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithWeakref_spec - -Modules/_testcapi/heaptype.c - HeapCTypeWithWeakref2_spec - -Modules/_testcapi/heaptype.c - HeapCTypeSetattr_spec - -Modules/_testcapimodule.c - HeapTypeNameType_Spec - -Modules/_testcapimodule.c - NullTpDocType_spec - -Modules/_threadmodule.c - local_dummy_type_spec - -Modules/_threadmodule.c - local_type_spec - -Modules/_threadmodule.c - lock_type_spec - -Modules/_threadmodule.c - rlock_type_spec - -Modules/_tkinter.c - PyTclObject_Type_spec - -Modules/_tkinter.c - Tkapp_Type_spec - -Modules/_tkinter.c - Tktt_Type_spec - -Modules/_winapi.c - winapi_overlapped_type_spec - -Modules/_zoneinfo.c - DAYS_BEFORE_MONTH - -Modules/_zoneinfo.c - DAYS_IN_MONTH - -Modules/arraymodule.c - array_spec - -Modules/arraymodule.c - arrayiter_spec - -Modules/cjkcodecs/multibytecodec.c - decoder_spec - -Modules/cjkcodecs/multibytecodec.c - encoder_spec - -Modules/cjkcodecs/multibytecodec.c - multibytecodec_spec - -Modules/cjkcodecs/multibytecodec.c - reader_spec - -Modules/cjkcodecs/multibytecodec.c - writer_spec - -Modules/md5module.c - md5_type_spec - -Modules/mmapmodule.c - mmap_object_spec - -Modules/overlapped.c - overlapped_type_spec - -Modules/posixmodule.c - DirEntryType_spec - -Modules/posixmodule.c - ScandirIteratorType_spec - -Modules/pyexpat.c - _xml_parse_type_spec - -Modules/selectmodule.c - devpoll_Type_spec - -Modules/selectmodule.c - kqueue_event_Type_spec - -Modules/selectmodule.c - kqueue_queue_Type_spec - -Modules/selectmodule.c - poll_Type_spec - -Modules/selectmodule.c - pyEpoll_Type_spec - -Modules/sha1module.c - sha1_type_spec - -Modules/sha256module.c - sha224_type_spec - -Modules/sha256module.c - sha256_type_spec - -Modules/sha512module.c - sha512_sha384_type_spec - -Modules/sha512module.c - sha512_sha512_type_spec - -Modules/unicodedata.c - ucd_type_spec - -Modules/xxlimited.c - Null_Type_spec - -Modules/xxlimited.c - Str_Type_spec - -Modules/xxlimited.c - Xxo_Type_spec - -Modules/xxlimited_35.c - Null_Type_spec - -Modules/xxlimited_35.c - Str_Type_spec - -Modules/xxlimited_35.c - Xxo_Type_spec - -Modules/zlibmodule.c - Comptype_spec - -Modules/zlibmodule.c - Decomptype_spec - -Python/Python-ast.c - AST_type_spec - -Python/Python-tokenize.c - tokenizeriter_spec - - -#----------------------- -# for structseq - -# PyStructSequence_Field[] -Modules/_cursesmodule.c - ncurses_version_fields - -Modules/grpmodule.c - struct_group_type_fields - -Modules/_lsprof.c - profiler_entry_fields - -Modules/_lsprof.c - profiler_subentry_fields - -Modules/posixmodule.c - stat_result_fields - -Modules/posixmodule.c - statvfs_result_fields - -Modules/posixmodule.c - waitid_result_fields - -Modules/posixmodule.c - uname_result_fields - -Modules/posixmodule.c - sched_param_fields - -Modules/posixmodule.c - times_result_fields - -Modules/posixmodule.c - TerminalSize_fields - -Modules/pwdmodule.c - struct_pwd_type_fields - -Modules/resource.c - struct_rusage_fields - -Modules/signalmodule.c - struct_siginfo_fields - -Modules/spwdmodule.c - struct_spwd_type_fields - -Modules/_threadmodule.c - ExceptHookArgs_fields - -Modules/timemodule.c - struct_time_type_fields - -Objects/floatobject.c - floatinfo_fields - -Objects/longobject.c - int_info_fields - -Python/errors.c - UnraisableHookArgs_fields - -Python/sysmodule.c - asyncgen_hooks_fields - -Python/sysmodule.c - hash_info_fields - -Python/sysmodule.c - windows_version_fields - -Python/sysmodule.c - flags_fields - -Python/sysmodule.c - version_info_fields - -Python/thread.c - threadinfo_fields - - -# PyStructSequence_Desc -Modules/_cursesmodule.c - ncurses_version_desc - -Modules/grpmodule.c - struct_group_type_desc - -Modules/_lsprof.c - profiler_entry_desc - -Modules/_lsprof.c - profiler_subentry_desc - -Modules/posixmodule.c - stat_result_desc - -Modules/posixmodule.c - statvfs_result_desc - -Modules/posixmodule.c - waitid_result_desc - -Modules/posixmodule.c - uname_result_desc - -Modules/posixmodule.c - sched_param_desc - -Modules/posixmodule.c - times_result_desc - -Modules/posixmodule.c - TerminalSize_desc - -Modules/pwdmodule.c - struct_pwd_type_desc - -Modules/resource.c - struct_rusage_desc - -Modules/signalmodule.c - struct_siginfo_desc - -Modules/spwdmodule.c - struct_spwd_type_desc - -Modules/_threadmodule.c - ExceptHookArgs_desc - -Modules/timemodule.c - struct_time_type_desc - -Objects/floatobject.c - floatinfo_desc - -Objects/longobject.c - int_info_desc - -Python/errors.c - UnraisableHookArgs_desc - -Python/sysmodule.c - asyncgen_hooks_desc - -Python/sysmodule.c - hash_info_desc - -Python/sysmodule.c - windows_version_desc - -Python/sysmodule.c - flags_desc - -Python/sysmodule.c - version_info_desc - -Python/thread.c - threadinfo_desc - +# All module defs, type defs, etc. are handled in c-analyzr/cpython/_analyzer.py. +# All kwlist arrays are handled in c-analyzr/cpython/_analyzer.py. #----------------------- # other vars that are actually constant @@ -1546,6 +381,8 @@ Modules/_struct.c - lilendian_table - Modules/_tkinter.c - state_key - Modules/_xxsubinterpretersmodule.c - _channelid_end_recv - Modules/_xxsubinterpretersmodule.c - _channelid_end_send - +Modules/_zoneinfo.c - DAYS_BEFORE_MONTH - +Modules/_zoneinfo.c - DAYS_IN_MONTH - Modules/arraymodule.c - descriptors - Modules/arraymodule.c - emptybuf - Modules/cjkcodecs/cjkcodecs.h - __methods - @@ -1603,6 +440,7 @@ Python/ast_opt.c fold_unaryop ops - Python/codecs.c - Py_hexdigits - Python/codecs.c - ucnhash_capi - Python/codecs.c _PyCodecRegistry_Init methods - +Python/compile.c - NO_LABEL - Python/compile.c - NO_LOCATION - Python/dynload_shlib.c - _PyImport_DynLoadFiletab - Python/dynload_stub.c - _PyImport_DynLoadFiletab - @@ -1622,4 +460,5 @@ Python/specialize.c - adaptive_opcodes - Python/specialize.c - cache_requirements - Python/specialize.c - compare_masks - Python/specialize.c - _PyOpcode_Adaptive - +Python/stdlib_module_names.h - _Py_stdlib_module_names - Python/sysmodule.c - whatstrings - diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 899cb6c7dea0b62..303409cb0077d1f 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -1752,7 +1752,7 @@ def is_other_python_frame(self): def is_waiting_for_gil(self): '''Is this frame waiting on the GIL?''' - # This assumes the _POSIX_THREADS version of Python/ceval_gil.h: + # This assumes the _POSIX_THREADS version of Python/ceval_gil.c: name = self._gdbframe.name() if name: return (name == 'take_gil') diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat index 425558f99d5910a..8771d004211ea94 100644 --- a/Tools/msi/build.bat +++ b/Tools/msi/build.bat @@ -12,15 +12,16 @@ set BUILDPACK= set REBUILD= :CheckOpts -if "%~1" EQU "-h" goto Help -if "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts -if "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts -if "%~1" EQU "-arm64" (set BUILDARM64=1) && shift && goto CheckOpts -if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts -if "%~1" EQU "--no-test-marker" (set BUILDTEST=) && shift && goto CheckOpts -if "%~1" EQU "--test-marker" (set BUILDTEST=--test-marker) && shift && goto CheckOpts -if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts -if "%~1" EQU "-r" (set REBUILD=-r) && shift && goto CheckOpts +if "%~1" EQU "-h" goto Help +if /I "%~1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if /I "%~1" EQU "-Win32" (set BUILDX86=1) && shift && goto CheckOpts +if /I "%~1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if /I "%~1" EQU "-arm64" (set BUILDARM64=1) && shift && goto CheckOpts +if "%~1" EQU "--doc" (set BUILDDOC=1) && shift && goto CheckOpts +if "%~1" EQU "--no-test-marker" (set BUILDTEST=) && shift && goto CheckOpts +if "%~1" EQU "--test-marker" (set BUILDTEST=--test-marker) && shift && goto CheckOpts +if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts +if "%~1" EQU "-r" (set REBUILD=-r) && shift && goto CheckOpts if not defined BUILDX86 if not defined BUILDX64 if not defined BUILDARM64 (set BUILDX86=1) && (set BUILDX64=1) diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat index 0373c9f7b836a79..ccec4da12c4285c 100644 --- a/Tools/msi/buildrelease.bat +++ b/Tools/msi/buildrelease.bat @@ -44,27 +44,28 @@ set BUILDZIP=1 :CheckOpts -if "%1" EQU "-h" goto Help -if "%1" EQU "-c" (set CERTNAME=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "--certificate" (set CERTNAME=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "-o" (set OUTDIR=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "--out" (set OUTDIR=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "-D" (set SKIPDOC=1) && shift && goto CheckOpts -if "%1" EQU "--skip-doc" (set SKIPDOC=1) && shift && goto CheckOpts -if "%1" EQU "-B" (set SKIPBUILD=1) && shift && goto CheckOpts -if "%1" EQU "--skip-build" (set SKIPBUILD=1) && shift && goto CheckOpts -if "%1" EQU "--download" (set DOWNLOAD_URL=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "--test" (set TESTTARGETDIR=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "-b" (set TARGET=Build) && shift && goto CheckOpts -if "%1" EQU "--build" (set TARGET=Build) && shift && goto CheckOpts -if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts -if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts -if "%1" EQU "-arm64" (set BUILDARM64=1) && shift && goto CheckOpts -if "%1" EQU "--pgo" (set PGO=%~2) && shift && shift && goto CheckOpts -if "%1" EQU "--skip-pgo" (set PGO=) && shift && goto CheckOpts -if "%1" EQU "--skip-nuget" (set BUILDNUGET=) && shift && goto CheckOpts -if "%1" EQU "--skip-zip" (set BUILDZIP=) && shift && goto CheckOpts -if "%1" EQU "--skip-msi" (set BUILDMSI=) && shift && goto CheckOpts +if "%1" EQU "-h" goto Help +if "%1" EQU "-c" (set CERTNAME=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "--certificate" (set CERTNAME=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "-o" (set OUTDIR=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "--out" (set OUTDIR=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "-D" (set SKIPDOC=1) && shift && goto CheckOpts +if "%1" EQU "--skip-doc" (set SKIPDOC=1) && shift && goto CheckOpts +if "%1" EQU "-B" (set SKIPBUILD=1) && shift && goto CheckOpts +if "%1" EQU "--skip-build" (set SKIPBUILD=1) && shift && goto CheckOpts +if "%1" EQU "--download" (set DOWNLOAD_URL=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "--test" (set TESTTARGETDIR=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "-b" (set TARGET=Build) && shift && goto CheckOpts +if "%1" EQU "--build" (set TARGET=Build) && shift && goto CheckOpts +if /I "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts +if /I "%1" EQU "-Win32" (set BUILDX86=1) && shift && goto CheckOpts +if /I "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts +if /I "%1" EQU "-arm64" (set BUILDARM64=1) && shift && goto CheckOpts +if "%1" EQU "--pgo" (set PGO=%~2) && shift && shift && goto CheckOpts +if "%1" EQU "--skip-pgo" (set PGO=) && shift && goto CheckOpts +if "%1" EQU "--skip-nuget" (set BUILDNUGET=) && shift && goto CheckOpts +if "%1" EQU "--skip-zip" (set BUILDZIP=) && shift && goto CheckOpts +if "%1" EQU "--skip-msi" (set BUILDMSI=) && shift && goto CheckOpts if "%1" NEQ "" echo Invalid option: "%1" && exit /B 1 diff --git a/Tools/msi/lib/lib_files.wxs b/Tools/msi/lib/lib_files.wxs index 64c046e6dd91086..73c0231352f35c4 100644 --- a/Tools/msi/lib/lib_files.wxs +++ b/Tools/msi/lib/lib_files.wxs @@ -1,6 +1,6 @@  - + diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 62eeafab0848cbc..d9c6030fc17c070 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -195,7 +195,6 @@ def generate_unicode(self, name: str, s: str) -> str: else: self.write("PyCompactUnicodeObject _compact;") self.write(f"{datatype} _data[{len(s)+1}];") - self.deallocs.append(f"_PyStaticUnicode_Dealloc((PyObject *)&{name});") with self.block(f"{name} =", ";"): if ascii: with self.block("._ascii =", ","): @@ -218,6 +217,9 @@ def generate_unicode(self, name: str, s: str) -> str: self.write(f".kind = {kind},") self.write(".compact = 1,") self.write(".ascii = 0,") + utf8 = s.encode('utf-8') + self.write(f'.utf8 = {make_string_literal(utf8)},') + self.write(f'.utf8_length = {len(utf8)},') with self.block(f"._data =", ","): for i in range(0, len(s), 16): data = s[i:i+16] diff --git a/Tools/scripts/generate_global_objects.py b/Tools/scripts/generate_global_objects.py index f3a11f5f7e59694..a50f3ba85d70dcc 100644 --- a/Tools/scripts/generate_global_objects.py +++ b/Tools/scripts/generate_global_objects.py @@ -287,7 +287,11 @@ def generate_runtime_init(identifiers, strings): immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(strings).ascii[{i}]') with printer.block('.latin1 =', ','): for i in range(128, 256): - printer.write(f'_PyUnicode_LATIN1_INIT("\\x{i:02x}"),') + utf8 = ['"'] + for c in chr(i).encode('utf-8'): + utf8.append(f"\\x{c:02x}") + utf8.append('"') + printer.write(f'_PyUnicode_LATIN1_INIT("\\x{i:02x}", {"".join(utf8)}),') immortal_objects.append(f'(PyObject *)&_Py_SINGLETON(strings).latin1[{i} - 128]') printer.write('') with printer.block('.tuple_empty =', ','): diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 24ddd2a20913a28..d64b4f66f5192bd 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -46,8 +46,8 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1n", - "3.0.2" + "1.1.1q", + "3.0.5" ] LIBRESSL_OLD_VERSIONS = [ diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 489484443aab6e1..c30175929d60f55 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -77,7 +77,8 @@ "PDF", "EN", "ES", "ET", "AN", "CS", "NSM", "BN", "B", "S", "WS", "ON", "LRI", "RLI", "FSI", "PDI" ] -EASTASIANWIDTH_NAMES = [ "F", "H", "W", "Na", "A", "N" ] +# "N" needs to be the first entry, see the comment in makeunicodedata +EASTASIANWIDTH_NAMES = [ "N", "H", "W", "Na", "A", "F" ] MANDATORY_LINE_BREAKS = [ "BK", "CR", "LF", "NL" ] @@ -135,6 +136,14 @@ def maketables(trace=0): def makeunicodedata(unicode, trace): + # the default value of east_asian_width is "N", for unassigned code points + # not mentioned in EastAsianWidth.txt + # in addition there are some reserved but unassigned code points in CJK + # ranges that are classified as "W". code points in private use areas + # have a width of "A". both of these have entries in + # EastAsianWidth.txt + # see https://unicode.org/reports/tr11/#Unassigned + assert EASTASIANWIDTH_NAMES[0] == "N" dummy = (0, 0, 0, 0, 0, 0) table = [dummy] cache = {0: dummy} @@ -160,15 +169,24 @@ def makeunicodedata(unicode, trace): category, combining, bidirectional, mirrored, eastasianwidth, normalizationquickcheck ) - # add entry to index and item tables - i = cache.get(item) - if i is None: - cache[item] = i = len(table) - table.append(item) - index[char] = i + elif unicode.widths[char] is not None: + # an unassigned but reserved character, with a known + # east_asian_width + eastasianwidth = EASTASIANWIDTH_NAMES.index(unicode.widths[char]) + item = (0, 0, 0, 0, eastasianwidth, 0) + else: + continue + + # add entry to index and item tables + i = cache.get(item) + if i is None: + cache[item] = i = len(table) + table.append(item) + index[char] = i # 2) decomposition data + decomp_data_cache = {} decomp_data = [0] decomp_prefix = [""] decomp_index = [0] * len(unicode.chars) @@ -207,12 +225,15 @@ def makeunicodedata(unicode, trace): comp_first[l] = 1 comp_last[r] = 1 comp_pairs.append((l,r,char)) - try: - i = decomp_data.index(decomp) - except ValueError: + key = tuple(decomp) + i = decomp_data_cache.get(key, -1) + if i == -1: i = len(decomp_data) decomp_data.extend(decomp) decomp_size = decomp_size + len(decomp) * 2 + decomp_data_cache[key] = i + else: + assert decomp_data[i:i+len(decomp)] == decomp else: i = 0 decomp_index[char] = i @@ -1081,6 +1102,7 @@ def __init__(self, version, cjk_check=True): for i in range(0, 0x110000): if table[i] is not None: table[i].east_asian_width = widths[i] + self.widths = widths for char, (p,) in UcdFile(DERIVED_CORE_PROPERTIES, version).expanded(): if table[char]: diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index 695e6ffc31fabbb..a35acfd9387b41f 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -108,6 +108,14 @@ "_zoneinfo": ["zoneinfo/"], } +SYSCONFIG_NAMES = ( + "_sysconfigdata__emscripten_wasm32-emscripten", + "_sysconfigdata__emscripten_wasm32-emscripten", + "_sysconfigdata__wasi_wasm32-wasi", + "_sysconfigdata__wasi_wasm64-wasi", +) + + def get_builddir(args: argparse.Namespace) -> pathlib.Path: """Get builddir path from pybuilddir.txt """ @@ -120,7 +128,11 @@ def get_sysconfigdata(args: argparse.Namespace) -> pathlib.Path: """Get path to sysconfigdata relative to build root """ data_name = sysconfig._get_sysconfigdata_name() - assert "emscripten_wasm32" in data_name + if not data_name.startswith(SYSCONFIG_NAMES): + raise ValueError( + f"Invalid sysconfig data name '{data_name}'.", + SYSCONFIG_NAMES + ) filename = data_name + ".py" return args.builddir / filename @@ -218,7 +230,8 @@ def main(): extmods = detect_extension_modules(args) omit_files = list(OMIT_FILES) - omit_files.extend(OMIT_NETWORKING_FILES) + if sysconfig.get_platform().startswith("emscripten"): + omit_files.extend(OMIT_NETWORKING_FILES) for modname, modfiles in OMIT_MODULE_FILES.items(): if not extmods.get(modname): omit_files.extend(modfiles) diff --git a/Tools/wasm/wasm_build.py b/Tools/wasm/wasm_build.py index df90f01a27b699d..9054370e5e2fdca 100755 --- a/Tools/wasm/wasm_build.py +++ b/Tools/wasm/wasm_build.py @@ -20,13 +20,16 @@ import dataclasses import os import pathlib +import re import shlex import shutil import subprocess import sysconfig +import tempfile +import warnings # for Python 3.8 -from typing import Any, Dict, Callable, Iterable, List, Optional, Union +from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union SRCDIR = pathlib.Path(__file__).parent.parent.parent.absolute() WASMTOOLS = SRCDIR / "Tools" / "wasm" @@ -44,6 +47,11 @@ EM_CONFIG = pathlib.Path(os.environ.setdefault("EM_CONFIG", "/opt/emsdk/.emscripten")) # 3.1.16 has broken utime() EMSDK_MIN_VERSION = (3, 1, 17) +EMSDK_BROKEN_VERSION = { + (3, 1, 14): "https://github.com/emscripten-core/emscripten/issues/17338", + (3, 1, 16): "https://github.com/emscripten-core/emscripten/issues/17393", + (3, 1, 20): "https://github.com/emscripten-core/emscripten/issues/17720", +} _MISSING = pathlib.PurePath("MISSING") # WASM_WEBSERVER = WASMTOOLS / "wasmwebserver.py" @@ -79,24 +87,46 @@ """ -def get_emscripten_root(emconfig: pathlib.Path = EM_CONFIG) -> pathlib.PurePath: - """Parse EM_CONFIG file and lookup EMSCRIPTEN_ROOT +def parse_emconfig( + emconfig: pathlib.Path = EM_CONFIG, +) -> Tuple[pathlib.PurePath, pathlib.PurePath]: + """Parse EM_CONFIG file and lookup EMSCRIPTEN_ROOT and NODE_JS. The ".emscripten" config file is a Python snippet that uses "EM_CONFIG" environment variable. EMSCRIPTEN_ROOT is the "upstream/emscripten" subdirectory with tools like "emconfigure". """ if not emconfig.exists(): - return _MISSING + return _MISSING, _MISSING with open(emconfig, encoding="utf-8") as f: code = f.read() # EM_CONFIG file is a Python snippet local: Dict[str, Any] = {} exec(code, globals(), local) - return pathlib.Path(local["EMSCRIPTEN_ROOT"]) + emscripten_root = pathlib.Path(local["EMSCRIPTEN_ROOT"]) + node_js = pathlib.Path(local["NODE_JS"]) + return emscripten_root, node_js -EMSCRIPTEN_ROOT = get_emscripten_root() +EMSCRIPTEN_ROOT, NODE_JS = parse_emconfig() + + +def read_python_version(configure: pathlib.Path = CONFIGURE) -> str: + """Read PACKAGE_VERSION from configure script + + configure and configure.ac are the canonical source for major and + minor version number. + """ + version_re = re.compile("^PACKAGE_VERSION='(\d\.\d+)'") + with configure.open(encoding="utf-8") as f: + for line in f: + mo = version_re.match(line) + if mo: + return mo.group(1) + raise ValueError(f"PACKAGE_VERSION not found in {configure}") + + +PYTHON_VERSION = read_python_version() class ConditionError(ValueError): @@ -134,6 +164,9 @@ class Platform: make_wrapper: Optional[pathlib.PurePath] environ: dict check: Callable[[], None] + # Used for build_emports(). + ports: Optional[pathlib.PurePath] + cc: Optional[pathlib.PurePath] def getenv(self, profile: "BuildProfile") -> dict: return self.environ.copy() @@ -155,6 +188,8 @@ def _check_clean_src(): pythonexe=sysconfig.get_config_var("BUILDPYTHON") or "python", config_site=None, configure_wrapper=None, + ports=None, + cc=None, make_wrapper=None, environ={}, check=_check_clean_src, @@ -174,14 +209,31 @@ def _check_emscripten(): raise MissingDependency(os.fspath(version_txt), INSTALL_EMSDK) with open(version_txt) as f: version = f.read().strip().strip('"') + if version.endswith("-git"): + # git / upstream / tot-upstream installation + version = version[:-4] version_tuple = tuple(int(v) for v in version.split(".")) if version_tuple < EMSDK_MIN_VERSION: - raise MissingDependency( + raise ConditionError( os.fspath(version_txt), f"Emscripten SDK {version} in '{EMSCRIPTEN_ROOT}' is older than " "minimum required version " f"{'.'.join(str(v) for v in EMSDK_MIN_VERSION)}.", ) + broken = EMSDK_BROKEN_VERSION.get(version_tuple) + if broken is not None: + raise ConditionError( + os.fspath(version_txt), + ( + f"Emscripten SDK {version} in '{EMSCRIPTEN_ROOT}' has known " + f"bugs, see {broken}." + ), + ) + if os.environ.get("PKG_CONFIG_PATH"): + warnings.warn( + "PKG_CONFIG_PATH is set and not empty. emconfigure overrides " + "this environment variable. Use EM_PKG_CONFIG_PATH instead." + ) _check_clean_src() @@ -190,11 +242,14 @@ def _check_emscripten(): pythonexe="python.js", config_site=WASMTOOLS / "config.site-wasm32-emscripten", configure_wrapper=EMSCRIPTEN_ROOT / "emconfigure", + ports=EMSCRIPTEN_ROOT / "embuilder", + cc=EMSCRIPTEN_ROOT / "emcc", make_wrapper=EMSCRIPTEN_ROOT / "emmake", environ={ # workaround for https://github.com/emscripten-core/emscripten/issues/17635 "TZ": "UTC", "EM_COMPILER_WRAPPER": "ccache" if HAS_CCACHE else None, + "PATH": [EMSCRIPTEN_ROOT, os.environ["PATH"]], }, check=_check_emscripten, ) @@ -215,15 +270,18 @@ def _check_wasi(): pythonexe="python.wasm", config_site=WASMTOOLS / "config.site-wasm32-wasi", configure_wrapper=WASMTOOLS / "wasi-env", + ports=None, + cc=WASI_SDK_PATH / "bin" / "clang", make_wrapper=None, environ={ "WASI_SDK_PATH": WASI_SDK_PATH, # workaround for https://github.com/python/cpython/issues/95952 "HOSTRUNNER": ( "wasmtime run " - "--env PYTHONPATH=/{relbuilddir}/build/lib.wasi-wasm32-$(VERSION):/Lib " + "--env PYTHONPATH=/{relbuilddir}/build/lib.wasi-wasm32-{version}:/Lib " "--mapdir /::{srcdir} --" ), + "PATH": [WASI_SDK_PATH / "bin", os.environ["PATH"]], }, check=_check_wasi, ) @@ -258,6 +316,42 @@ def is_wasi(self) -> bool: cls = type(self) return self in {cls.wasm32_wasi, cls.wasm64_wasi} + def get_extra_paths(self) -> Iterable[pathlib.PurePath]: + """Host-specific os.environ["PATH"] entries. + + Emscripten's Node version 14.x works well for wasm32-emscripten. + wasm64-emscripten requires more recent v8 version, e.g. node 16.x. + Attempt to use system's node command. + """ + cls = type(self) + if self == cls.wasm32_emscripten: + return [NODE_JS.parent] + elif self == cls.wasm64_emscripten: + # TODO: look for recent node + return [] + else: + return [] + + @property + def emport_args(self) -> List[str]: + """Host-specific port args (Emscripten).""" + cls = type(self) + if self is cls.wasm64_emscripten: + return ["-sMEMORY64=1"] + elif self is cls.wasm32_emscripten: + return ["-sMEMORY64=0"] + else: + return [] + + @property + def embuilder_args(self) -> List[str]: + """Host-specific embuilder args (Emscripten).""" + cls = type(self) + if self is cls.wasm64_emscripten: + return ["--wasm64"] + else: + return [] + class EmscriptenTarget(enum.Enum): """Emscripten-specific targets (--with-emscripten-target)""" @@ -272,10 +366,32 @@ def can_execute(self) -> bool: cls = type(self) return self not in {cls.browser, cls.browser_debug} + @property + def emport_args(self) -> List[str]: + """Target-specific port args.""" + cls = type(self) + if self in {cls.browser_debug, cls.node_debug}: + # some libs come in debug and non-debug builds + return ["-O0"] + else: + return ["-O2"] + + +class SupportLevel(enum.Enum): + supported = "tier 3, supported" + working = "working, unsupported" + experimental = "experimental, may be broken" + broken = "broken / unavailable" + + def __bool__(self): + cls = type(self) + return self in {cls.supported, cls.working} + @dataclasses.dataclass class BuildProfile: name: str + support_level: SupportLevel host: Host target: Union[EmscriptenTarget, None] = None dynamic_linking: Union[bool, None] = None @@ -358,21 +474,35 @@ def getenv(self) -> dict: for key, value in platenv.items(): if value is None: env.pop(key, None) + elif key == "PATH": + # list of path items, prefix with extra paths + new_path: List[pathlib.PurePath] = [] + new_path.extend(self.host.get_extra_paths()) + new_path.extend(value) + env[key] = os.pathsep.join(os.fspath(p) for p in new_path) elif isinstance(value, str): env[key] = value.format( relbuilddir=self.builddir.relative_to(SRCDIR), srcdir=SRCDIR, + version=PYTHON_VERSION, ) else: env[key] = value return env - def _run_cmd(self, cmd: Iterable[str], args: Iterable[str]): + def _run_cmd( + self, + cmd: Iterable[str], + args: Iterable[str] = (), + cwd: Optional[pathlib.Path] = None, + ): cmd = list(cmd) cmd.extend(args) + if cwd is None: + cwd = self.builddir return subprocess.check_call( cmd, - cwd=os.fspath(self.builddir), + cwd=os.fspath(cwd), env=self.getenv(), ) @@ -420,10 +550,58 @@ def clean(self, all: bool = False): elif self.makefile.exists(): self.run_make("clean") + def build_emports(self, force: bool = False): + """Pre-build emscripten ports.""" + platform = self.host.platform + if platform.ports is None or platform.cc is None: + raise ValueError("Need ports and CC command") + + embuilder_cmd = [os.fspath(platform.ports)] + embuilder_cmd.extend(self.host.embuilder_args) + if force: + embuilder_cmd.append("--force") + + ports_cmd = [os.fspath(platform.cc)] + ports_cmd.extend(self.host.emport_args) + if self.target: + ports_cmd.extend(self.target.emport_args) + + if self.dynamic_linking: + # Trigger PIC build. + ports_cmd.append("-sMAIN_MODULE") + embuilder_cmd.append("--pic") + if self.pthreads: + # Trigger multi-threaded build. + ports_cmd.append("-sUSE_PTHREADS") + # https://github.com/emscripten-core/emscripten/pull/17729 + # embuilder_cmd.append("--pthreads") + + # Pre-build libbz2, libsqlite3, libz, and some system libs. + ports_cmd.extend(["-sUSE_ZLIB", "-sUSE_BZIP2", "-sUSE_SQLITE3"]) + embuilder_cmd.extend(["build", "bzip2", "sqlite3", "zlib"]) + + if not self.pthreads: + # Emscripten <= 3.1.20 has no option to build multi-threaded ports. + self._run_cmd(embuilder_cmd, cwd=SRCDIR) + + with tempfile.TemporaryDirectory(suffix="-py-emport") as tmpdir: + tmppath = pathlib.Path(tmpdir) + main_c = tmppath / "main.c" + main_js = tmppath / "main.js" + with main_c.open("w") as f: + f.write("int main(void) { return 0; }\n") + args = [ + os.fspath(main_c), + "-o", + os.fspath(main_js), + ] + self._run_cmd(ports_cmd, args, cwd=tmppath) + # native build (build Python) BUILD = BuildProfile( "build", + support_level=SupportLevel.working, host=Host.build, ) @@ -432,43 +610,59 @@ def clean(self, all: bool = False): # wasm32-emscripten BuildProfile( "emscripten-browser", + support_level=SupportLevel.supported, host=Host.wasm32_emscripten, target=EmscriptenTarget.browser, dynamic_linking=True, ), BuildProfile( "emscripten-browser-debug", + support_level=SupportLevel.working, host=Host.wasm32_emscripten, target=EmscriptenTarget.browser_debug, dynamic_linking=True, ), BuildProfile( "emscripten-node-dl", + support_level=SupportLevel.supported, host=Host.wasm32_emscripten, target=EmscriptenTarget.node, dynamic_linking=True, ), BuildProfile( "emscripten-node-dl-debug", + support_level=SupportLevel.working, host=Host.wasm32_emscripten, target=EmscriptenTarget.node_debug, dynamic_linking=True, ), BuildProfile( "emscripten-node-pthreads", + support_level=SupportLevel.supported, host=Host.wasm32_emscripten, target=EmscriptenTarget.node, pthreads=True, ), BuildProfile( "emscripten-node-pthreads-debug", + support_level=SupportLevel.working, host=Host.wasm32_emscripten, target=EmscriptenTarget.node_debug, pthreads=True, ), - # wasm64-emscripten (currently not working) + # Emscripten build with both pthreads and dynamic linking is crashing. + BuildProfile( + "emscripten-node-dl-pthreads-debug", + support_level=SupportLevel.broken, + host=Host.wasm32_emscripten, + target=EmscriptenTarget.node_debug, + dynamic_linking=True, + pthreads=True, + ), + # wasm64-emscripten (requires unreleased Emscripten >= 3.1.21) BuildProfile( "wasm64-emscripten-node-debug", + support_level=SupportLevel.experimental, host=Host.wasm64_emscripten, target=EmscriptenTarget.node_debug, # MEMORY64 is not compatible with dynamic linking @@ -478,6 +672,7 @@ def clean(self, all: bool = False): # wasm32-wasi BuildProfile( "wasi", + support_level=SupportLevel.supported, host=Host.wasm32_wasi, # skip sysconfig test_srcdir testopts="-i '*.test_srcdir' -j2", @@ -485,6 +680,7 @@ def clean(self, all: bool = False): # no SDK available yet # BuildProfile( # "wasm64-wasi", + # support_level=SupportLevel.broken, # host=Host.wasm64_wasi, # ), ] @@ -500,15 +696,17 @@ def clean(self, all: bool = False): "--clean", "-c", help="Clean build directories first", action="store_true" ) -platforms = list(PROFILES) + ["cleanall"] +# Don't list broken and experimental variants in help +platforms_choices = list(p.name for p in _profiles) + ["cleanall"] +platforms_help = list(p.name for p in _profiles if p.support_level) + ["cleanall"] parser.add_argument( "platform", metavar="PLATFORM", - help=f"Build platform: {', '.join(platforms)}", - choices=platforms, + help=f"Build platform: {', '.join(platforms_help)}", + choices=platforms_choices, ) -ops = ["compile", "pythoninfo", "test", "repl", "clean", "cleanall"] +ops = ["compile", "pythoninfo", "test", "repl", "clean", "cleanall", "emports"] parser.add_argument( "op", metavar="OP", @@ -549,6 +747,8 @@ def main(): builder.clean(all=False) if args.op == "compile": + if builder.host.is_emscripten: + builder.build_emports() builder.run_build(force_configure=True) else: if not builder.makefile.exists(): @@ -563,6 +763,8 @@ def main(): builder.clean(all=False) elif args.op == "cleanall": builder.clean(all=True) + elif args.op == "emports": + builder.build_emports(force=args.clean) else: raise ValueError(args.op) diff --git a/configure b/configure index 82b55a3745d5751..9522977c8c70641 100755 --- a/configure +++ b/configure @@ -2,7 +2,7 @@ # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for python 3.12. # -# Report bugs to . +# Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -267,10 +267,10 @@ fi $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: https://bugs.python.org/ about your system, including -$0: any error possibly output before this message. Then -$0: install a modern shell, or manually run the script -$0: under such a shell if you do have one." +$0: https://github.com/python/cpython/issues/ about your +$0: system, including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." fi exit 1 fi @@ -582,7 +582,7 @@ PACKAGE_NAME='python' PACKAGE_TARNAME='python' PACKAGE_VERSION='3.12' PACKAGE_STRING='python 3.12' -PACKAGE_BUGREPORT='https://bugs.python.org/' +PACKAGE_BUGREPORT='https://github.com/python/cpython/issues/' PACKAGE_URL='' ac_unique_file="Include/object.h" @@ -861,6 +861,7 @@ LIBEXPAT_CFLAGS TZPATH LIBUUID_LIBS LIBUUID_CFLAGS +PERF_TRAMPOLINE_OBJ SHLIBS CFLAGSFORSHARED LINKFORSHARED @@ -869,6 +870,8 @@ BLDSHARED LDCXXSHARED LDSHARED SHLIB_SUFFIX +DSYMUTIL_PATH +DSYMUTIL LIBTOOL_CRUFT OTHER_LIBTOOL_OPT UNIVERSAL_ARCH_FLAGS @@ -887,6 +890,9 @@ LLVM_PROF_FILE LLVM_PROF_MERGER PGO_PROF_USE_FLAG PGO_PROF_GEN_FLAG +MERGE_FDATA +LLVM_BOLT +PREBOLT_RULE LLVM_AR_FOUND LLVM_AR PROFILE_TASK @@ -1049,6 +1055,8 @@ enable_pystats with_assertions enable_optimizations with_lto +enable_bolt +with_dsymutil with_address_sanitizer with_memory_sanitizer with_undefined_behavior_sanitizer @@ -1774,6 +1782,8 @@ Optional Features: --enable-pystats enable internal statistics gathering (default is no) --enable-optimizations enable expensive, stable optimizations (PGO, etc.) (default is no) + --enable-bolt enable usage of the llvm-bolt post-link optimizer + (default is no) --enable-loadable-sqlite-extensions support loadable extensions in the sqlite3 module, see Doc/library/sqlite3.rst (default is no) @@ -1818,6 +1828,8 @@ Optional Packages: --with-lto=[full|thin|no|yes] enable Link-Time-Optimization in any build (default is no) + --with-dsymutil link debug information into final executable with + dsymutil in macOS (default is no) --with-address-sanitizer enable AddressSanitizer memory error detector, 'asan' (default is no) @@ -1960,7 +1972,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . _ACEOF ac_status=$? fi @@ -2182,9 +2194,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## --------------------------------------- ## -## Report this to https://bugs.python.org/ ## -## --------------------------------------- ##" +( $as_echo "## -------------------------------------------------------- ## +## Report this to https://github.com/python/cpython/issues/ ## +## -------------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac @@ -7032,7 +7044,7 @@ $as_echo "$LDLIBRARY" >&6; } # LIBRARY_DEPS, LINK_PYTHON_OBJS and LINK_PYTHON_DEPS variable case $ac_sys_system/$ac_sys_emscripten_target in #( Emscripten/browser*) : - LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB)' ;; #( + LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB) python.html python.worker.js' ;; #( *) : LIBRARY_DEPS='$(PY3LIBRARY) $(EXPORTSYMS)' ;; @@ -7825,10 +7837,10 @@ $as_echo "$as_me: llvm-ar found via xcrun: ${LLVM_AR}" >&6;} # Any changes made here should be reflected in the GCC+Darwin case below if test $Py_LTO_POLICY = default then - LTOFLAGS="-flto -Wl,-export_dynamic" + LTOFLAGS="-flto -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto" else - LTOFLAGS="-flto=${Py_LTO_POLICY} -Wl,-export_dynamic" + LTOFLAGS="-flto=${Py_LTO_POLICY} -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto=${Py_LTO_POLICY}" fi ;; @@ -7857,7 +7869,7 @@ $as_echo "$as_me: llvm-ar found via xcrun: ${LLVM_AR}" >&6;} LDFLAGS_NOLTO="-fno-lto" case $ac_sys_system in Darwin*) - LTOFLAGS="-flto -Wl,-export_dynamic" + LTOFLAGS="-flto -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto" ;; *) @@ -7878,6 +7890,261 @@ $as_echo "$as_me: llvm-ar found via xcrun: ${LLVM_AR}" >&6;} LDFLAGS_NODIST="$LDFLAGS_NODIST $LTOFLAGS" fi +# Enable bolt flags +Py_BOLT='false' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-bolt" >&5 +$as_echo_n "checking for --enable-bolt... " >&6; } +# Check whether --enable-bolt was given. +if test "${enable_bolt+set}" = set; then : + enableval=$enable_bolt; +if test "$enableval" != no +then + Py_BOLT='true' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; +else + Py_BOLT='false' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; +fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +if test "$Py_BOLT" = 'true' ; then + PREBOLT_RULE="${DEF_MAKE_ALL_RULE}" + DEF_MAKE_ALL_RULE="bolt-opt" + DEF_MAKE_RULE="build_all" + + # These flags are required for bolt to work: + CFLAGS_NODIST="$CFLAGS_NODIST -fno-reorder-blocks-and-partition" + LDFLAGS_NODIST="$LDFLAGS_NODIST -Wl,--emit-relocs" + + # These flags are required to get good performance from bolt: + CFLAGS_NODIST="$CFLAGS_NODIST -fno-pie" + # We want to add these no-pie flags to linking executables but not shared libraries: + LINKCC="$LINKCC -fno-pie -no-pie" + # Designate the DWARF version into 4 since the LLVM-BOLT does not support DWARF5 yet. + CFLAGS="$CFLAGS -gdwarf-4" + LDFLAGS="$LDFLAGS -gdwarf-4" + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}llvm-bolt", so it can be a program name with args. +set dummy ${ac_tool_prefix}llvm-bolt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LLVM_BOLT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LLVM_BOLT in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVM_BOLT="$LLVM_BOLT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in ${llvm_path} +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LLVM_BOLT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +LLVM_BOLT=$ac_cv_path_LLVM_BOLT +if test -n "$LLVM_BOLT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_BOLT" >&5 +$as_echo "$LLVM_BOLT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_LLVM_BOLT"; then + ac_pt_LLVM_BOLT=$LLVM_BOLT + # Extract the first word of "llvm-bolt", so it can be a program name with args. +set dummy llvm-bolt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_LLVM_BOLT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_LLVM_BOLT in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_LLVM_BOLT="$ac_pt_LLVM_BOLT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in ${llvm_path} +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_LLVM_BOLT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_LLVM_BOLT=$ac_cv_path_ac_pt_LLVM_BOLT +if test -n "$ac_pt_LLVM_BOLT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LLVM_BOLT" >&5 +$as_echo "$ac_pt_LLVM_BOLT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_LLVM_BOLT" = x; then + LLVM_BOLT="''" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LLVM_BOLT=$ac_pt_LLVM_BOLT + fi +else + LLVM_BOLT="$ac_cv_path_LLVM_BOLT" +fi + + if test -n "${LLVM_BOLT}" -a -x "${LLVM_BOLT}" + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"Found llvm-bolt\"" >&5 +$as_echo "\"Found llvm-bolt\"" >&6; } + else + as_fn_error $? "llvm-bolt is required for a --enable-bolt build but could not be found." "$LINENO" 5 + fi + + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}merge-fdata", so it can be a program name with args. +set dummy ${ac_tool_prefix}merge-fdata; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MERGE_FDATA+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MERGE_FDATA in + [\\/]* | ?:[\\/]*) + ac_cv_path_MERGE_FDATA="$MERGE_FDATA" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in ${llvm_path} +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MERGE_FDATA="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MERGE_FDATA=$ac_cv_path_MERGE_FDATA +if test -n "$MERGE_FDATA"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MERGE_FDATA" >&5 +$as_echo "$MERGE_FDATA" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_MERGE_FDATA"; then + ac_pt_MERGE_FDATA=$MERGE_FDATA + # Extract the first word of "merge-fdata", so it can be a program name with args. +set dummy merge-fdata; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_MERGE_FDATA+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_MERGE_FDATA in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_MERGE_FDATA="$ac_pt_MERGE_FDATA" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in ${llvm_path} +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_MERGE_FDATA="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_MERGE_FDATA=$ac_cv_path_ac_pt_MERGE_FDATA +if test -n "$ac_pt_MERGE_FDATA"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_MERGE_FDATA" >&5 +$as_echo "$ac_pt_MERGE_FDATA" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_MERGE_FDATA" = x; then + MERGE_FDATA="''" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MERGE_FDATA=$ac_pt_MERGE_FDATA + fi +else + MERGE_FDATA="$ac_cv_path_MERGE_FDATA" +fi + + if test -n "${MERGE_FDATA}" -a -x "${MERGE_FDATA}" + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"Found merge-fdata\"" >&5 +$as_echo "\"Found merge-fdata\"" >&6; } + else + as_fn_error $? "merge-fdata is required for a --enable-bolt build but could not be found." "$LINENO" 5 + fi +fi + # Enable PGO flags. @@ -10713,6 +10980,81 @@ else $as_echo "no" >&6; } fi +# Check for --with-dsymutil + + +DSYMUTIL= +DSYMUTIL_PATH= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dsymutil" >&5 +$as_echo_n "checking for --with-dsymutil... " >&6; } + +# Check whether --with-dsymutil was given. +if test "${with_dsymutil+set}" = set; then : + withval=$with_dsymutil; +if test "$withval" != no +then + if test "$MACHDEP" != "darwin"; then + as_fn_error $? "dsymutil debug linking is only available in macOS." "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; + DSYMUTIL='true' +else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; DSYMUTIL= +fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "$DSYMUTIL"; then + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DSYMUTIL_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DSYMUTIL_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_DSYMUTIL_PATH="$DSYMUTIL_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DSYMUTIL_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DSYMUTIL_PATH" && ac_cv_path_DSYMUTIL_PATH="not found" + ;; +esac +fi +DSYMUTIL_PATH=$ac_cv_path_DSYMUTIL_PATH +if test -n "$DSYMUTIL_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL_PATH" >&5 +$as_echo "$DSYMUTIL_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$DSYMUTIL_PATH" = "not found"; then + as_fn_error $? "dsymutil command not found on \$PATH" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dyld" >&5 $as_echo_n "checking for dyld... " >&6; } case $ac_sys_system/$ac_sys_release in @@ -11157,6 +11499,35 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHLIBS" >&5 $as_echo "$SHLIBS" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking perf trampoline" >&5 +$as_echo_n "checking perf trampoline... " >&6; } +case $PLATFORM_TRIPLET in #( + x86_64-linux-gnu) : + perf_trampoline=yes ;; #( + aarch64-linux-gnu) : + perf_trampoline=yes ;; #( + *) : + perf_trampoline=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $perf_trampoline" >&5 +$as_echo "$perf_trampoline" >&6; } + +if test "x$perf_trampoline" = xyes; then : + + +$as_echo "#define PY_HAVE_PERF_TRAMPOLINE 1" >>confdefs.h + + PERF_TRAMPOLINE_OBJ=Objects/asm_trampoline.o + + if test "x$Py_DEBUG" = xtrue; then : + + as_fn_append BASECFLAGS " -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" + +fi + +fi + # checks for libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sendfile in -lsendfile" >&5 @@ -20504,7 +20875,7 @@ fi # rounding issues. The result of this test has little meaning on non # IEEE 754 platforms. On IEEE 754, test should return 1 if rounding # mode is round-to-nearest and double rounding issues are present, and -# 0 otherwise. See http://bugs.python.org/issue2937 for more info. +# 0 otherwise. See https://github.com/python/cpython/issues/47186 for more info. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x87-style double rounding" >&5 $as_echo_n "checking for x87-style double rounding... " >&6; } if ${ac_cv_x87_double_rounding+:} false; then : @@ -28572,7 +28943,7 @@ $config_files Configuration headers: $config_headers -Report bugs to ." +Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 diff --git a/configure.ac b/configure.ac index 85d9e8011835edb..3a009bb5042a94c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl *************************************************** dnl * Please run autoreconf -if to test your changes! * dnl *************************************************** dnl -dnl Python's configure script requires autoconf 2.69 and autoconf-archive. +dnl Python's configure.ac file requires autoconf 2.69 and autoconf-archive. dnl # Set VERSION so we only need to edit in one place (i.e., here) @@ -10,7 +10,7 @@ m4_define(PYTHON_VERSION, 3.12) AC_PREREQ([2.69]) -AC_INIT([python],[PYTHON_VERSION],[https://bugs.python.org/]) +AC_INIT([python],[PYTHON_VERSION],[https://github.com/python/cpython/issues/]) m4_ifdef( [AX_C_FLOAT_WORDS_BIGENDIAN], @@ -1581,7 +1581,7 @@ AC_MSG_RESULT($LDLIBRARY) # LIBRARY_DEPS, LINK_PYTHON_OBJS and LINK_PYTHON_DEPS variable AS_CASE([$ac_sys_system/$ac_sys_emscripten_target], - [Emscripten/browser*], [LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB)'], + [Emscripten/browser*], [LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB) python.html python.worker.js'], [LIBRARY_DEPS='$(PY3LIBRARY) $(EXPORTSYMS)'] ) LINK_PYTHON_DEPS='$(LIBRARY_DEPS)' @@ -1863,10 +1863,10 @@ if test "$Py_LTO" = 'true' ; then # Any changes made here should be reflected in the GCC+Darwin case below if test $Py_LTO_POLICY = default then - LTOFLAGS="-flto -Wl,-export_dynamic" + LTOFLAGS="-flto -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto" else - LTOFLAGS="-flto=${Py_LTO_POLICY} -Wl,-export_dynamic" + LTOFLAGS="-flto=${Py_LTO_POLICY} -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto=${Py_LTO_POLICY}" fi ;; @@ -1896,7 +1896,7 @@ if test "$Py_LTO" = 'true' ; then LDFLAGS_NOLTO="-fno-lto" case $ac_sys_system in Darwin*) - LTOFLAGS="-flto -Wl,-export_dynamic" + LTOFLAGS="-flto -Wl,-export_dynamic -Wl,-object_path_lto,\"\$@\".lto" LTOCFLAGS="-flto" ;; *) @@ -1917,6 +1917,59 @@ if test "$Py_LTO" = 'true' ; then LDFLAGS_NODIST="$LDFLAGS_NODIST $LTOFLAGS" fi +# Enable bolt flags +Py_BOLT='false' +AC_MSG_CHECKING(for --enable-bolt) +AC_ARG_ENABLE(bolt, AS_HELP_STRING( + [--enable-bolt], + [enable usage of the llvm-bolt post-link optimizer (default is no)]), +[ +if test "$enableval" != no +then + Py_BOLT='true' + AC_MSG_RESULT(yes); +else + Py_BOLT='false' + AC_MSG_RESULT(no); +fi], +[AC_MSG_RESULT(no)]) + +AC_SUBST(PREBOLT_RULE) +if test "$Py_BOLT" = 'true' ; then + PREBOLT_RULE="${DEF_MAKE_ALL_RULE}" + DEF_MAKE_ALL_RULE="bolt-opt" + DEF_MAKE_RULE="build_all" + + # These flags are required for bolt to work: + CFLAGS_NODIST="$CFLAGS_NODIST -fno-reorder-blocks-and-partition" + LDFLAGS_NODIST="$LDFLAGS_NODIST -Wl,--emit-relocs" + + # These flags are required to get good performance from bolt: + CFLAGS_NODIST="$CFLAGS_NODIST -fno-pie" + # We want to add these no-pie flags to linking executables but not shared libraries: + LINKCC="$LINKCC -fno-pie -no-pie" + # Designate the DWARF version into 4 since the LLVM-BOLT does not support DWARF5 yet. + CFLAGS="$CFLAGS -gdwarf-4" + LDFLAGS="$LDFLAGS -gdwarf-4" + AC_SUBST(LLVM_BOLT) + AC_PATH_TOOL(LLVM_BOLT, llvm-bolt, '', ${llvm_path}) + if test -n "${LLVM_BOLT}" -a -x "${LLVM_BOLT}" + then + AC_MSG_RESULT("Found llvm-bolt") + else + AC_MSG_ERROR([llvm-bolt is required for a --enable-bolt build but could not be found.]) + fi + + AC_SUBST(MERGE_FDATA) + AC_PATH_TOOL(MERGE_FDATA, merge-fdata, '', ${llvm_path}) + if test -n "${MERGE_FDATA}" -a -x "${MERGE_FDATA}" + then + AC_MSG_RESULT("Found merge-fdata") + else + AC_MSG_ERROR([merge-fdata is required for a --enable-bolt build but could not be found.]) + fi +fi + # Enable PGO flags. AC_SUBST(PGO_PROF_GEN_FLAG) AC_SUBST(PGO_PROF_USE_FLAG) @@ -3000,6 +3053,33 @@ else AC_MSG_RESULT(no) fi +# Check for --with-dsymutil +AC_SUBST(DSYMUTIL) +AC_SUBST(DSYMUTIL_PATH) +DSYMUTIL= +DSYMUTIL_PATH= +AC_MSG_CHECKING(for --with-dsymutil) +AC_ARG_WITH(dsymutil, + AS_HELP_STRING([--with-dsymutil], [link debug information into final executable with dsymutil in macOS (default is no)]), +[ +if test "$withval" != no +then + if test "$MACHDEP" != "darwin"; then + AC_MSG_ERROR([dsymutil debug linking is only available in macOS.]) + fi + AC_MSG_RESULT(yes); + DSYMUTIL='true' +else AC_MSG_RESULT(no); DSYMUTIL= +fi], +[AC_MSG_RESULT(no)]) + +if test "$DSYMUTIL"; then + AC_PATH_PROG(DSYMUTIL_PATH, [dsymutil], [not found]) + if test "$DSYMUTIL_PATH" = "not found"; then + AC_MSG_ERROR([dsymutil command not found on \$PATH]) + fi +fi + AC_MSG_CHECKING(for dyld) case $ac_sys_system/$ac_sys_release in Darwin/*) @@ -3372,6 +3452,26 @@ case "$ac_sys_system" in esac AC_MSG_RESULT($SHLIBS) +dnl perf trampoline is Linux specific and requires an arch-specific +dnl trampoline in asssembly. +AC_MSG_CHECKING([perf trampoline]) +AS_CASE([$PLATFORM_TRIPLET], + [x86_64-linux-gnu], [perf_trampoline=yes], + [aarch64-linux-gnu], [perf_trampoline=yes], + [perf_trampoline=no] +) +AC_MSG_RESULT([$perf_trampoline]) + +AS_VAR_IF([perf_trampoline], [yes], [ + AC_DEFINE([PY_HAVE_PERF_TRAMPOLINE], [1], [Define to 1 if you have the perf trampoline.]) + PERF_TRAMPOLINE_OBJ=Objects/asm_trampoline.o + + dnl perf needs frame pointers for unwinding, include compiler option in debug builds + AS_VAR_IF([Py_DEBUG], [true], [ + AS_VAR_APPEND([BASECFLAGS], [" -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"]) + ]) +]) +AC_SUBST([PERF_TRAMPOLINE_OBJ]) # checks for libraries AC_CHECK_LIB(sendfile, sendfile) @@ -5502,7 +5602,7 @@ AS_VAR_IF([ac_cv_gcc_asm_for_mc68881], [yes], [ # rounding issues. The result of this test has little meaning on non # IEEE 754 platforms. On IEEE 754, test should return 1 if rounding # mode is round-to-nearest and double rounding issues are present, and -# 0 otherwise. See http://bugs.python.org/issue2937 for more info. +# 0 otherwise. See https://github.com/python/cpython/issues/47186 for more info. AC_CACHE_CHECK([for x87-style double rounding], [ac_cv_x87_double_rounding], [ # $BASECFLAGS may affect the result ac_save_cc="$CC" @@ -6229,7 +6329,7 @@ dnl TODO: detect "curses" and special cases tinfo, terminfo, or termcap AC_MSG_CHECKING([curses module flags]) AS_VAR_IF([have_curses], [no], [ - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([$have_curses (CFLAGS: $CURSES_CFLAGS, LIBS: $CURSES_LIBS)]) ]) @@ -6277,7 +6377,7 @@ PANEL_CFLAGS=$(echo $PANEL_CFLAGS | sed 's/-D_XOPEN_SOURCE=600//g') AC_MSG_CHECKING([panel flags]) AS_VAR_IF([have_panel], [no], [ - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([$have_panel (CFLAGS: $PANEL_CFLAGS, LIBS: $PANEL_LIBS)]) ]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 10e7ad12fa982c2..1ce09855f5559d9 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1568,6 +1568,9 @@ /* Define if you want to coerce the C locale to a UTF-8 based locale */ #undef PY_COERCE_C_LOCALE +/* Define to 1 if you have the perf trampoline. */ +#undef PY_HAVE_PERF_TRAMPOLINE + /* Define to 1 to build the sqlite module with loadable extensions support. */ #undef PY_SQLITE_ENABLE_LOAD_EXTENSION